A production-ready iPhone-like expense tracker web app built with Next.js 14, Tailwind CSS, and Supabase.
Last updated: January 2025
- π¨ Native iOS Feel - Designed to feel like a native iPhone app when added to Home Screen
- π Username-Only Auth - Simple username authentication, no passwords or email verification
- β‘ Instant UI Feedback - Optimistic updates and skeleton loaders
- π Zero Full Page Reloads - Smooth client-side navigation
- π± Bottom Tab Navigation - iOS-style navigation bar
- π Offline-First - Works offline with service worker caching
- π Dark Mode - Automatic dark mode support
- π Smart Analytics - Daily/monthly totals and category breakdowns
- Next.js 14 (App Router)
- Tailwind CSS (iOS-style design system)
- Supabase (Database + Authentication)
- TypeScript
- PWA (Progressive Web App)
- Node.js 18+ and npm/yarn
- A Supabase account and project
- Clone and install dependencies:
npm install-
Set up Supabase:
- Create a new project at supabase.com
- Go to SQL Editor and run the SQL from
supabase/schema.sql - Copy your project URL and anon key
-
Configure environment variables:
cp .env.example .env.localEdit .env.local and add your Supabase credentials:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
- Run the development server:
npm run devOpen http://localhost:3000 in your browser.
- id: UUID (primary key, references auth.users)
- username: VARCHAR(50) (unique)
- created_at: TIMESTAMP
- updated_at: TIMESTAMP- id: UUID (primary key)
- user_id: UUID (foreign key to auth.users)
- amount: DECIMAL(10, 2)
- category: VARCHAR(50)
- note: TEXT (optional)
- date: DATE
- created_at: TIMESTAMP
- updated_at: TIMESTAMPAll expenses are protected by RLS policies:
- Users can only view their own expenses
- Users can only insert/update/delete their own expenses
- All policies use
auth.uid() = user_idfor security
- User enters a username (3-20 characters, alphanumeric + underscore)
- System checks if username is available
- If available: Creates anonymous Supabase session + profile with username
- If taken: Shows error message
- User redirected to home
- Username is stored and displayed throughout the app
The app is configured as a PWA with:
manifest.jsonfor iOS Home Screen installation- Service worker for offline caching
- iOS-specific meta tags
- Safe area insets support
- Open the app in Safari
- Tap the Share button
- Select "Add to Home Screen"
- The app will launch in standalone mode
- Code Splitting - Automatic with Next.js App Router
- Optimistic Updates - Instant UI feedback
- Skeleton Loaders - Smooth loading states
- Service Worker - Offline caching
- Image Optimization - Next.js Image component
- Bundle Optimization - Tree-shaking and minification
- Push to GitHub:
git init
git add .
git commit -m "Initial commit"
git remote add origin your-repo-url
git push -u origin main-
Deploy on Vercel:
- Go to vercel.com
- Import your GitHub repository
- Add environment variables:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
- Deploy!
-
Update Supabase Redirect URLs:
- Go to Supabase Dashboard β Authentication β URL Configuration
- Add your Vercel URL to "Redirect URLs"
- Add
https://your-app.vercel.app/auth/callbackto allowed redirect URLs
- Disabled Bounce/Zoom - Via CSS and viewport meta tags
- Safe Area Support - Uses
env(safe-area-inset-*)for notched devices - Haptic Feedback - Uses Web Vibration API
- Native Transitions - Smooth page transitions
- Standalone Mode - Full-screen PWA experience
βββ app/
β βββ components/ # Reusable components
β βββ utils/ # Utility functions
β βββ auth/ # Authentication pages
β βββ add/ # Add expense page
β βββ stats/ # Statistics page
β βββ settings/ # Settings page
β βββ layout.tsx # Root layout
β βββ page.tsx # Home page
β βββ globals.css # Global styles
βββ public/ # Static assets
βββ supabase/ # Database schema
βββ package.json # Dependencies
The app is optimized for:
- Performance > 95
- Accessibility > 95
- Best Practices > 95
- SEO > 95
MIT