No description
  • JavaScript 48.2%
  • TypeScript 25.5%
  • CSS 15.9%
  • HTML 8.9%
  • Dockerfile 1.5%
Find a file
Freydis Mende e946b6a468
All checks were successful
CI / Backend – install, typecheck & syntax check (push) Successful in 1m17s
CI / Docker – build image (push) Successful in 12s
CI / deploy (push) Successful in 0s
rename web network, drop traefik labels
2026-08-30 22:09:22 +02:00
.forgejo/workflows Migrate backend to TypeScript, add zod request validation 2026-08-14 23:31:18 +02:00
backend Migrate backend to TypeScript, add zod request validation 2026-08-14 23:31:18 +02:00
frontend Split into frontend/backend dirs, replace content-hash version with git hash, add /api/health 2026-08-14 10:22:59 +02:00
.dockerignore Split into frontend/backend dirs, replace content-hash version with git hash, add /api/health 2026-08-14 10:22:59 +02:00
.gitignore Split into frontend/backend dirs, replace content-hash version with git hash, add /api/health 2026-08-14 10:22:59 +02:00
docker-compose.yml rename web network, drop traefik labels 2026-08-30 22:09:22 +02:00
Dockerfile Migrate backend to TypeScript, add zod request validation 2026-08-14 23:31:18 +02:00
README.md Split into frontend/backend dirs, replace content-hash version with git hash, add /api/health 2026-08-14 10:22:59 +02:00

Haushaltsbuch

Ein persönliches, lokal gehostetes Haushaltsbuch: Einkommen und Fixkosten eintragen, Tagesausgaben pflegen und den verbleibenden Monatsbudget im Blick behalten inklusive kleiner Gamification (Maskottchen & Achievements) und einer Auswertungsseite mit Diagrammen.

Features

  • Mehrere Einkommensquellen und Fixkosten mit frei einstellbaren Kategorien
  • Tagesaktuelle Ausgabenerfassung mit laufendem Restbetrag für den Monat
  • Einmalige Einkommensanpassungen (Bonus, Gehaltskürzung) für einen einzelnen Monat, ohne die Vorlage zu ändern
  • Maskottchen (Kuh/Drache/Hai), das je nach Sparverhalten reagiert, plus ein Achievement-System
  • Auswertungsseite mit Einkommen/Ausgaben-Verlauf und einer Kategorie-Aufschlüsselung ("Wohin dein Geld fließt")

Tech-Stack

  • Node.js + Express (backend/server.js)
  • Datenzugriff über Knex (backend/db.js, backend/db-config.js), Backend je nach DATABASE_URL: SQLite über better-sqlite3 lokal (Datenbankdatei wird beim ersten Start automatisch angelegt), Postgres in Produktion. Schema-Änderungen laufen über Knex-Migrationen (backend/migrations/, npm run migrate:make <name>)
  • Reines HTML/CSS/JavaScript im Frontend (frontend/), kein Build-Schritt, kein Framework

Lokal starten (ohne Docker)

Voraussetzung: Node.js 24 (siehe Dockerfile).

cd backend
npm install
npm start

Die App läuft danach unter http://localhost:3000. Die SQLite-Datenbank wird als backend/haushaltsbuch.db angelegt (per .gitignore ausgeschlossen).

Mit Docker starten

docker compose up -d --build

Die App läuft danach unter http://localhost:3000. Die Datenbank wird im benannten Volume haushaltsbuch-data gespeichert und bleibt über Container-Neubauten hinweg erhalten.

Zum Stoppen:

docker compose down

(Das Volume bleibt dabei erhalten; docker compose down -v würde es zusätzlich löschen.)

Das Compose-File enthält bereits Traefik-Labels für den Betrieb hinter einem Traefik-Reverse-Proxy. Dafür muss das externe Docker-Netzwerk existieren, auf dem auch Traefik lauscht (Standard: traefik, per TRAEFIK_NETWORK anpassbar), und TRAEFIK_HOST auf die gewünschte Domain gesetzt werden (siehe Tabelle unten).

Zugriffsschutz per Client-Zertifikat (mTLS)

