Files
verdande/docs/editions.md
T
kristianwindandClaude Opus 5 6154e6b247 feat(udgaver): urd — noter-udgaven siger sit eget navn
Verdande og Urd er to af nornerne i Völuspá, og digtet har dem skære
mærker i træ: *skáru á skíði*. Verdande er det der bliver; Urd er det der
blev, og blev gemt. En instans startet uden opgaveruterne er et andet
produkt for den der bruger den, så den siger et andet navn.

Navnet læses fra udgaven i ÉT sted — Config.ProductName/ProductSlug —
frem for at stå skrevet i teksterne. Frontend-bygget er byte-identisk i
begge udgaver; serveren omdøber de to filer, browseren læser før noget
JavaScript kører.

Der er to titler, og det blev først klart, da e2e-prøven sagde det:
skallens <title>, som serveren omdøber, og rutens egen i <svelte:head>,
som appen sætter bagefter og som overskriver den første. Go-prøven var
grøn over de bytes, serveren sendte, mens fanen sagde "Noter · verdande".
Begge prøver spørger nu om begge.

Omdøbningen er ankret på hele strenge frem for på ordet "verdande", fordi
app.html også indeholder localStorage.getItem('verdande:theme'). Omdøbes
præfikset der og ikke i resten af appen, bliver temaet sat fra én nøgle og
læst fra en anden, og det eneste symptom er det hvide blink, det
indlejrede script findes for at undgå. Tre plantede fejl bekræfter, at det
er de rigtige prøver, der fanger det: et flyttet anker i app.html, en bred
søg-erstat, og en applyRebrands uden fejlretur.

Mailen var det vigtigste sted. appName var et felt med en værdi og ingen
læser, og kommentaren ved siden af sagde, at det stod i hver besked — de
tre steder havde ordet skrevet ud i stedet. En invitation fra en
urd-instans går til et andet menneskes indbakke.

Også omdøbt: web-manifestet (og sendt som application/manifest+json — Go
kender ikke .webmanifest og sniffer den til text/plain, hvorefter
browseren ignorerer manifestet uden at sige noget, og installationsknappen
bare ikke er der), mærket i menuen (ᚢ uruz frem for ᚹ wunjo),
opstartsloggen, passkey-promptens visningsnavn, ICS-kalendernavnet og
udseendet, der er opkaldt efter programmet.

Ikonet er IKKE med: icon.svg er stadig ᚹ, og de tre PNG'er genereres fra
den. Det rører binære, genererede filer og hører i sin egen ændring.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-07 01:11:25 +02:00

3.1 KiB

Two editions: verdande and urd

One program, built once, with two faces.

verdande urd
What it is Tasks, projects and notes Notes
VERDANDE_EDITION full (the default) notes
Routes served 200 171
Mark ᚹ ᚢ

Set VERDANDE_EDITION=notes and the instance is urd: the task routes are not mounted, the sidebar has no way to them, search answers with notes only, and the program calls itself urd in its tab, its wordmark and its web manifest.

Why one codebase and not a fork

The two share everything that is hard: accounts, sessions, passkeys, sharing, invitations, the realtime socket, search, the backup format, the migrations. Notes are about a twentieth of the Go in this repository and reference no task type; tasks reference no note type. A fork would have duplicated the other nineteen twentieths in order to separate the one — and then every security fix would have needed applying twice, by hand, forever.

So the split is a configuration value read in one place, and the thing that keeps it honest is a test rather than a convention: TestNotesEditionServesOnlyItsOwnRoutes walks both routers, compares them against a written-down list of the 29 withheld routes, and fails in both directions — a route that appears in the notes edition and a route that stops being withheld are both a failure.

An unknown value refuses to start

VERDANDE_EDITION=note, Notes and none are all rejected at startup, by name, rather than being treated as "not notes".

The silent direction is the dangerous one here. An operator who sets up an instance for notes and mistypes the value would otherwise get every task route served on it, with no error anywhere and no way to tell from the outside.

What urd does not have

The 29 withheld routes are tasks, sub-tasks, labels, saved filters, reminders, the upcoming and delegated views, and the task half of search and export. Everything else is the same program:

  • accounts, invitations, passkeys and two-factor
  • projects — which in urd are what a note belongs to
  • per-note sharing with other people, independent of projects
  • search, over notes
  • export, of notes
  • the mail, calendar and MCP surfaces, minus their task routes

The name

Verðandi and Urðr are two of the three Norns in Völuspá, and the poem has them cutting marks into wood — the act of writing something down. Verdande is what is becoming; Urd is what has become and was kept.

An instance started without the task routes is a different product to the person using it, so it says a different name. That name is read from the configuration in one place (Config.ProductName), which is why there is no build-time flag and no second frontend: the frontend is byte-identical in both editions, and the server renames the two files a browser reads before any JavaScript runs — the HTML shell's title and the web manifest.

!!! note "The beacon counts them separately" Both editions report the same two values once a day — instance id and version — and nothing else; see The install count. The edition is not in the payload, so the count does not distinguish them.