2e264014b641bda7b54ed70d71249cbf5d18ab45
req.url resolves to the internal hostname in Docker standalone mode. Read the Host header directly so redirects and CSRF origin checks use whatever host the browser actually used (IP, hostname, or domain). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Finance App
Personal finance web app for tracking bank transactions, monitoring net worth, and visualizing spending. Self-hosted via Docker Compose — no cloud services required.
Features
- Import transactions from CSV exports (Discover Savings, Discover Credit Card, Huntington Checking, Fidelity)
- Net worth tracking across bank accounts
- Browse, filter, and annotate transactions
- Assign transactions to budgets with optional monthly caps
- Dashboard: net worth snapshot, cash flow, recent transactions, budget summary
- Charts: net worth trend, monthly cash flow, spending by category, budget performance
Quick start
Prerequisites: Docker and Docker Compose
# 1. Copy the example env file
cp .env.example .env
Edit .env:
- Set
NEXTAUTH_SECRETto the output ofopenssl rand -base64 32 - Set
SEED_EMAILandSEED_PASSWORDto your desired login credentials - Change
POSTGRES_PASSWORDto a strong password
# 2. Build the images
docker compose build
# 3. Start the database
docker compose up db -d
# 4. First-run only: apply the schema and create your user
docker compose --profile setup run --rm setup
# 5. Start the app
docker compose up app -d
# 6. Open the app
open http://localhost:3000
Sign in with the SEED_EMAIL / SEED_PASSWORD you set.
Environment variables
| Variable | Description |
|---|---|
NEXTAUTH_SECRET |
Secret for JWT signing — run openssl rand -base64 32 |
NEXTAUTH_URL |
Public URL of the app (default: http://localhost:3000) |
SEED_EMAIL |
Login email created by the seed script |
SEED_PASSWORD |
Login password created by the seed script |
POSTGRES_USER |
PostgreSQL username |
POSTGRES_PASSWORD |
PostgreSQL password |
POSTGRES_DB |
PostgreSQL database name |
DATABASE_URL |
Full connection string — set automatically by Compose |
Useful commands
# View logs
docker compose logs -f app
# Stop the stack
docker compose down
# Stop and wipe the database volume
docker compose down -v
# Re-seed after a wipe
docker compose --profile setup run --rm setup
# Check health
curl http://localhost:3000/api/health
CSV import
Upload CSV files at /upload. The bank profile is auto-detected from the header row. Supported profiles:
| Bank | Account type |
|---|---|
| Discover High Yield Savings | BANK |
| Discover Credit Card | CREDIT_CARD |
| Huntington Checking | BANK |
| Fidelity (cash activity only) | BANK |
If auto-detection fails, a column mapper is shown for manual field assignment.
BANK accounts count toward net worth and cash flow. CREDIT_CARD accounts are tracked only.
Development
# Start the database
docker compose up db -d
# Install dependencies
npm install
# Apply schema
npx prisma db push
# Seed a user
npx prisma db seed
# Start the dev server
npm run dev
The app is at http://localhost:3000.
Architecture
| Layer | Choice |
|---|---|
| Framework | Next.js 16 App Router + TypeScript |
| Database | PostgreSQL 16 + Prisma ORM |
| Auth | NextAuth.js v5 (JWT sessions, bcrypt) |
| UI | Tailwind CSS + shadcn/ui |
| Charts | Recharts |
| Deployment | Docker Compose |
Description
Languages
TypeScript
97%
CSS
2.1%
Dockerfile
0.6%
JavaScript
0.3%