A full-stack personal finance platform for tracking income, expenses, budgets, subscriptions, and account-level analytics.
MET is built as a production-style monorepo with a React frontend, an Express API, PostgreSQL, Prisma ORM, Docker support, and CI/CD workflows.
- JWT authentication with profile management
- Multi-account finance tracking (Primary, Savings, etc.)
- Transaction management with summaries and charts
- Recurring transactions (Premium/Admin)
- Category rules, bulk category assignment, and split transactions (Premium/Admin)
- Budget goals and monthly budget tracking (Premium/Admin)
- Data transfer logs for import/export actions
- Role system:
BASIC,PREMIUM,ADMIN - Admin panel endpoints (user management, audit logs, promo codes)
- Docker image build pipeline and security workflows
.
|- backend/ # Express + TypeScript + Prisma API
|- frontend/ # React + Vite + TypeScript app
|- docs/ # generated/auxiliary documentation artifacts
|- scripts/ # repo utility scripts
|- .github/ # CI/CD workflows
`- docker-compose.yml # local PostgreSQL service
- Frontend: React 19, Vite, TypeScript, Tailwind CSS v4, Recharts, Framer Motion
- Backend: Node.js, Express 5, TypeScript, Prisma
- Database: PostgreSQL 15
- Auth/Security: JWT, bcrypt, CORS policy, rate limiting
- CI/CD: GitHub Actions (CI, Security, Docker, Docs)
- Containers: Docker, Docker Compose
- Node.js 22+
- npm 10+
- Docker (for local PostgreSQL)
From repository root:
docker compose up -dThis starts PostgreSQL on localhost:5432 with the credentials from docker-compose.yml.
Create backend/.env with at least:
DATABASE_URL=postgresql://met_user:met_password@localhost:5432/met_db?schema=public
JWT_SECRET=replace_with_a_strong_secretOptional values are documented in backend/README.md.
cd backend && npm install
cd ../frontend && npm installcd backend
npx prisma migrate dev
npx prisma generateIn one terminal:
cd backend
npm run devIn another terminal:
cd frontend
npm run devOpen http://localhost:5173.
- Frontend:
http://localhost:5173 - Backend API:
http://localhost:3000 - Health check:
GET http://localhost:3000/health - PostgreSQL:
localhost:5432
- Authentication and account/profile lifecycle
- Account-scoped transactions and summaries
- Categories, rules, and budget planning
- Premium-only analytics and automation
- Admin moderation and audit tooling
For endpoint-level documentation, see backend/README.md.
- Database startup is handled via
docker compose up -d
npm run devnpm run lintnpm run typechecknpm run checknpm run buildnpm run preview
npm run devnpm run startnpm run typechecknpm run checknpm run prisma:generate
Note: npm run check is the current quality gate in both projects (lint/typecheck). Automated unit/integration test suites are not set up yet.
Defined in .github/workflows:
ci.yml- frontend/backend install, checks, and buildsecurity.yml- npm audit + CodeQLdocker.yml- Docker image build (and push to GHCR onmain)docs.yml- auto-generated docs artifactpost-deploy-smoke.yml- post-push Render health and CORS smoke checksuptime-monitor.yml- scheduled backend uptime monitor with GitHub issue alerting
To enable smoke tests and uptime alerting, configure repository secrets in GitHub:
RENDER_HEALTH_URL(example:https://your-backend.onrender.com/health)RENDER_API_BASE_URL(example:https://your-backend.onrender.com/api)FRONTEND_ORIGIN(example:https://your-frontend.vercel.app)
For frontend preview deployments, frontend/src/api/baseUrl.ts now supports:
VITE_API_BASE_URL(preferred explicit API base for build envs)VITE_VERCEL_FALLBACK_API_BASE_URL(optional fallback for*.vercel.apphosts)
Before publishing broadly, verify:
- No secrets or private tokens are committed.
backend/.envis excluded and never tracked.- A proper
LICENSEfile is added at repo root. - Production values are set for CORS, JWT secret, and database credentials.
- GHCR/package permissions match your publication model.
Security policy and reporting notes are in SECURITY.md.
- Update this section with your public maintainer profile before publishing.