No description
  • TypeScript 57.5%
  • Go 36%
  • CSS 2.9%
  • Dockerfile 2.2%
  • JavaScript 0.7%
  • Other 0.7%
Find a file
Freydis Mende d8e00d14bb
All checks were successful
CI / Frontend – install, typecheck & build (push) Successful in 14s
CI / Backend – build & vet (push) Successful in 20s
CI / Docker Compose – build images (push) Successful in 3s
CI / deploy (push) Successful in 0s
rename web network, drop traefik labels
2026-08-30 22:10:06 +02:00
.forgejo/workflows Add /api/health and /api/version, bake in git commit hash into Docker builds 2026-08-14 10:21:27 +02:00
.github initial import 2026-06-07 18:18:06 +02:00
.vite/deps initial import 2026-06-07 18:18:06 +02:00
backend Make git-hash Dockerfile stage tolerant of a missing .git 2026-08-14 19:57:33 +02:00
frontend Disable react-hooks/set-state-in-effect false positive in frontend lint 2026-08-14 19:14:21 +02:00
.dockerignore Add /api/health and /api/version, bake in git commit hash into Docker builds 2026-08-14 10:21:27 +02:00
.gitignore initial import 2026-06-07 18:18:06 +02:00
docker-compose.yml rename web network, drop traefik labels 2026-08-30 22:10:06 +02:00
README.md Add /api/health and /api/version, bake in git commit hash into Docker builds 2026-08-14 10:21:27 +02:00

Haushaltsplan

A household chore tracker for kids with a parent confirmation flow. Children can mark tasks as done and earn coins that top up their weekly allowance. Parents confirm or reject completions through a certificate-gated view.

Features

  • Child view shows all chores for the current week, coin rewards per task, and a running allowance total
  • Parent view gated by an mTLS client certificate; confirm or reject pending completions with optional notes; manage tasks and settings
  • Configurable base allowance and coin value (€ per coin) are editable at runtime
  • Persistent SQLite database stored on a Docker volume

Tech stack

Layer Technology
Backend Go 1.26 · chi router · modernc SQLite (no CGO)
Frontend React 19 · TypeScript · Vite · Tailwind CSS v4
Container Docker Compose (nginx reverse proxy → Go API)

Local development

Prerequisites

  • Go ≥ 1.22
  • Node.js ≥ 20

Backend

cd backend
go run .
# API available at http://localhost:8080

Frontend

cd frontend
npm install
npm run dev
# App available at http://localhost:5173

The Vite dev server proxies /api/* requests to http://localhost:8080.

Docker

docker compose up --build

The app will be available at http://localhost:8080.

The SQLite database is persisted in a named Docker volume (db-data).

docker-compose.yml includes Traefik labels for running behind a Traefik reverse proxy. This needs the external Docker network Traefik listens on (default traefik, override via TRAEFIK_NETWORK) and TRAEFIK_HOST set to the desired domain.

Variable Default Description
TRAEFIK_HOST haushaltsplan.example.com Domain Traefik routes to this app
TRAEFIK_NETWORK traefik External Docker network Traefik listens on
TRAEFIK_CERT_RESOLVER letsencrypt Traefik cert resolver name

Access control (mTLS)

Instead of a PIN, the parent view is gated by a client certificate signed by a shared personal CA — see the separate mtls-ca repo for the CA, device-cert issuing script, and the actual TLS Options definition (Docker labels can only reference a tls.options entry with clientAuth settings, not define one, so it's defined via Traefik's file provider and referenced here with the @file suffix).

haushaltsplan also attaches mtls-ca's pass-client-cert middleware, which forwards the verified cert's CN to the app via the X-Forwarded-Tls-Client-Cert-Info header. The backend (backend/certauth) maps that CN against the parent_cert_cns setting (comma-separated names, matching the CN a cert was issued with in mtls-ca./issue-client-cert.sh "<Name>") to decide whether a request is a parent.

GET /api/me returns {"certCn": ..., "isParent": ...} for the current request's certificate. The frontend uses this to show or hide the "Eltern-Ansicht" toggle — a device without a parent cert never sees it, and can't reach parent-only actions even by calling the API directly, since those are enforced server-side.

Household-admin actions — managing tasks, confirming/rejecting/deleting completions, editing settings (including parent_cert_cns itself), marking weeks/balance paid, and loan tracking — require a parent certificate. Completing a task is the only write a child's device can make.

Bootstrapping the first parent cert: since editing parent_cert_cns is itself a parent-only action, set it once before putting the app behind Traefik in production — either during local development (go run ., which is exempt) or via a direct PUT /api/settings call before APP_ENV=production is set, e.g.:

curl -X PUT http://localhost:8080/api/settings \
  -H "Content-Type: application/json" \
  -d '{"parent_cert_cns": "<Name>"}'

where <Name> matches the CN the cert was issued with. Add more parents later from the Settings tab in the parent view itself.

In production (APP_ENV=production, e.g. the Docker image), any write request without a client certificate at all — no cert, or the host port reached directly instead of through Traefik's mTLS gate — gets a 403. Local dev has no Traefik in front, so it's exempt from this check.

API overview

Method Path Description
GET /api/health Health check ({"status":"ok","database":"connected"}, 503 if the DB ping fails)
GET /api/version Git commit hash baked in at build time ({"version":"<hash>"}, "unknown" outside Docker)
GET /api/tasks List all tasks
POST /api/tasks Create task
PUT /api/tasks/:id Update task
DELETE /api/tasks/:id Delete task
POST /api/tasks/:id/complete Child marks task done
GET /api/completions List completions (filter by ?week= and ?status=)
POST /api/completions/:id/confirm Parent confirms
POST /api/completions/:id/reject Parent rejects
GET /api/summary Weekly summary (coins, allowance)
GET /api/settings Read settings
PUT /api/settings Update settings (parent-only)
GET /api/me Current request's client-cert identity (certCn, isParent)

Environment variables

Variable Default Description
DB_PATH ./haushaltsplan.db Path to the SQLite database file
APP_ENV (unset) Set to production to enforce the client-certificate gate (see Access control)

Default settings (first run)

Setting Default Description
parent_cert_cns (empty) Comma-separated CNs of client certs recognized as a parent
base_allowance 500 (= 5.00 €) Weekly base allowance in cents
coin_value 50 (= 0.50 €) Value of one earned coin in cents