Skip to content
konradthiemannPublic

About

Local-first personal & family finance PWA — offline capture with two-way sync, household sharing, budgets, savings goals, recurring entries, web push & analytics. Next.js 14 App Router + TypeScript + Prisma + PostgreSQL monorepo. Docs: konradthiemann.github.io/Doewe

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

💰 Doewe

Personal & family finance tracking and insights — record transactions, categorize spending, monitor budgets, manage recurring entries and saving goals, and surface analytics that reveal the patterns blocking your financial goals.

📖 Documentation: https://konradthiemann.github.io/Doewe/

CI Next.js 14.2.5 TypeScript 5.6.3 React 18.3 Prisma 5.19 PostgreSQL Tailwind CSS 3.4 License: MIT


🎯 About

Doewe is a personal finance tracking and insights platform. It helps you record transactions, categorize spending, define and monitor budgets, manage recurring transactions, and surface analytics summaries so you can spot patterns that block financial goals.

Primary goals:

  • Strong developer experience (DX) with strict types, linting, testing, and CI.
  • Learn and apply modern monorepo + Next.js + TypeScript practices.
  • Provide a foundation for future goal‑oriented financial coaching features.

📚 Documentation

Full documentation is hosted at https://konradthiemann.github.io/Doewe/. The source Markdown lives in docs/ and is the single source of truth:


🧰 Technology Stack

Core technologies (derived from workspace manifests and config):

  • Runtime: Node.js (>= 22.12.0, pinned in .nvmrc)
  • Framework: Next.js 14.2.5 (App Router)
  • Language: TypeScript (strict) / React 18.3.1
  • Styling: Tailwind CSS 3.4.x + @tailwindcss/forms — "Calm Finance" design system with semantic tokens (light + dark, see docs/design/)
  • Data Layer: Prisma ORM 5.19.x with PostgreSQL & generated client
  • Validation: Zod
  • Charts/Visualization: chart.js + react-chartjs-2 + chartjs-plugin-datalabels
  • Testing: Vitest 1.6.x (unit + integration) & custom test config
  • Tooling: ESLint (typescript, import, unused imports), SWC (Next.js build), PostCSS + Autoprefixer
  • Monorepo: npm workspaces (apps/, packages/)
  • Shared Library: @doewe/shared for domain primitives (money, strings, domain logic)

🏗️ Project Architecture

High-level overview:

root
├─ apps/web             # Next.js application (App Router) + API route handlers
│  ├─ app/              # Layout, pages, nested routes, API endpoints under app/api/*
│  ├─ components/       # UI components (forms, charts, etc.)
│  ├─ lib/prisma.ts     # Prisma client bootstrap (singleton pattern)
│  ├─ prisma/           # Prisma schema & seed script
│  ├─ tests/            # API route tests (Vitest)
│  ├─ tailwind.config.ts
│  └─ next.config.mjs   # Next.js config (transpile shared workspace)
├─ packages/shared      # Reusable domain logic (money handling, string utilities)
│  └─ src/              # Domain types & functions with tests
├─ shared/              # Centralized ESLint and tsconfig baselines
│  ├─ eslint/           # ESLint base configuration
│  └─ tsconfig/         # Shared tsconfig for extension
├─ .github/             # Workflows (CI) & prompt/instruction docs
└─ vitest.config.ts     # Global test configuration (monorepo aware)

