chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
Colour, so every theme reads the same
A theme is a set of tokens. A component that reaches for a raw colour, or for the accent to mean "important", reads well in the theme it was built against and muddy in the next. Two rules keep every theme consistent by construction.
Surfaces are an elevation ladder
Four neutral surfaces, ordered. In dark themes each step is lighter than the
one below, because a shadow does not read on dark and lightness carries depth.
Use a surface by its rung, never by eye, and never with an alpha (bg-muted/40
composites against whatever is behind it and shifts per theme).
| rung | token | for |
|---|---|---|
| base | bg-background | the page |
| raised | bg-card | a card or panel that floats above the page |
| band | bg-muted | a header, a gutter, a chip, a recessed strip |
| interaction | bg-accent | a hover or a selected row, never a static fill |
accent is a surface here, the brightest neutral, distinct from the semantic
accent below. A selected row is bg-accent; a link is not.
Semantic colours mean one thing
Reserved for their meaning, never for generic emphasis.
| token | means | example |
|---|---|---|
key | a link, a selected or focused thing, neutral information | a branch link, the active tab, a comment verdict |
success | a positive state | an approval, a passing check |
destructive | a blocking or destructive state | a requested change, a failing check, a delete |
foreground / muted-foreground / faint | ordinary text, in three weights | a label, a caption, a timestamp |
A verdict wears its meaning wherever it is shown: approve is success, a
requested change is destructive, a plain comment is key. The review buttons,
the timeline mark and the diff thread all read from one map (verdictLook), so
the three hues never drift apart.
A label is not a link. A branch name in a header is text-foreground on a
bg-muted chip, not text-key; the accent is what a reader clicks.