Spendwise is a full-stack personal finance management dashboard built with Next.js 14 App Router. Track your income and expenses, manage accounts and categories, visualize spending patterns with interactive charts, and analyze summaries with powerful filters and data tables.
- Multi-user support with Clerk authentication
- CRUD operations for Accounts, Categories, and Transactions via intuitive shadcn/ui sheets and forms
- Interactive Charts (Pie, Bar, Line, Area, Radar, Radial) powered by Recharts with custom tooltips and filters (date range, accounts)
- Data Tables with TanStack Table, sorting, pagination
- Advanced Filters: Date picker, account/category selectors, amount inputs
- Demo Data: CSV import via seed script (
bun run db:seed) - Responsive UI with Tailwind CSS and shadcn/ui components
- Type-safe API with TanStack Query hooks, Zod validation, Drizzle ORM
- Dark/Light mode support
splitfin-expense-platform/
├── app/ # Next.js 14 App Router
│ ├── (auth)/ # Auth routes
│ ├── (dashboard)/ # Protected dashboard routes
│ ├── api/[[...route]]/ # API catch-all (Hono?)
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── components/ # Shared UI components
│ ├── ui/ # shadcn/ui primitives (button, card, table, etc.)
│ ├── chart.tsx # Chart wrappers/variants
│ └── data-*.tsx # Data cards, grids, tables
├── features/ # Feature-sliced organization
│ ├── accounts/ # Accounts CRUD (api hooks, forms, sheets)
│ ├── categories/ # Categories CRUD
│ ├── summary/ # Summary data
│ └── transactions/ # Transactions CRUD (bulk ops)
├── db/ # Drizzle ORM
│ ├── schema.ts # Accounts, Categories, Transactions tables
│ └── drizzle.ts
├── lib/ # Utilities
│ ├── utils.ts
│ └── hono.ts # API router?
├── providers/ # React providers (QueryClient, Theme)
├── config/ # App config
├── drizzle/ # Generated migrations
├── scripts/seed.ts # Demo data seeding
├── package.json # Bun + deps
├── tailwind.config.ts
├── drizzle.config.ts
├── next.config.mjs
└── tsconfig.json
User (Clerk Auth)
↓
App Router (Next.js 14)
├── Client Components (RSC boundaries)
│ ├── shadcn/ui + Custom (charts, forms, tables)
│ ├── TanStack Query (mutations/queries)
│ └── Zustand (state?)
├── Server Actions / API Routes (Hono?)
│ └── Drizzle ORM (Neon Postgres)
└── Providers (QueryClient, Theme)
Data Flow:
- Queries/Mutations → features/*/api/use-*.ts → Drizzle
- UI → React Hook Form + Zod → Mutations
- Charts → Recharts + Aggregated data from summary queries
- Frontend: Feature-sliced (accounts/transactions/etc.), TanStack Query for optimistic updates/caching.
- Backend: Drizzle for schema/migrations/queries, Zod for validation.
- Styling: Tailwind + shadcn/ui + class-variance-authority (cva).
- Data: Per-user tables, transactions link accounts/categories.
| Category | Technologies |
|---|---|
| Framework | Next.js 14, React 18, TypeScript 5 |
| UI/Styling | Tailwind CSS, shadcn/ui, Radix UI, Lucide Icons, Sonner |
| Data Fetching | @tanstack/react-query, @tanstack/react-table |
| Forms/Validation | React Hook Form, Zod |
| Database/ORM | Drizzle ORM, Neon Postgres, pg |
| Auth | Clerk |
| Charts | Recharts |
| Utils | date-fns, class-variance-authority, clsx, Hono |
| Other | Bun (lockfile/scripts), react-countup |
Full deps in package.json.
-
Prerequisites: Git, Bun (recommended) or Node.js 20+.
-
Clone & Install:
git clone <repo> splitfin-expense-platform cd splitfin-expense-platform bun install # or npm install
-
Environment (
.env.local):NEXT_TELEMETRY_DISABLED=1 # Clerk (sign up at https://clerk.com) NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up # Neon Postgres (https://neon.tech) or local PG DATABASE_URL=postgresql://user:pass@host/db?sslmode=require NEXT_PUBLIC_APP_URL=http://localhost:3000
-
Database:
bunx drizzle-kit generate:pg bunx drizzle-kit migrate bun run db:seed # Loads demo data from public/data.csv # Optional: bun run db:studio (Drizzle Studio UI)
-
Run:
bun run dev # http://localhost:3000
Use Turso libSQL or Docker Postgres:
docker run -p 5432:5432 -e POSTGRES_PASSWORD=pass -d postgres
DATABASE_URL=postgresql://postgres:pass@localhost:5432/splitfin- Frontend: Vercel (auto-deploys from GitHub)
- DB: Neon or Supabase Postgres
- Auth: Clerk (dev/prod keys)
- Fork & PR
- Follow ESLint/Prettier
- Update deps with
bun add
See CODE_OF_CONDUCT.md.
⭐ Star on GitHub if useful!