Full-stack personal finance dashboard with AI-powered insights, receipt scanning, and PWA support.
FinSight is a production-ready personal finance application that helps users track transactions, manage budgets, set financial goals, and understand their spending patterns through AI-powered analysis. Built as a portfolio project demonstrating modern full-stack development with real-world features across the entire stack.
Highlights:
- π€ AI spending analysis powered by Google Gemini 2.5 Flash
- πΈ OCR receipt scanning β photograph a receipt to auto-fill transaction forms
- π― Financial goals tracking with progress visualization
- π± Progressive Web App β installable on mobile and desktop
- π Smart budget alerts with automatic threshold notifications
- π PDF & CSV export with receipt image attachments
Real-time financial overview with summary cards (income, expense, net balance, saving rate), 6-month income vs expense trend chart, category spending breakdown pie chart, budget progress strips, recent transactions, and AI-generated spending insights.
Full CRUD with OCR receipt scanning via Gemini Vision, file attachment support (images/PDF stored in Supabase Storage), full-text search with 300ms debounce, category/date/type filters, recurring transactions (daily/weekly/monthly/yearly), and paginated list.
Per-category monthly spending limits with real-time progress bars, configurable alert thresholds, and automatic toast notifications when a budget is exceeded β deduplicated to one alert per budget per month.
Set savings targets with deadlines, track progress manually, and mark goals as complete. Supports custom icons, colors, and motivational notes per goal.
Queries real transaction data to generate 3 personalized insights per month β spending patterns, budget warnings, and saving tips. Results cached in PostgreSQL to minimize API costs.
Upload or photograph a receipt. Gemini Vision extracts amount, date, merchant, and category to pre-fill the transaction form automatically.
CSV for spreadsheet analysis (includes receipt filename column). PDF with full transaction table, summary section, and a receipt image appendix β each transaction's receipt embedded at actual size.
Email/password and Google OAuth via NextAuth.js. JWT sessions with 30-day persistence. Route protection via Next.js middleware with public path exclusions.
Installable on Android, iOS (Safari), and desktop Chrome. Service worker for offline fallback. Add to Home Screen works across all supported platforms.
| Category | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| Language | TypeScript 5.9 β strict mode |
| Styling | Tailwind CSS v4 |
| Database | PostgreSQL via Supabase |
| ORM | Prisma 7 with @prisma/adapter-pg |
| Auth | NextAuth.js v4 |
| AI | Google Gemini 2.5 Flash (@google/genai) |
| File Storage | Supabase Storage (receipts) |
| Validation | Zod v4 |
| Forms | React Hook Form v7 |
| Charts | Recharts v3 |
| jsPDF + jsPDF-AutoTable | |
| Testing | Vitest (165 tests) |
| CI/CD | GitHub Actions β Vercel |
finsight/
βββ app/
β βββ (auth)/ # Login, Register, Onboarding
β βββ (dashboard)/ # Protected dashboard routes
β β βββ page.tsx # Dashboard overview
β β βββ transactions/ # Transaction management
β β βββ budgets/ # Budget management
β β βββ goals/ # Financial goals
β β βββ analytics/ # Detailed analytics
β β βββ settings/ # User settings
β βββ api/
β β βββ auth/ # NextAuth + registration
β β βββ transactions/ # CRUD + receipt upload API
β β βββ budgets/ # CRUD + alert checking
β β βββ goals/ # Financial goals CRUD
β β βββ categories/ # System + custom categories
β β βββ dashboard/summary/ # Aggregated dashboard data
β β βββ ai/insight/ # Gemini AI integration
β β βββ ocr/ # Receipt OCR via Gemini Vision
β β βββ export/ # CSV + PDF export
β β βββ user/ # Settings, onboarding, delete account
β βββ manifest.ts # PWA manifest (Next.js native)
βββ components/
β βββ dashboard/ # Summary cards, charts, AI insight card
β βββ transactions/ # List, form modal, OCR scanner, receipt uploader
β βββ budgets/ # Budget manager, alert bell
β βββ goals/ # Goals manager + goal cards
β βββ settings/ # Settings form with delete account
β βββ shared/ # Sidebar, Header, BottomNav, Providers
β βββ ui/ # Skeleton loaders
βββ lib/
β βββ prisma.ts # Prisma client singleton (pg adapter)
β βββ supabase.ts # Supabase Storage client
β βββ auth.ts # NextAuth configuration
β βββ utils.ts # Formatting, color helpers
β βββ validations.ts # Zod schemas (shared client/server)
βββ hooks/ # useTransactions, useDebounce, etc.
βββ types/ # TypeScript interfaces
βββ prisma/
β βββ schema.prisma # Database schema
β βββ seed.ts # Demo data seeder
βββ public/
β βββ sw.js # Service worker (PWA)
βββ middleware.ts # Auth + onboarding route protection
Prisma 7 driver adapter β Uses @prisma/adapter-pg with connection pooling for Supabase pgBouncer compatibility, preventing "too many clients" errors on free tier. Schema defined separately in prisma.config.ts.
Parallel data fetching β Dashboard endpoint uses Promise.all() to run 3 aggregation queries concurrently instead of sequentially, cutting response time by ~60%.
AI cost optimization β Gemini insights are cached in PostgreSQL with @@unique([userId, month, year]). The model is only called once per user per month regardless of how many times the dashboard is visited.
Supabase Storage with signed URLs β Receipts stored privately under {userId}/{transactionId}/ path structure. Signed URLs (1-hour expiry) generated server-side on every access β files are never directly public.
Budget alert deduplication β BudgetAlert has @@unique([budgetId, month, year]) constraint. Alerts triggered client-side after every expense transaction, but only one notification fires per budget per calendar month.
OCR without a separate Vision API β Receipt scanning reuses the existing GOOGLE_AI_API_KEY with Gemini's multimodal capability (text + image in the same request), avoiding a separate Google Cloud Vision billing account.
TypeScript exactOptionalPropertyTypes β Enforces strict distinction between undefined and null throughout the codebase, preventing subtle bugs in optional form fields and Prisma update payloads.
- Node.js >= 20
- A Supabase project (free tier)
- A Google Cloud OAuth 2.0 client
- A Google AI Studio API key
git clone https://github.com/afifn11/finsight.git
cd finsight
npm install
cp .env.example .env.local
# Fill in all values β see below
npx prisma db push
npm run db:seed # optional demo data
npm run dev# App
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET= # openssl rand -base64 32
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Database β Supabase PostgreSQL
DATABASE_URL= # Pooler URL (port 6543, ?pgbouncer=true)
DIRECT_URL= # Direct URL (port 5432)
# Google OAuth β console.cloud.google.com
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# Google Gemini AI β aistudio.google.com
GOOGLE_AI_API_KEY=
# Supabase Storage β project Settings β API
NEXT_PUBLIC_SUPABASE_URL=
SUPABASE_SERVICE_ROLE_KEY=npm run test:run # 165 unit tests (Vitest)
npm run type-check # TypeScript strict check
npm run lint # ESLint
npm run build # Full production buildGitHub Actions runs all four checks on every push to main. The CI badge at the top reflects the current status.
Deployed on Vercel with automatic deployments triggered by pushes to main. Build command: prisma generate && next build.
Database schema changes are applied manually via npx prisma db push against the production Supabase instance before merging.
npm run dev # Dev server (Turbopack)
npm run build # Production build
npm run type-check # tsc --noEmit
npm run lint # ESLint
npm run db:push # Push schema to database
npm run db:studio # Prisma Studio GUI
npm run db:seed # Seed demo data
npm run test:run # Run all testsMIT β free to use for educational and portfolio purposes.
Built by Muhammad Afif Naufal





