A personal finance SaaS for bank account management, transaction tracking, hierarchical budgeting, AI-powered insights, and automated reporting.
| Layer | Technology |
|---|---|
| Framework | Next.js 15 (App Router, React Server Components) |
| API | tRPC 11 with React Query |
| Database | PostgreSQL via Prisma 7 |
| Auth | Better Auth (email/password + email verification) |
| AI | Google Gemini (categorization, insights, receipt OCR) |
| Background Jobs | Inngest (event-driven + cron workers) |
| Resend + Handlebars templates | |
| Rate Limiting | Upstash Redis (with in-memory fallback) |
| Image Uploads | ImageKit |
| Logging | Better Stack (Logtail) |
| Styling | Tailwind CSS + shadcn/ui |
- Node.js >= 20
- pnpm >= 10
- PostgreSQL database (local or hosted, e.g. Neon)
git clone <repo-url>
cd trackit-saas
pnpm installcp .env.example .envOpen .env and fill in your credentials. See the Environment Variables section for details.
# Push schema to database (no migration history)
pnpm db:push
# Or create a migration
pnpm db:generatepnpm devThe app runs at http://localhost:3000.
To run background jobs locally:
pnpm dev:inngest| Command | Description |
|---|---|
pnpm dev |
Start dev server (Turbo-enabled) |
pnpm build |
Production build |
pnpm start |
Start production server |
pnpm check |
Lint + typecheck |
pnpm lint |
ESLint check |
pnpm lint:fix |
ESLint auto-fix |
pnpm typecheck |
TypeScript type check |
pnpm format:check |
Prettier check |
pnpm format:write |
Prettier auto-fix |
pnpm analyze |
Bundle analysis |
pnpm db:generate |
Create Prisma migration |
pnpm db:migrate |
Deploy migrations |
pnpm db:push |
Push schema without migration |
pnpm db:studio |
Open Prisma Studio |
All environment variables are validated at startup via T3 Env in src/env.js.
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
BETTER_AUTH_SECRET |
Random secret for session signing (generate with openssl rand -hex 32) |
BETTER_AUTH_URL |
App URL (e.g. http://localhost:3000) |
NEXT_PUBLIC_APP_URL |
Public app URL |
RESEND_API_KEY |
Resend API key for transactional emails |
EMAIL_FROM |
Sender email address |
GEMINI_API_KEY |
Google AI Studio API key |
NEXT_PUBLIC_BETTER_STACK_SOURCE_TOKEN |
Better Stack source token |
NEXT_PUBLIC_BETTER_STACK_INGESTING_URL |
Better Stack ingesting endpoint |
NEXT_PUBLIC_BETTER_STACK_LOG_LEVEL |
Log level (debug, info, warn, error) |
| Variable | Description |
|---|---|
UPSTASH_REDIS_REST_URL |
Upstash Redis REST URL for rate limiting |
UPSTASH_REDIS_REST_TOKEN |
Upstash Redis REST token |
INNGEST_EVENT_KEY |
Inngest event key for background jobs |
INNGEST_SIGNING_KEY |
Inngest signing key |
IMAGEKIT_PRIVATE_KEY |
ImageKit private key |
IMAGEKIT_URL_ENDPOINT |
ImageKit URL endpoint |
NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY |
ImageKit public key |
NEXT_PUBLIC_IMAGEKIT_URL_ENDPOINT |
ImageKit public URL endpoint |
When UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN are not set, rate limiting falls back to in-memory — suitable for development but not production multi-instance deployments.
src/
app/ # Next.js App Router pages
(public)/ # Marketing pages (/, /about, /blog, etc.)
(auth)/ # Sign-in, sign-up, reset password
(features)/ # Protected app pages (RSC + client)
api/ # API routes (tRPC, auth, inngest)
server/
api/ # tRPC router definitions + middleware
services/ # Business logic layer
components/
ui/ # shadcn/ui primitives
charts/ # Recharts-based chart components
pages/ # Page-specific components
skeletons/ # Loading skeleton components
common/ # Shared components
hooks/ # Custom React hooks
lib/ # Utilities (auth, email, logging, redis)
store/ # Zustand client state
trpc/ # tRPC client + server helpers
types/ # TypeScript type definitions
validation/ # Zod schemas
prisma/
schema.prisma # Database schema
seed.ts # Database seed script
Client Component → tRPC React Query Hook → tRPC Router → Service Layer → Prisma → PostgreSQL
- tRPC routers (
src/server/api/routers/) define API endpoints - Services (
src/server/services/) contain business logic - RSC pages prefetch data server-side via
api.*.prefetch()and hydrate to client components via<HydrateClient>
Better Auth with email/password. Edge middleware provides cookie-based route heuristics; protectedProcedure in tRPC enforces actual auth.
Inngest handles event-driven and cron-scheduled work:
- Transaction processing triggers budget evaluation
- Budget threshold alerts via email
- Recurring transactions, weekly digests, monthly reports
- AI-powered spending insights
| Branch | Purpose |
|---|---|
main |
Production releases (semantic release) |
develop |
Default development branch |
feat/* |
New features |
fix/* |
Bug fixes |
refactor/* |
Code improvements |
hotfix/* |
Urgent production fixes |
Commits follow Conventional Commits (feat:, fix:, refactor:, etc.).
Private. All rights reserved.