==> read the decisions
ADR-0013: One preference cookie, resolved on the server
Status: Accepted (2026-10-14). Supersedes the transport part of ADR-0007; its store and its rules stand. Implemented 2026-10-15. Amended by ADR-0025: signed in, a choice this browser made that the account has not taken yet beats the account.
Context
Section titled “Context”ADR-0007 made the control database the durable store, NULL mean "nobody chose", and three cookies
(cs-color, cs-mode, cs-lang) the pre-paint transport. It also had to accept a static homepage
that could only paint from a client script. With both surfaces rendered on the server (ADR-0012),
the constraint that shaped the transport is gone, and three cookies for one decision is clutter.
Decision
Section titled “Decision”- One cookie,
cs-prefs, on.clusterstuck.shso the homepage and the app share it:v1.<theme>.<mode>.<lang>, an empty field meaning "not chosen". Versioned, so its shape can change without guessing what an old value meant. - Mode follows the operating system until someone chooses, in CSS (
prefers-color-scheme,color-scheme,light-dark()), with no cookie and no script. Only an explicit choice is written. - ADR-0007's rules stand: the database is the durable store and wins whenever it holds a value;
NULLis distinct from the default; a present cookie means a human chose; nothing derived is ever written; the ladder is explicit choice, then derived (Accept-Language), then default. - Signed in, the account wins: the server resolves from the session's stored settings and rewrites the cookie to match. Anonymous, the cookie is all there is.
- Language is never in the URL on the platform. The homepage may take a language path later, for search engines; that is its own decision.
Consequences
Section titled “Consequences”- Three cookie names and the code that kept them in step become one;
prefs.tskeeps the ladder and gains the cookie's parse and format. - No pre-paint script anywhere (ADR-0012).
- A reader of an old
cs-*cookie is not kept: the cutover writescs-prefsfrom the account, or the visitor chooses again.
Alternatives rejected
Section titled “Alternatives rejected”- Anonymous server-side sessions holding preferences. Still needs a cookie to find the session, plus a database row per visitor, bots included.
- localStorage. Per-origin, invisible to the server, and needs the pre-paint script this removes.
- Language in the URL across the platform. Every link and route changes for a gain only a public, indexed page has.