Architectural principles:

  • Separation of web/application concerns (apps/web) from pure domain logic (packages/shared).
  • Single Prisma client instance to avoid multi-instance overhead.
  • Shared TypeScript configuration and lint baselines to enforce consistency.
  • API routes in app/api/* follow Next.js route handler pattern (export HTTP verb functions).
  • Strict typing + domain primitives (e.g., Money) to reduce runtime errors.
  • Mobile‑first responsive UI with accessibility guardrails baked into component patterns.

🚀 Getting Started

🔧 Prerequisites

  • Node.js >= 22.12.0 (pinned in .nvmrc, currently 22.14.0; install via nvm recommended)
  • npm (comes with Node)
  • PostgreSQL database for Prisma (local Docker is fine)

📦 Installation & Setup

# Clone
git clone https://github.com/konradthiemann/Doewe.git
cd Doewe

# Ensure the pinned Node version (reads .nvmrc)
nvm use

# Install all workspace dependencies
npm ci

# Initialize Prisma schema & seed database for web app
npm --workspace @doewe/web run db:push
npm --workspace @doewe/web run db:seed

# Start development server
npm run dev:web

🐳 Local dev with Docker Postgres

If you have Docker Desktop installed, you can run a local database only for local dev:

# Start local Postgres, migrate + seed, then run the app
npm run dev:web:local

# Stop local Postgres when done
npm run db:down:local

🔑 Environment Variables

Create .env.local (not committed). Example matching the local Docker Postgres:

DATABASE_URL="postgresql://doewe:doewe@localhost:5432/doewe_local"
NEXTAUTH_SECRET="set-a-strong-random-secret"
NEXTAUTH_URL="http://localhost:3000"

The seed user is hardcoded (not configurable via env): log in with demo@doewe.test / demo1234 after seeding. After changing schema run:

npm --workspace @doewe/web run prisma:generate

🩺 Migration troubleshooting (non-empty/prod DB)

If a production or Railway database is already populated, Prisma can refuse to apply migrations (P3005) or the schema may drift from the Prisma model (missing columns or incorrect casing like recurringId vs recurringid). Use this checklist to recover quickly:

  1. Point Prisma at the target DB Ensure DATABASE_URL is set to the production database you want to fix.

  2. Try normal deploy first Run npm --workspace @doewe/web run prisma:migrate:deploy.

  3. Baseline a non-empty DB (P3005) If Prisma reports the database is not empty, mark the first migration as applied:

    • Use the migration ID from apps/web/prisma/migrations (example: 20260119095855_add_recurring_skip).
    • Command: npx prisma migrate resolve --applied <MIGRATION_ID> --schema apps/web/prisma/schema.prisma.
  4. Re-run deploy Run npm --workspace @doewe/web run prisma:migrate:deploy again.

  5. If columns or constraints are still missing Apply the corrective SQL in apps/web/prisma/migrations/20260119110500_fix_recurring_columns/migration.sql. This migration is safe to run multiple times and will:

    • Ensure RecurringTransaction.intervalMonths exists
    • Ensure the RecurringTransactionSkip columns, FK, and indexes exist
  6. Verify

    • App starts without column does not exist errors.
    • Recurring transactions load and skips can be toggled.

Tip: PostgreSQL is case-sensitive for quoted identifiers. If a column was created as recurringid (lowercase), Prisma will still look for "recurringId". The fix migration above normalizes this.

🐘 Local database (Docker)

If you don’t have Postgres locally, run a disposable container:

docker run --name doewe-postgres -e POSTGRES_USER=doewe -e POSTGRES_PASSWORD=doewe -e POSTGRES_DB=doewe_local -p 5432:5432 -d postgres:16

Then set:

DATABASE_URL="postgresql://doewe:doewe@localhost:5432/doewe_local"

Seed the database (creates a demo account with the SEED_USER_* credentials):

npm --workspace @doewe/web run db:push
npm --workspace @doewe/web run db:seed

📜 Scripts (root)

  • npm run dev:web – Next.js dev server
  • npm run dev:web:local – Starts local Postgres (Docker), pushes schema, seeds, then runs dev server
  • npm run db:up:local / npm run db:down:local – Start/stop the local Postgres container
  • npm run lint / lint:fix – ESLint across workspaces
  • npm run typecheck – TypeScript noEmit across all workspaces
  • npm run test – Vitest tests (monorepo filter)
  • npm run build – Build all workspaces (web app + stub others)

🗂️ Project Structure

See architecture tree above. Monorepo uses npm workspaces:

  • Apps reside in apps/
  • Shared libraries in packages/
  • Central config baselines under shared/
  • Global test config at root; tests colocated per workspace.

✨ Key Features

Current implemented features include:

  • Transaction management (create, edit, delete, list) via app/api/transactions, with a manually selectable posting date.
  • Recurring transactions with monthly cadence, optional start date, and skips for upcoming runs.
  • Budget endpoints for tracking planned vs actual spending, with Web Push budget alerts.
  • Categories management (app/api/categories).
  • Saving plans & goals with progress timeline, withdrawals, undated idea-backlog goals, and completion.
  • Analytics summary endpoint (app/api/analytics/summary) plus quarterly and monthly-review breakdowns (including income-by-source).
  • Tax preparation (German Belegvorhaltepflicht): earmark transactions for the tax return, attach receipt photos/PDFs (stored in PostgreSQL, app/api/transactions/[id]/attachments), mark whole categories as tax-relevant (retroactive), and review per-year sums with receipt status on /tax.
  • Authentication: credentials login, password reset & change with session eviction, optional Sign-in with Google.
  • Household sharing: the household is the tenancy boundary; roles (OWNER/MEMBER) and invitation links let a family share one dataset.
  • Progressive Web App: installable (manifest, icons, service worker), offline reading (TanStack Query + IndexedDB), offline capture (outbox with client IDs + idempotency), and a two-way sync engine with per-field Last-Write-Wins conflict handling (app/api/sync/*).
  • Web Push notifications: budget alerts, monthly-review reminders, and capture reminders (VAPID).
  • Domain utilities (money formatting, numeric handling, string helpers, sync merge logic) in @doewe/shared.
  • Chart visualization using Chart.js to display spending patterns.
  • Accessible, mobile‑first UI components styled with Tailwind, with reusable toast + spinner feedback primitives.
  • "Calm Finance" design system: semantic design tokens (surfaces, ink, brand, income/expense/savings, status) that adapt to light and dark automatically, applied across every screen and component. Source & spec live in docs/design/ (design-system.html, claude-design-prompt.md, brand logos).

Planned / extensible areas:

  • Advanced anomaly detection across spending categories.
  • Bank/CSV import.
  • Fine-grained household permissions beyond OWNER/MEMBER.

🔄 Development Workflow

  • Conventional Commits for clarity (e.g., feat: add transaction API)
  • Each commit body includes Goal / Why / How.
  • Update monorepoTimeline.md and CHANGELOG.md with notable changes (newest entries on top).
  • CI pipeline (.github/workflows/ci.yml) runs: lint → typecheck → test → build with concurrency control.
  • Prefer small, incremental PRs; keep quality gates green locally before pushing.
  • Branching: main is protected (PR + green CI required); use feature branches named feat/<short-name> or chore/<short-name>.

🚢 Deployment & CI

  • The web app deploys to Railway (EU region europe-west4) on push to main — but only when the CI is green and the push changes files under the watch path apps/web/**. Otherwise Railway marks the deploy SKIPPED.
  • Node version for CI and Railway comes from .nvmrc (engine-strict=true makes a wrong version fail npm ci).
  • Docs deploy to GitHub Pages via .github/workflows/docs.yml → https://konradthiemann.github.io/Doewe/.
  • Full details, skip reasons, and how to fix "prod is not on main's state": see docs/deployment.md.

🤖 Claude AI Agents

This project ships a suite of specialised Claude Code sub-agents in .claude/agents/. They are invoked from within a Claude Code session with @agent-name and each one has deep knowledge of the Doewe stack.

Agent overview

Agent File When to use
orchestrator orchestrator.md Starting point for any multi-layer feature (DB + API + UI + tests)
planner planner.md Design an implementation plan before any code is written
implementer implementer.md Write or refactor production code (routes, components, migrations)
reviewer reviewer.md Review a diff or PR for correctness, TypeScript quality, test coverage
security security.md Audit API routes, auth flows, and data handling for vulnerabilities
ui-ux ui-ux.md Review or build UI components with accessibility + Tailwind compliance
data-analyst data-analyst.md Design schema changes, optimise Prisma queries, reason about domain logic
docs docs.md Write, update, or audit documentation (inline TSDoc, README, CHANGELOG)
agent-quality agent-quality.md Audit and improve the agent files themselves when the project evolves

How to invoke agents

In any Claude Code session, prefix your request with the agent name:

@orchestrator Neues Feature: Benutzer soll Budget-Alerts per E-Mail erhalten wenn die Ausgaben 80% des Budgets überschreiten.

@planner Plane die Implementierung eines CSV-Exports für Transaktionen.

@implementer Implementiere GET /api/accounts basierend auf dem folgenden Plan: [...]

@reviewer Bitte review den folgenden Diff: [diff einfügen]

@security Prüfe alle Routen in apps/web/app/api/ auf fehlende Auth-Guards.

@data-analyst Ich möchte den SavingPlan um ein deadline-Feld erweitern. Welche Schema-Änderungen brauche ich?

@ui-ux Review die TransactionForm-Komponente auf Accessibility-Probleme.

@docs Aktualisiere die README nach dem neuen Recurring-Transactions-Feature.

@agent-quality Prüfe alle Agent-Dateien — wir haben letzte Woche auf Next.js 15 migriert.

Recommended workflows

Neues Feature (End-to-End)

1. @orchestrator  →  Dekomposition in Sub-Tasks
2. @planner       →  Detaillierter Implementierungsplan mit Reihenfolge
3. @data-analyst  →  Schema-Review (falls DB betroffen)
4. @implementer   →  Code schreiben layer by layer
5. @reviewer      →  Code-Review vor dem Commit
6. @security      →  Security-Check der neuen API-Routen
7. @ui-ux         →  Accessibility-Review der neuen Komponenten
8. @docs          →  Dokumentation aktualisieren

Quick Bug Fix

1. @implementer   →  Fix direkt beschreiben lassen
2. @reviewer      →  Kurz-Review des Fixes

PR-Review

1. @reviewer      →  Allgemeine Code-Qualität
2. @security      →  Sicherheits-Check (bei API-Änderungen)

Schema-Migration

1. @data-analyst  →  Migration planen + Risiken bewerten
2. @implementer   →  Migration schreiben
3. @docs          →  CHANGELOG + README aktualisieren

Projekt wächst / Stack-Update

1. @agent-quality →  Agent-Dateien auf Aktualität prüfen und verbessern

Tips for efficient use

  • Kontext mitgeben: Je konkreter der Prompt, desto besser das Ergebnis. Dateinamen, Zeilennummern, und bestehende Code-Snippets helfen enorm.
  • Orchestrator zuerst: Bei Features die mehr als eine Datei betreffen, lohnt es sich immer zuerst den Orchestrator zu fragen — er verhindert vergessene Layers (z.B. fehlender Auth-Check, fehlender Test).
  • Agent Quality nach Stack-Updates: Wenn Dependencies, Konventionen oder Dateistrukturen sich ändern, den agent-quality-Agent laufen lassen damit die anderen Agents nicht mit veralteten Annahmen arbeiten.
  • Agents kombinieren: Du kannst in einer Session mehrere Agents hintereinander nutzen — z.B. erst @planner für den Plan, dann @implementer mit dem Plan als Input.

📐 Coding Standards

  • TypeScript strict everywhere; domain types first.
  • Tailwind for styling (avoid inline styles by merge-time).
  • Accessibility: follow WCAG 2.2 AA; leverage semantic HTML & ARIA where necessary (see a11y instructions).
  • Next.js best practices: App Router, server components by default, isolate client logic in 'use client' components, avoid next/dynamic with ssr:false in server components.
  • Shared ESLint baseline in shared/eslint/eslint.base.cjs; extend in workspaces.
  • DRY: prefer pulling common utilities into @doewe/shared.
  • Secure defaults: no secrets committed; use .env.example for reference.

🧪 Testing

  • Test runner: Vitest (configured globally in vitest.config.ts).
  • Test locations:
    • Domain tests: packages/shared/src/*.test.ts
    • API tests: apps/web/tests/*.test.ts
    • Component tests: apps/web/components/**/*.test.tsx (jsdom, via apps/web/vitest.config.ts)
  • Strategy: Focus on domain correctness (money/math), API contract validation (status codes, payload shapes), and regression protection for critical logic.
  • Run tests:
