Kingdom.md — Design system (Warm Editorial)
The named-aesthetic spec Task 6 (Blade views) builds against. Produced with Anthropic's
frontend-design discipline (commit to a direction before code) and grounded in
working/2026-06-16-frontend-design-research.md. Success bar: elegant, minimal, fast.
For a read-only markdown viewer, design is the spec.
The commitment (four questions)
- Purpose — A read-only window into a personal markdown corpus (memory, plans, design notes). The reader is the author, reading their own work; reading comfort is the entire job.
- Tone — Warm Editorial. Paper, not dashboard. It should feel like a well-set journal, not a web app.
- Constraints — Server-rendered Blade + hand-written CSS (Tailwind reduced to its Preflight reset — see CSS architecture), minimal Alpine; login-less, no server-side persistence (MVP); fast.
- Differentiation — The markdown is unmistakably the hero; chrome (file tree, kingdom switcher) recedes to near-invisible until reached for. The one thing you remember: it reads like paper.
Reference lineage: Editorial Minimalism (Linear / Swiss-grid — "every pixel earns its place through typography hierarchy, not decoration"), iA Writer ("typography is the interface"), Obsidian's Minimal theme (receding chrome).
Typography
The whole quality ceiling. Get this right and most of the design follows.
- Body — serif:
'Newsreader', Georgia, serif. 17px,line-height: 1.66, warm-ink color. Auditioned 2026-06-16 against Literata / Source Serif 4 / Lora / Vollkorn / Spectral — Newsreader held. - Headings — display serif:
'Spectral', Georgia, serif,font-weight: 500(h1 600). h1 ~31px, h2 ~21px. Chosen 2026-06-16 as the better general-purpose default; Fraunces was a close, well-liked contender, parked as a theme/display face (see Deferred). - Chrome / UI —
'Figtree', ui-sans-serif, system-ui, sans-serif. The sidebar + topbar voice: a warm humanist sans that recedes as interface, distinct from the serif reading voice. Chosen 2026-06-16, replacing the initial IBM Plex Sans (read a touch cold/corporate). - Code / mono —
'IBM Plex Mono', monospace(an iA Writer nod). - Banned (per the
frontend-designskill) — Inter, Roboto, Arial, system fonts, and the over-converged defaults (e.g. Space Grotesk). A characterful body face is the single highest- leverage rule. - Measure — prose capped at ~66ch (
max-width: ~33remat 17px). The sacred measure; see "Measure & code width" below for the one deliberate exception.
Color & theme
Warm paper throughout, one disciplined accent. "Dominant color + sharp accent beats a timid, evenly-distributed palette." Wire as CSS variables.
| Token | Value | Use |
|---|---|---|
| paper | #FAF6EF |
page background |
| paper-raised | #FFFDF8 |
cards, code surfaces |
| sidebar | #F7F1E7 / #F3ECE0 |
chrome surfaces |
| ink | #241F1A / #2F2922 |
headings / body |
| ink-soft | #6B6157 |
secondary, dir labels |
| ink-faint | #9C9286 |
hints, resting chrome |
| accent | #9A3B2E |
claret — active file, title rule, links (used sparingly) |
| line | #E0D7C7 / #E7DFD0 |
hairline borders |
Intentionally a light "paper" surface — a deliberate aesthetic choice, not a theming gap. A dark/sepia variant is a future option, not an MVP requirement.
Layout & chrome
- Reading column is the hero — centered, held to the sacred measure, generous top/side whitespace.
- Sidebar recedes — file tree + kingdom switcher sit in muted warm-grays (
ink-faint), resolving toink-softon hover andaccentwhen active. Quiet until reached for. (Nav mechanics — depth handling, the inline subnav, drill motion — live innav-design.md.) - Frontmatter — rendered as a quiet bordered card (mono, muted) above the article, not a loud banner.
- Hairline borders (
0.5px), full-border rounded corners only (no rounded single-sided accents).
Measure & code width (baked-in decision — 2026-06-16)
"80 columns" and "the sacred measure" govern different content types, so they don't conflict:
- Prose → the ~66ch sacred measure. Long proportional lines hurt the return sweep; this is a readability fact, and it's the default.
- Code blocks → their own, wider width, independent of the prose column. Code must never wrap to 66ch (that mangles it). Render code to ~80 monospace columns — which is visibly wider than 66 proportional chars — via a break-out band (code extends past the text column) or horizontal scroll past 80. This is just correct typography, not a compromise, and it lands exactly what the 80-column crowd wants, where it actually matters.
Motion & speed
- Motion — reserve it for purposeful interactions, not a page-load reveal. (Originally a staggered article fade-up on load; reconsidered — in a server-rendered viewer every doc-open is a page load, so a load reveal would replay on every navigation, which prototyping surfaced as flicker.) The live example is the subnav's directional drill slides. Restraint over flash; this aesthetic earns delight through precision.
- Speed — server-rendered Blade + minimal Alpine is the fast path (the Sublime Text lesson: fast by doing less). The design job is not to betray it — no heavy client JS.
CSS architecture (decisions — 2026-06-18)
How the styling is authored, and how document types are namespaced.
- Hand-written CSS + design tokens, not utility classes. The design system lives in plain CSS
custom properties in
:root(resources/css/app.css), ported from the validateddesign-prototype.html. This bespoke, art-directed look (paper grain, furl/unfurl animation, the break-out code band, the ~66ch measure) reads better as named semantic CSS than as utility-class strings — and the rendered-markdown HTML comes from CommonMark server-side, so it has no classes to hang utilities on anyway (it must be styled by element selector regardless). - Tailwind reduced to its Preflight reset only.
app.cssimportstailwindcss/preflight.css(the cross-browser base reset the CSS depends on — buttonfont: inherit, margin/box-sizing normalization), not the fulltailwindcss(theme tokens + utility engine, both unused). The@tailwindcss/typographyplugin was dropped — the.mdprofile replaced itsproseclass. Net: CSS bundle ~65→20 KB, and the dependency does exactly one honest job. To bring utilities /@apply/theme()back later, re-importtailwindcss/theme.css+utilities.css(or fulltailwindcss); to generate utilities from our palette, move the:roottokens into an@themeblock. - Per-document-type render profiles; chrome stays type-agnostic. The rendered-document
<article>carries a class named for its content type —.mdfor markdown today, with a future renderer (e.g. JSON) dropping in as a sibling.jsonprofile on the same element, sharing the column/measure from.col/.page. The app chrome does not encode document type: the file-tree row class.row.doc(and.subnav-row.doc) means simply "a file node" (vs.dir), agnostic to extension — a.jsonfile is still a.row.doc. Keep type-specific styling in the render profiles, never in the chrome. - Chrome vs prose line-height.
<body>is pinned toline-height: 1.5(the chrome — sidebar/tree/topbar) — a deliberate value, previously inherited by accident from Preflight. The reading pane overrides to the generous 1.66 on.md(the sacred reading rhythm; see Typography).
Set aside (not this aesthetic)
- Maximalist / motion-heavy families; dark-first defaults; gradient-mesh / neon / heavy-shadow atmospherics. Wrong fit for a calm reading surface.
Deferred (config options — post-Task-6)
- Prose reading-width preference — a toggle ("Comfortable" ~66ch default / "Wide"
~80+col) for readers who prefer denser prose. Never auto-detected from viewport — a wide
screen signals the reader's display, not their preference, and auto-widening prose is
exactly the readability anti-pattern the sacred measure prevents. So: the default encodes the
recommendation; the option respects autonomy. Implementation:
localStoragevia Alpine — fully client-side, zero backend, safe under the login-less MVP. Scope beyond Task 6's "beautiful baseline," so tracked here rather than built now. (Surfaced 2026-06-16.) - Frontmatter display style — default is the compact tabulated key/value table (aligned
label column + values). A "paper-form" variant (tiny uppercase label stacked over a larger
serif value, roomy fields — like a filled-in form) was prototyped and liked as an optional
alternative, not the default. Candidate reader preference; same client-side
localStoragemechanism as the reading-width toggle. Exact CSS preserved (commented) inworking/design-prototype.html. (Surfaced 2026-06-16.) - Dark / sepia reading theme — a future variant of the palette above; not an MVP need.
- Fraunces as a display/header face — strongly liked in the 2026-06-16 type audition for headings, but Spectral won as the calmer general-purpose default. Park Fraunces as an optional theme/display face for a future theming layer (it pairs naturally with the dark/sepia variant above — a more expressive "editorial" theme). (Surfaced 2026-06-16.)