Skip to content
sign in

==> 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.

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.

  • One cookie, cs-prefs, on .clusterstuck.sh so 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; NULL is 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.
  • Three cookie names and the code that kept them in step become one; prefs.ts keeps 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 writes cs-prefs from the account, or the visitor chooses again.
  • 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.