Statt Basic Auth (das bei installierten iOS-PWAs wegen des WebKit-Zertifikatscaches bei jedem Neustart erneut nach Zugangsdaten fragt) verlangt der Router ein gültiges Client-Zertifikat, bevor überhaupt eine TLS-Verbindung zustande kommt. Kein Passwort-Prompt mehr das Gerät weist sich über das installierte Zertifikat aus.

Die CA, die Skripte zum Ausstellen von Geräte-Zertifikaten und die eigentliche TLS-Options-Definition (inkl. clientAuth) liegen nicht in diesem Repo, sondern im separaten Repo mtls-ca sie sind app-übergreifend, ein einmal ausgestelltes Zertifikat gilt für alle Apps, die dieselbe CA referenzieren (z. B. auch dex-binder). Wichtig: Ein tls.options-Eintrag mit clientAuth-Einstellungen lässt sich über Docker-Labels nur referenzieren, nicht definieren die Definition muss über Traefiks File-Provider laufen (siehe mtls-ca-Repo). Dieses App-Repo referenziert die Option daher mit dem Suffix @file (traefik.http.routers.haushaltsbuch.tls.options=haushaltsbuch-mtls@file), nicht @docker.

Konfiguration

Variable Beschreibung Standard
DATABASE_URL Postgres-Connection-String; wenn gesetzt, wird Postgres statt SQLite verwendet nicht gesetzt (SQLite)
DB_PATH Pfad zur SQLite-Datenbankdatei (nur wenn DATABASE_URL nicht gesetzt ist) backend/haushaltsbuch.db
PORT Port, auf dem der Server lauscht 3000
HOST_PORT Host-Port, auf den der Container-Port gemappt wird (Docker Compose) 3000
TRAEFIK_HOST Domain, unter der Traefik die App erreichbar macht haushaltsbuch.example.com
TRAEFIK_NETWORK Name des externen Docker-Netzwerks, auf dem Traefik lauscht traefik
TRAEFIK_CERT_RESOLVER Name des in Traefik konfigurierten Cert-Resolvers letsencrypt

API

Alle Endpunkte liefern/erwarten JSON.

Methode Pfad Beschreibung
GET /api/health Health-Check ({"status":"ok","database":"connected"}, 503 falls die DB-Prüfung fehlschlägt)
GET /api/version Git-Commit-Hash, beim Build eingebacken ({"version":"<hash>"}, "unknown" außerhalb von Docker)
GET /api/summary?month=YYYY-MM Einkommen, Fixkosten, Ausgaben, Rest, Maskottchen für einen Monat
GET /api/achievements Freigeschaltete Achievements über alle Monate
GET /api/analytics?range=N Monatlicher Verlauf + Kategorie-Aufschlüsselung der letzten N Monate
GET/POST/DELETE /api/categories[/:id] Kategorien verwalten
POST/PUT/DELETE /api/incomes[/:id] Einkommensquellen verwalten
POST/DELETE /api/income-adjustments[/:id] Einmalige Einkommensanpassungen
POST/PUT/DELETE /api/fixed-costs[/:id] Fixkosten verwalten
POST/PUT/DELETE /api/expenses[/:id] Tagesausgaben verwalten

Projektstruktur

backend/
  server.js        Express-Server, API-Routen, Business-Logik (Summary, Maskottchen, Achievements, Analytics)
  db.js             Knex-Instanz, Migrations-Bootstrap (baselined bestehende Datenbanken automatisch)
  db-config.js      Knex-Connection-Config (SQLite lokal, Postgres via DATABASE_URL)
  seed.js           Idempotentes Seeding (Settings-Zeile, Standardkategorien) für frische Datenbanken
  migrations/       Knex-Migrationen (Schema-Historie)
frontend/
  index.html      Dashboard (Summary-Karten, Maskottchen, Achievements, Ausgaben, Einstellungen)
  auswertung.html Auswertungsseite mit Diagrammen
  app.js          Frontend-Logik für das Dashboard
  analytics.js    Diagramm-Rendering (SVG) für die Auswertungsseite
  styles.css      Gemeinsames Styling