Skip to content

What runs the work.

The destination for everything eventually. Free tiers get a project launched; they are not where it lives.

Docker
Compose file in the repository from the first commit, so "run it somewhere else" is never a project.
Cloudflare Tunnel
Exposes a homelab service without opening a port or renting a static IP.
Umami
Self-hosted analytics. Shipping third-party tracking to a community organisation's members is not a trade worth making.
Linux, WSL2
Most development happens against WSL2. FinanceFlow ships a bridge script because the filesystem boundary is a real problem, not a footnote.

Owned formats, in the repository, with a migration history somebody can read.

PostgreSQL
The default. Portable, boring, outlives the host it started on.
Drizzle ORM
Schema as TypeScript, migrations as files. Moving providers is a connection string.
SQLite via sql.js
Where a single file is enough and a native build step is not worth the friction.
Cloudflare R2
S3-compatible on purpose. Media is the most expensive thing to be locked into.

Whatever the problem shape asks for. Occasionally that is nothing at all.

TypeScript
Default language for anything that will be read again.
Next.js
Most of the web work. App Router, server components where they earn it.
Astro
This site. Static by default, with one server route for the contact endpoint.
Kotlin, Jetpack Compose
Android, when the thing belongs on a device.
No build step
The Wolt splitter is three HTML files. A bundler would have added failures it does not otherwise have.

Babysitting a capable system is the job. Most of the leverage is in what you write down before it starts.

CLAUDE.md per repository
Project rules committed next to the code, so the constraints are version-controlled rather than re-explained.
DESIGN.md, PRODUCT.md, GOTCHAS.md
FinnaRenewer carries all three. The gotchas file is the one that saves the most time, from both a human and an agent.
Tight scopes
A task specified loosely enough to wander will be wandered through. Context is finite and expensive.

Where things live until the homelab takes them.

Vercel
Launch host for the Next.js work. Cron for FinnaRenewer, and the least portable dependency in the stack.
Cloudflare Pages
Static fronts.
Netlify
The no-build projects, deployed straight from the repository.
GitHub Actions
Deploys on push. No dashboard-only configuration.
Sentry
Errors from phase one. A failure nobody hears about is a failure that keeps happening.