A modern, scalable Personal Finance Management System built with Next.js 15, Express.js, TypeScript, and Nx Monorepo architecture.
This monorepo follows Feature-Sliced Design (FSD) with clear separation of concerns:
- Next.js 15 application with App Router
- Server Components by default for optimal performance
- Shadcn/UI components with Tailwind CSS
- Pages: Dashboard, Accounts, Transactions, Insurances, Automation
- Service Worker support for offline capabilities
- Express.js REST API server
- TypeScript with strict mode (no
anytypes) - Zod validation for all API boundaries
- CORS and logging middleware
- Health check endpoint at
/health
- Single Source of Truth for all domain models
- Zod schemas for runtime validation
- TypeScript interfaces and discriminated unions
- Types: Transactions, Accounts, Insurances
- Prisma ORM setup and database client
- Service layer:
TransactionService: Income/expense logic and balance managementAccountService: Account management and balance trackingInsuranceService: Policy tracking and renewal management
- Shared TypeScript types for API requests/responses
- Ensures type safety between frontend and backend
- Exports: Accounts, Transactions, Summary, API Response types
- Shared React components
- Financial charts using Recharts
- Currency display components
- Transaction dialogs and forms
- Account management components
- Financial utilities:
- Currency conversion
- Tax calculations
- API key validation for webhooks
- Environment variable validation with Zod
- Node.js 18+
- pnpm (recommended for monorepo performance)
-
Install dependencies:
pnpm install
-
Set up environment variables: Create a
.envfile in the root directory:DATABASE_URL="file:./prisma/dev.db" PORT=3000 NODE_ENV=development NEXT_PUBLIC_API_URL=http://localhost:3000 NEXT_PUBLIC_APP_URL=http://localhost:4200 FRONTEND_URL=http://localhost:4200 N8N_WEBHOOK_API_KEY=your-api-key-here # Optional, for webhook authentication
-
Set up the database:
pnpm prisma:generate pnpm prisma:migrate
-
Run the development servers:
Frontend (Next.js):
pnpm dev
Available at
http://localhost:4200Backend API (Express):
pnpm dev:api
Available at
http://localhost:3000
finance-vault/
├── apps/
│ ├── front/ # Next.js 15 frontend
│ │ └── src/
│ │ ├── app/ # App Router pages
│ │ ├── components/ # UI components
│ │ ├── features/ # Feature modules (FSD)
│ │ ├── widgets/ # App layout widgets
│ │ └── shared/ # Shared frontend code
│ └── api/ # Express.js backend
│ └── src/
│ ├── app/ # Express app setup
│ ├── features/ # Feature modules
│ └── shared/ # Shared backend code
├── libs/
│ └── shared/
│ ├── domain/ # Domain models & Zod schemas
│ ├── data-access/ # Prisma & services
│ ├── api-types/ # API request/response types
│ ├── ui/ # Shared React components
│ └── utils/ # Utility functions
├── prisma/
│ └── schema.prisma # SQLite database schema
└── ...
- Accounts: Multi-currency support with JSON metadata
- Transactions: Income/Expense transactions with categories
- Insurances: Policy tracking with renewal dates and status
- Strict TypeScript configuration (no
anytypes) - Discriminated unions for transaction types
- Zod schemas for runtime validation at all API boundaries
- Shared types between frontend and backend via
@finance-vault/api-types
- API key validation for n8n webhook endpoint
- Constant-time comparison to prevent timing attacks
- Environment variable validation with Zod
- Server Components by default in Next.js
- Parallel data fetching for optimal performance
- Indexed database queries
- Service Worker for offline support
- Feature-Sliced Design (FSD) structure
- Clean separation between apps and libraries
- Reusable shared components and utilities
The project uses path aliases for clean imports:
@finance-vault/domain→libs/shared/domain/src/index.ts@finance-vault/data-access→libs/shared/data-access/src/index.ts@finance-vault/api-types→libs/shared/api-types/src/index.ts@finance-vault/ui→libs/shared/ui/src/index.ts@finance-vault/utils→libs/shared/utils/src/index.ts@/→apps/front/src/(frontend only)
cd apps/front
npx shadcn-ui@latest add [component-name]# Create a new migration
pnpm prisma:migrate --name migration-name
# Generate Prisma Client
pnpm prisma:generate
# Open Prisma Studio
pnpm prisma:studioBase URL: http://localhost:3000
- GET
/health- Service health status
- GET
/api/v1/accounts- Get all accounts
- GET
/api/v1/transactions- Get transactions (with query params for filtering) - POST
/api/v1/transactions- Create a new transaction - PUT
/api/v1/transactions/:id- Update a transaction - DELETE
/api/v1/transactions/:id- Delete a transaction
- GET
/api/v1/summary- Get financial summary data
- GET
/api/v1/automate- Health check for automation endpoint - POST
/api/v1/automate- n8n webhook endpoint for automated transaction processing- Headers:
x-api-key: API key for authentication (optional ifN8N_WEBHOOK_API_KEYis not set)
- Headers:
# Run linting
pnpm lint
# Run tests
pnpm test
# Run tests for specific project
nx test api
nx test front# Build all projects
pnpm build
# Build specific project
nx build front
nx build apipnpm dev- Start frontend development server (port 3000)pnpm dev:api- Start API development server (port 4200)pnpm build- Build all projectspnpm test- Run all testspnpm lint- Lint all projectspnpm format- Format code with Prettierpnpm prisma:generate- Generate Prisma Clientpnpm prisma:migrate- Run database migrationspnpm prisma:studio- Open Prisma Studio
- Frontend: Next.js 15 (App Router), React 19, TypeScript, Tailwind CSS, Shadcn/UI
- Backend: Express.js, TypeScript
- Database: SQLite with Prisma ORM
- Monorepo: Nx
- Validation: Zod
- Charts: Recharts
- Forms: React Hook Form
MIT