Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions apps/admin/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Backpack } from 'lucide-react';
import Link from 'next/link';

export default function NotFound() {
return (
<div className="min-h-screen flex items-center justify-center bg-background">
<div className="text-center px-4">
<div className="flex justify-center mb-6">
<div className="bg-primary/10 rounded-full p-6 inline-flex">
<Backpack className="w-12 h-12 text-primary" />
</div>
</div>
<h1 className="text-8xl font-extrabold text-foreground mb-2 leading-none">404</h1>
<p className="text-xl font-semibold text-foreground mb-2">Page not found</p>
<p className="text-muted-foreground max-w-xs mx-auto mb-8">
This admin page doesn&apos;t exist. Head back to the dashboard.
</p>
<Link
href="/dashboard"
className="inline-flex items-center justify-center rounded-lg bg-primary px-6 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 transition-colors"
>
Back to dashboard
</Link>
</div>
</div>
);
}
62 changes: 62 additions & 0 deletions apps/admin/pages/404.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Backpack } from 'lucide-react';

export default function Custom404() {
return (
<div
Comment on lines +1 to +5
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This app now has both App Router (app/not-found.tsx) and a Pages Router pages/404.tsx. In this repo, pages/404.tsx is used in some apps specifically as a static export workaround (overriding Next’s internal _error). Consider adding a short file header comment explaining why pages/404.tsx exists here and how it relates to app/not-found.tsx to avoid accidental deletion later.

Copilot uses AI. Check for mistakes.
style={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#0f172a',
fontFamily: 'system-ui, sans-serif',
}}
>
<div style={{ textAlign: 'center', padding: '0 1rem' }}>
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: '1.5rem' }}>
<div
style={{
background: 'rgba(15,118,110,0.15)',
borderRadius: '9999px',
padding: '1.5rem',
display: 'inline-flex',
}}
>
<Backpack size={48} color="#14b8a6" />
</div>
</div>
<h1
style={{
fontSize: '5rem',
fontWeight: 800,
color: '#f8fafc',
margin: '0 0 0.5rem',
lineHeight: 1,
}}
>
404
</h1>
<p style={{ fontSize: '1.25rem', fontWeight: 600, color: '#f8fafc', margin: '0 0 0.5rem' }}>
Page not found
</p>
<p style={{ color: '#94a3b8', maxWidth: '22rem', margin: '0 auto 2rem' }}>
This admin page doesn&apos;t exist. Head back to the dashboard.
</p>
<a
href="/dashboard"
style={{
background: '#0f766e',
color: '#fff',
padding: '0.625rem 1.5rem',
borderRadius: '0.5rem',
fontWeight: 600,
textDecoration: 'none',
fontSize: '1rem',
}}
>
Back to dashboard
</a>
</div>
</div>
);
}
80 changes: 80 additions & 0 deletions apps/admin/pages/500.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { AlertTriangle } from 'lucide-react';

