carlos / todomvc-bakeoff Public
đŸ¤– AGENTS.md: todo-go
The CARLOS bakeoff's TodoMVC, in Go. Live at https://todo-go.bfj.oncarlos.com (Carloku app todo-go, account bfj).
The one rule
Every page works as plain HTML forms first. The server renders the whole app, and every change is a form POST answered with a 303. The JavaScript in web/static/app.js only sends those same POSTs in the background and swaps in the HTML the server sends back. If a feature can't be done with JavaScript off, it is done differently, not skipped.
BRIEF.md and CONTRACT.md at the repo root are binding; this file adds what is specific to the Go build.
Tenancy declaration
| Question | Answer | |---|---| | What is one instance? | The whole app. One process, one SQLite file, one unix socket | | How do people reach it? | Anonymously. A visitor's first request sets a random cookie (256 bits), and that cookie is their list. No sign-in, no accounts | | Where is each list kept? | In the one SQLite file, each row keyed by the SHA-256 of the visitor's cookie. The app never stores the cookie itself, so a copy of the database can't be used to open anyone's list | | Trust class | C, chosen 2026-10-23: todo titles are stored as plain text, readable by the server and by anyone holding the database or its replicas. A todo list for a public demo doesn't justify server-blind encryption | | Benefits claimed | Hibernation (the instance sleeps when idle and starts in milliseconds), replication of the one file by the platform | | Costs accepted | A list lives as long as its cookie: clear cookies and the list is gone, and there is no way to move a list between browsers. Every list shares one file, so there is no per-visitor export or erasure beyond "delete by cookie hash" |
Rules
- One static binary,
CGO_ENABLED=0. SQLite throughmodernc.org/sqlite. - Migrations in
internal/todo/store.goonly ever add. Never edit or remove a shipped migration; append a new one. - Every query that touches a todo names the caller's list. An id that isn't in the caller's list is a 404.
- Titles are rendered by
html/template, never as raw HTML. - JavaScript is one small ES module with no build step. Keep it under 300 lines.
- Servers bind
127.0.0.1only. Don't changeGOCACHE;make build-arm64 COLD=1passes-ainstead.