Spendly is a modern personal finance tracker built with Next.js App Router, TypeScript, Tailwind CSS, shadcn/ui-style components, Recharts, Zod, and InsForge for authentication, database, backend access, and deployment.
- InsForge authentication with sign up, sign in, sign out, password reset, protected routes, and profile settings
- Dashboard with total balance, monthly income/expenses, net savings, trend charts, budget states, savings goals, recent transactions, and recurring reminders
- Transactions with search, filters, notes, recurring flag, edit/delete flows, and account transfers
- Accounts for cash, bank, credit card, and savings balances
- Budgets with progress tracking, 80% warning states, and exceeded alerts
- Savings goals with target tracking and deadlines
- Recurring payments with weekly, monthly, and yearly cadence, a reminder inbox, and optional email alerts
- Insights for income vs expense comparison, top spending categories, savings rate, and financial health score
- Settings for profile updates, currency selection, true light/dark/system theme switching, reminder preferences, category management, CSV import, per-dataset CSV exports, and one-click demo data
- Next.js 15 App Router
- TypeScript
- Tailwind CSS 3.4
- shadcn/ui-style component system
- Recharts
- Zod + React Hook Form
- InsForge SDK + InsForge CLI
Copy .env.example to .env.local and set:
NEXT_PUBLIC_INSFORGE_URL=https://your-project.us-east.insforge.app
NEXT_PUBLIC_INSFORGE_ANON_KEY=your-insforge-anon-key
NEXT_PUBLIC_APP_URL=http://localhost:3000If this repo is already linked to InsForge, .env.local can be populated from:
.insforge/project.json→oss_hostnpx @insforge/cli secrets get ANON_KEY
- Install dependencies:
npm install- Apply the database migration:
npx @insforge/cli db migrations up --all- Apply auth redirect URL configuration:
npx @insforge/cli config apply --file insforge.toml --auto-approve- Start the app:
npm run dev-
Run the unit tests:
npm run test:unitOptional local reminder worker setup:
npx @insforge/cli functions deploy sync-recurring-reminders --file functions/sync-recurring-reminders.ts --name "Sync recurring reminders" --description "Generates reminder rows and sends reminder emails"For a new repo:
npx @insforge/cli create --json --name Spendly --org-id <org-id> --region us-east --template emptyFor an existing project:
npx @insforge/cli link- Make sure deployment env vars exist:
npx @insforge/cli deployments env set NEXT_PUBLIC_INSFORGE_URL https://your-project.us-east.insforge.app
npx @insforge/cli deployments env set NEXT_PUBLIC_INSFORGE_ANON_KEY your-insforge-anon-key
npx @insforge/cli deployments env set NEXT_PUBLIC_APP_URL https://spendly.insforge.site-
Make sure
insforge.tomlincludes your deployed login URL inauth.allowed_redirect_urls. -
Re-apply auth config:
npx @insforge/cli config apply --file insforge.toml --auto-approve- Build locally:
npm run build- Run the unit suite:
npm run test:unit- Deploy the recurring reminder worker and background schedule:
npx @insforge/cli secrets add SPENDLY_INSFORGE_BASE_URL https://your-project.us-east.insforge.app
npx @insforge/cli secrets add SPENDLY_INSFORGE_API_KEY your-insforge-api-key
npx @insforge/cli secrets add REMINDER_SCHEDULE_TOKEN your-random-token
npx @insforge/cli functions deploy sync-recurring-reminders --file functions/sync-recurring-reminders.ts --name "Sync recurring reminders" --description "Generates reminder rows and sends reminder emails"
npx @insforge/cli schedules create --name "Spendly recurring reminders" --cron "0 8 * * *" --url "https://your-project.us-east.insforge.app/functions/sync-recurring-reminders" --method POST --headers '{"X-Reminder-Token":"${{secrets.REMINDER_SCHEDULE_TOKEN}}"}'If the schedule already exists, use npx @insforge/cli schedules update <id> ... instead of creating a second one.
- Deploy the frontend:
npx @insforge/cli deployments deploy .Current production URL:
The app includes InsForge-backed tables for:
profilesaccountscategoriestransactionsbudgetssavings_goalsrecurring_transactionsrecurring_reminders
The schema is defined in:
migrations/20260604143000_create-spendly-finance-schema.sqlmigrations/20260605101500_add-recurring-reminders.sqlmigrations/20260605101505_add-demo-workspace-rpc.sql
- User data is protected by both app-level ownership checks and Postgres RLS through
auth.uid(). - Default accounts and categories are bootstrapped per user through the
bootstrap_spendly_userRPC. - Account balances stay in sync automatically via a database trigger on
transactions. - Reminder emails use InsForge custom email from the scheduled edge function. In-app reminders work without email; email delivery requires an InsForge paid plan.
- Demo workspace loading is intentionally limited to empty workspaces so sample data can’t overwrite a real ledger.