export default function Custom500() {
return (
<div
Comment on lines +1 to +5
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to pages/404.tsx, pages/500.tsx can look redundant in an App Router app. Consider adding a brief header comment noting if this file is intentionally present for static export / internal _error override behavior (as seen in other apps in this repo), so future refactors don’t remove it unintentionally.

Copilot uses AI. Check for mistakes.
style={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#0f172a',
fontFamily: 'system-ui, sans-serif',
}}
>
<div style={{ textAlign: 'center', padding: '0 1rem' }}>
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: '1.5rem' }}>
<div
style={{
background: 'rgba(239,68,68,0.15)',
borderRadius: '9999px',
padding: '1.5rem',
display: 'inline-flex',
}}
>
<AlertTriangle size={48} color="#ef4444" />
</div>
</div>
<h1
style={{
fontSize: '5rem',
fontWeight: 800,
color: '#f8fafc',
margin: '0 0 0.5rem',
lineHeight: 1,
}}
>
500
</h1>
<p style={{ fontSize: '1.25rem', fontWeight: 600, color: '#f8fafc', margin: '0 0 0.5rem' }}>
Something went wrong
</p>
<p style={{ color: '#94a3b8', maxWidth: '22rem', margin: '0 auto 2rem' }}>
An unexpected error occurred. Try again or contact support if the problem persists.
</p>
<div
style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem', justifyContent: 'center' }}
>
<a
href="/dashboard"
style={{
background: '#0f766e',
color: '#fff',
padding: '0.625rem 1.5rem',
borderRadius: '0.5rem',
fontWeight: 600,
textDecoration: 'none',
fontSize: '1rem',
}}
>
Back to dashboard
</a>
<a
href="mailto:hello@packratai.com"
style={{
border: '1px solid #334155',
color: '#f8fafc',
padding: '0.625rem 1.5rem',
borderRadius: '0.5rem',
fontWeight: 600,
textDecoration: 'none',
fontSize: '1rem',
}}
>
Contact support
</a>
</div>
</div>
</div>
);
}
5 changes: 5 additions & 0 deletions apps/admin/public/_headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
9 changes: 9 additions & 0 deletions apps/admin/wrangler.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://developers.cloudflare.com/schemas/wrangler.json",
"name": "packrat-admin",
"compatibility_date": "2024-09-23",
"assets": {
"directory": "./out",
"not_found_handling": "404-page"
}
}
25 changes: 0 additions & 25 deletions apps/expo/app/(app)/(tabs)/(home)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
import { Icon } from 'expo-app/components/Icon';
import TabScreen from 'expo-app/components/TabScreen';
import { featureFlags } from 'expo-app/config';
import { clientEnvs } from 'expo-app/env/clientEnvs';
import { AIChatTile } from 'expo-app/features/ai/components/AIChatTile';
import { ReportedContentTile } from 'expo-app/features/ai/components/ReportedContentTile';
import { AIPacksTile } from 'expo-app/features/ai-packs/components/AIPacksTile';
Expand All @@ -33,10 +32,8 @@ import { WeatherAlertsTile } from 'expo-app/features/weather/components/WeatherA
import { WeatherTile } from 'expo-app/features/weather/components/WeatherTile';
import { WildlifeTile } from 'expo-app/features/wildlife/components/WildlifeTile';
import { cn } from 'expo-app/lib/cn';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import { asNonNullableRef } from 'expo-app/lib/utils/asNonNullableRef';
import { Link } from 'expo-router';
import { useMemo, useRef, useState } from 'react';
import { FlatList, Platform, Pressable, Text, View } from 'react-native';

Expand Down Expand Up @@ -158,23 +155,6 @@ const tileInfo = {

type TileName = keyof typeof tileInfo;

function DemoIcon() {
const { colors } = useColorScheme();
if (clientEnvs.NODE_ENV !== 'development') return null;

return (
<Link href="/demo" asChild>
<Pressable className="opacity-80">
{({ pressed }) => (
<View className={cn(pressed ? 'opacity-50' : 'opacity-90')}>
<Icon name="tag-outline" color={colors.foreground} />
</View>
)}
</Pressable>
</Link>
);
}

export default function DashboardScreen() {
const [searchValue, setSearchValue] = useState('');
const searchBarRef = useRef<LargeTitleSearchBarMethods>(null);
Expand Down Expand Up @@ -309,11 +289,6 @@ export default function DashboardScreen() {
),
}}
backVisible={false}
rightView={() => (
<View className="flex-row items-center gap-2 pr-2">
<DemoIcon />
</View>
)}
/>

<List
Expand Down
22 changes: 21 additions & 1 deletion apps/expo/app/(app)/(tabs)/profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Icon } from 'expo-app/components/Icon';
import TabScreen from 'expo-app/components/TabScreen';
import { clientEnvs } from 'expo-app/env/clientEnvs';
import { withAuthWall } from 'expo-app/features/auth/hocs';
import { useAuth } from 'expo-app/features/auth/hooks/useAuth';
import { useUser } from 'expo-app/features/auth/hooks/useUser';
Expand Down Expand Up @@ -53,6 +54,23 @@ function SettingsIcon() {
);
}