npm run test
  • Type safety acts as first defense; add tests for complex calculations, parsing, and error paths.

🤝 Contributing

Guidelines:

  1. Create a branch (feat/, fix/, chore/).
  2. Implement change with focus on accessibility, DX, and performance.
  3. Run local quality gates:
    npm run lint
    npm run typecheck
    npm run test
  4. Update CHANGELOG.md and monorepoTimeline.md (top‑append newest change).
  5. Ensure commit body has Goal / Why / How.
  6. Open PR; CI must pass before merge (main is protected).

Reference Docs:


⚡ Quick Reference

# Install & bootstrap
npm ci && npm --workspace @doewe/web run db:push && npm --workspace @doewe/web run db:seed

# Dev server
npm run dev:web

# Prisma generate (after schema change)
npm --workspace @doewe/web run prisma:generate

# Quality gates
npm run lint && npm run typecheck && npm run test

🗺️ Roadmap

  • Enhanced analytics (trend lines, category forecasts)
  • Export/import (CSV, OFX) and optional bank connections
  • Fine-grained household permissions
  • Performance budget & bundle size tracking

✅ Shipped: the "Calm Finance" design-system rollout (semantic tokens + full component/screen refresh, light + dark) is complete — see docs/design/.


📄 License

Released under the MIT License — © 2026 Konrad Thiemann.

🔒 Security

Found a vulnerability? Please report it privately — see SECURITY.md.


🙏 Acknowledgements

Built with modern Next.js & TypeScript standards, emphasizing accessibility and clean domain modeling.

About

Local-first personal & family finance PWA — offline capture with two-way sync, household sharing, budgets, savings goals, recurring entries, web push & analytics. Next.js 14 App Router + TypeScript + Prisma + PostgreSQL monorepo. Docs: konradthiemann.github.io/Doewe

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages