Table of Contents
Quartermaster
Household budget tracker. FastAPI + HTMX frontend, SQLite backend, managed
with uv. Built to practise zero-based budgeting: every income dollar
should be assigned to a category on the plan side, and reconciled against
real spending on the applied side.
Pages
- Architecture — data model, route map, snapshot semantics, lifecycle states, deviation rules, zero-amount calculation, visual identity
- DevelopmentGuide — prerequisites, setup, run, test, project layout, conventions, throwaway-DB pattern
- Operations — backup script, restore, DB safety rule, alembic hook, /healthz endpoint, structured JSON logs, deploy flow
- Roadmap — shipped features and what's deferred
At a glance
/— the budget configuration (the plan). Sections organised into four collapsible groups: Income, Committed (fixed bills + debt minimums + Primary Debt Target), Savings (sinking funds), and Flexible (food, subscriptions, other)./month/YYYY-MM— a snapshot of the budget for a specific calendar month. Each entry becomes a<details>block: the summary row shows planned (click-to-edit) and applied (derived); expand the row to see its backing ledger of transactions (postings) and add more. Applied is alwayssum(postings.amount), never typed directly. Rows carry deviation tags when edited or added post-snapshot./healthz— unauthenticated health probe. Returns 200{"status":"ok"}when the DB is reachable, 503{"status":"error","detail":<exc-class>}otherwise. Targets the DockerHEALTHCHECKand the platform's container-down alert.- Zero Amount header on both pages. Green when every dollar is assigned, amber when unassigned income remains, red when over-budget. The logo anchors the left of the hero; Applied / Planned flank the big number on month pages.
- Per-entry notes — free-text annotation on every row. Copied through at snapshot time; editable inline.
- Backing transaction ledger — every month entry owns a list of postings (date, amount, optional description and payee). Applied is derived from the ledger. One posting for fixed items like rent, many for variable ones like groceries.
Month lifecycle
Each month moves through three explicit states:
| State | Editable? | Transition |
|---|---|---|
| Planning | yes | Activate → Active |
| Active | yes | Close → Closed (requires applied zero = $0.00) |
| Closed | no | Reopen → Active |
Nothing sweeps automatically. The Primary Debt Target is a hint about where leftover applied dollars belong; filling it is the user's job.
Visual identity
- Typography: Barlow Condensed throughout (weights 300-800 + italic), Barlow proportional as a secondary pair. Tabular lining figures in every numeric column.
- Palette: warm cream paper, warm near-black ink, burgundy accent
(
#732629, sampled from the logo shield). Sage / ochre / indigo for balance / under-spend / new-this-month states. - Layout: ledger-style density. Entry rows carry a 2-pixel progress bar along the bottom border that fills to the applied/planned ratio and overshoots in burgundy when over-budget.
- Brand: the logo's shield encloses a Q, a $, and a
$0— literally the zero-based thesis. It sits in the left column of every zero hero.
Status
Live in production on home-ctr-onyx at
https://quartermaster.unbiasedgeek.com/ since 2026-04-19. Every merge
to main rolls out automatically via .forgejo/workflows/deploy.yml.
Shipped: initial scaffold, monthly snapshot with deviation tags, database
backup script with alembic auto-hook, zero-amount header, section groups
with collapsible headers, sinking funds section, per-entry notes, month
lifecycle with the balance gate, UI redesign in Barlow Condensed + logo,
backing transaction ledger with applied derived from postings,
budget-side inline edit of entry name and amount, /healthz endpoint,
structured JSON logs on stdout with five seed application events for
Loki, production deploy pipeline (Dockerfile, compose.yml, Forgejo
Actions workflow).
See the Roadmap for what's deferred.
Deploy
Production is home-ctr-onyx (homelab). The deploy contract with the
homelab platform is documented on the platform wiki as
PlatformContractQuartermaster.
Platform-side provisioning (DNS for quartermaster.unbiasedgeek.com,
Traefik basic-auth + rate-limit middlewares, /mnt/quartermaster/ bind
mount with nightly restic) is complete. Container side (Dockerfile,
compose.yml, .forgejo/workflows/deploy.yml) lives in the repo; push
to main triggers the deploy workflow which builds + pushes the image
and rolls the container via docker compose against the host's Docker
daemon. See Operations for the flow and required secrets.
Code
Repo: archeious/quartermaster on the self-hosted Forgejo. All work is
issue-driven; branches follow feat/<issue>-<slug>; PRs merge to main
via the API; issues close manually on merge.