function DemoIcon() {
const { colors } = useColorScheme();
if (clientEnvs.NODE_ENV !== 'development') return null;

return (
<Link href="/demo" asChild>
<Pressable className="opacity-80">
{({ pressed }) => (
<View className={cn(pressed ? 'opacity-50' : 'opacity-90')}>
<Icon name="tag-outline" color={colors.foreground} />
</View>
)}
</Pressable>
</Link>
);
}

function Profile() {
const user = useUser();
const { t } = useTranslation();
Expand Down Expand Up @@ -94,7 +112,9 @@ function Profile() {
title={t('profile.profile')}
backVisible={false}
rightView={() => (
<View className="flex-row items-center gap-2 pr-2">
<View className="flex-row items-center gap-2 pr-2 pl-2">
<DemoIcon />

<SettingsIcon />
</View>
)}
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/features/packs/screens/PackListScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export function PackListScreen() {
),
}}
rightView={() => (
<View className="flex-row items-center">
<View className="flex-row items-center mr-2 ml-2">
<CreatePackIconButton />
</View>
)}
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/features/trips/screens/TripListScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export function TripsListScreen() {
),
}}
rightView={() => (
<View className="flex-row items-center">
<View className="flex-row items-center mr-2 ml-2">
<CreateTripIconButton />
</View>
)}
Expand Down
7 changes: 5 additions & 2 deletions apps/expo/features/trips/screens/TripWeatherDetailsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,11 @@ export default function TripWeatherDetailsScreen() {

<LinearGradient colors={gradientColors} style={{ flex: 1 }}>
<View className="absolute top-10 left-4 z-10">
<TouchableOpacity onPress={() => router.back()}>
<Icon name="arrow-left" color="white" size={20} />
<TouchableOpacity
onPress={() => router.back()}
hitSlop={{ top: 16, bottom: 16, left: 16, right: 16 }}
>
<Icon name="arrow-left" color="white" size={24} />
</TouchableOpacity>
</View>

Expand Down
24 changes: 14 additions & 10 deletions apps/expo/features/weather/screens/LocationsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,20 +121,24 @@ function LocationsScreen() {
<LargeTitleHeader
title={t('weather.weather')}
leftView={() => (
<Pressable onPress={() => router.back()} className="mr-2">
<Pressable
onPress={() => router.back()}
className="mr-2 ml-1.5 items-center justify-center"
>
<Icon name="arrow-left" color={colors.foreground} size={24} />
</Pressable>
)}
rightView={() => (
<View className="flex-row items-center pr-2">
<Pressable className="opacity-80" onPress={handleAddLocation}>
{({ pressed }) => (
<View className={cn(pressed ? 'opacity-50' : 'opacity-90')}>
<Icon name="plus" color={colors.foreground} />
</View>
)}
</Pressable>
</View>
<Pressable
className="opacity-80 mr-2 ml-2 items-center justify-center"
onPress={handleAddLocation}
>
{({ pressed }) => (
<View className={cn(pressed ? 'opacity-50' : 'opacity-90')}>
<Icon name="plus" color={colors.foreground} />
</View>
)}
</Pressable>
)}
/>

Expand Down
2 changes: 1 addition & 1 deletion apps/guides/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"scripts": {
"build": "bun run build-content && next build",
"build-content": "bun run scripts/build-content.ts",
"clean": "bunx rimraf .next node_modules out .vercel",
"clean": "bunx rimraf .next node_modules out",
"demo-enhancement": "bun run scripts/demo-enhancement.ts",
"dev": "next dev",
"enhance-content": "bun run scripts/enhance-content.ts",
Expand Down
5 changes: 5 additions & 0 deletions apps/guides/public/_headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
9 changes: 9 additions & 0 deletions apps/guides/wrangler.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://developers.cloudflare.com/schemas/wrangler.json",
"name": "packrat-guides",
"compatibility_date": "2024-09-23",
"assets": {
"directory": "./out",
"not_found_handling": "404-page"
}
}
2 changes: 1 addition & 1 deletion apps/landing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"scripts": {
"build": "next build",
"clean": "bunx rimraf node_modules .next out .vercel",
"clean": "bunx rimraf node_modules .next out",
"dev": "next dev",
"lint": "next lint",
"start": "next start"
Expand Down
5 changes: 5 additions & 0 deletions apps/landing/public/_headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Loading
Loading