How this site works.
I run everything you see here: six sections, one program, one server. This page explains what that program does, the decisions behind it, and how I know it still works after a change.
What it is
The site is one program written in Rust. A visitor asks for a page, the program reads what it needs from a small database, fills in an HTML template and sends back a finished page. There is no app to install, no front-end framework to keep up with, and no front-end build step: the browser gets the page as the server wrote it.
That choice keeps a page light on a phone on mobile data, and keeps the whole thing small enough for one person to run. Everything below follows from it.
For a technical reader
Rust and Axum, SQLite through sqlx, Askama templates, and HTMX with hx-boost for navigation. Images live in S3-compatible object storage. Sign-in is a WebAuthn passkey or a name and PIN. Five of the six sections share one header and one stylesheet; the drinks games carry their own. 27 database migrations run automatically at startup: 24 for the site's database and 3 for the drinks games' own.
What happens when you open a page
Four steps on one server; the drawings themselves come from object storage.
- step 1 The front door nginx handles the encrypted connection, limits how fast anyone can try to sign in, and tells browsers to keep the site's static files for a year.
- step 2 The program One Rust binary matches the address to a section and checks whether you are allowed to see it.
- step 3 The data Text and numbers come from SQLite on the same machine; drawings come from object storage.
- step 4 The page A template is filled in and sent as finished HTML. The one exception is the sorting board, which the browser draws from the day's plan.
The six sections
Five of them share the site's header and stylesheet. Drinks is a separate part of the same program, with its own templates, database and sign-in.
| Section | What it does | Who can use it |
|---|---|---|
| Drawing Portfolio/artportfolio | A feed of my drawings, grouped by month and filterable by tag or collection. | Anyone. Admins upload. |
| Drawing Tasks/tasks | Practice prompts attached to reference images, filterable by subject, difficulty and type. | Anyone can read it. Admins manage it. |
| Drinks/drinks | Four party games in one room — pick a name and PIN, then join with a room code. Live standings, and a big-screen view for the room. | Anyone, after picking a name and PIN. |
| Fitness Tracker/fitness | A food log with calorie and macro targets, a week view, and barcode scanning in the phone camera. | Signed in, and private per person. |
| Sorting/sorting | Crate sort and van load — a pick checklist, a live loading diagram, and the counts checked against each other. | Signed in; built for a tablet. |
| CV/cv | My CV, in Norwegian, with a print-ready PDF. | Anyone. |
A worked example: uploading a drawing
Uploading used to take 39 seconds. Nothing was removed — the slow work was moved out of the wait.
- in the browser On the admin form, the picture is converted to WebP before it leaves the device, so the server never converts what the browser already can.
- during the upload The file is stored, the row is written, and the finished card comes back. At this point I can close the tab.
- nobody waits A second format, AVIF, is slower to produce, so it is made in the background and used from the next page load. If it fails, the page still works.
The rule I took from it: if a step does not change what the person sees next, it does not belong in the wait. The same rule shapes the rest of the site — images reserve their space before they load, so the page does not jump as they arrive, and the first image on a feed is given priority while the rest load as you scroll.
Who can see what
Sections like the food log hold personal data, so who may see what is decided in one place, and every page behind a sign-in names the rule it uses.
Sees the public drawings, the practice board, the CV and this page, and can join the drinks games with a name and PIN. A page behind the site's sign-in sends them to sign in.
Signs in with a name and PIN on an account the owner created, and gets their own food log and their own sorting plans. A member cannot see anyone else's.
Manages drawings and the practice board: admins upload, caption, tag and set visibility. Being signed in is not enough on its own.
One account. Creates accounts, resets PINs, grants admin. An admin cannot do any of those, so nothing granted can be turned back on the owner.
For a technical reader
Four session extractors, one per rule — OptionalAdmin never refuses, AuthSession wants any account, RequireAdmin an admin, RequireOwner the owner — so picking the wrong one is visible in the handler's signature. A visitor without a session is sent to sign in. A signed-in account that lacks the rule gets a 404 rather than a 403, since a 403 would confirm the page exists. Every function that reads a post takes a required viewer argument, so forgetting it is a compile error rather than a leak. A site account's PIN attempts are counted in the database: 5 wrong ones lock that account for 15 minutes, and a restart does not clear the count.
How I build it
How I use AI. I design the solution first — the data model, the boundaries, the failure cases, what has to be tested — then hand Claude Code a precise brief to implement it. Because I know the technology and where it usually goes wrong, the brief names the right constraints up front, so the first pass lands close and there are few rounds of correction. That keeps both cycle time and token cost low. Review is scaled to risk: I weigh how critical a change is and how likely it is to go wrong. Routine, low-stakes work gets a quick check; anything that reaches live users, touches security or data, or is complex enough to hide errors gets a thorough review — often of the plan, before any code is written.
More about me: CV (in Norwegian).
How I know it still works
A hobby project is where habits are cheap to build. These are the same ones I would bring to a team.
Decisions I would defend
Each one costs something. Knowing what it costs is the point.
What I would change
/tasks and the sign-in page still wear the site's original light look.
/admin and its accounts page are still the old light pages, and their redesign is planned.
The site by keyboard
From any of the site's own pages, every section is one shortcut away: press the two keys, type a few letters, and press Enter.