The short brief
For agents
If you are an agent building an interface with Ink, you need four things: what to load, the token and class vocabulary, the icons, and the rules you must not break. All of it is also in SKILL.md.
Setup
What to load
ink-design/
dist/ink.css Paper + Night, flattened, self-contained
dist/CHECKSUMS sha256, for a pinned vendored copy
fonts/ 8 woff2 + 2 OFL license texts — copy all of it
src/icons/*.svg the drawn icons — inline them, never <img>
SKILL.md this briefLink ink.css, put ink-paper or ink-night on <html>, and copy fonts/ next to it. With no stored choice, use Night when prefers-color-scheme is dark, and set the class before first paint, so the page is drawn once, not twice.
<!DOCTYPE html>
<html lang="en" class="ink-paper"> <!-- or ink-night; follow the OS until chosen -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="ink.css">
</head>
<body>
<main class="ink-page">
<div class="ink-runninghead"><span>Walden</span><span>Solitude</span></div>
<div class="ink-prose"><p>…</p></div>
<div class="ink-folio">Page 113 of 268</div>
</main>
<nav class="ink-pager" aria-label="Pages">
<button class="ink-btn ink-btn--icon">…<span class="ink-visually-hidden">Previous page</span></button>
<span class="ink-pager__label" aria-live="polite">Page 113 of 268</span>
<button class="ink-btn ink-btn--icon">…<span class="ink-visually-hidden">Next page</span></button>
</nav>
</body>
</html>Vocabulary
Tokens: semantics only
surfaces --surface-canvas --surface-raised --surface-sunk --surface-inverse
text --text-heading --text-body --text-secondary --text-inverse
non-text --mark-muted (idle marks, never type) --rule (decorative) --rule-strong
controls --border-control --focus-ring --selected-fill / --on-selected
levels --gray-0..15 (for tokens only; components never name one)
space --space-1..9 radius --radius-s|m|pill
stroke --stroke (1px) --stroke-control (2px) --stroke-focus (3px)
type --font-book (Lora) --font-ui (Atkinson Hyperlegible Next)
--weight-body|ui|heading|strong --size-label|caption|ui|body|lead|h3|h2|h1|title
--leading-tight|ui|body --measure
target --hit (48px)
motion none, by designThree that will catch you out
--mark-muted is for leader dots and idle marks. Never set type in it; use --text-secondary, which clears 7:1.
--border-control, not --rule, for the edge of anything interactive.
There are no motion, shadow or color tokens. Their absence is the design.
Vocabulary
The class list, complete
modes html.ink-paper html.ink-night [+ .ink-full for pure paper and pure ink]
type .ink-title .ink-h1 .ink-h2 .ink-h3 .ink-lead .ink-body .ink-secondary .ink-italic
.ink-ui .ink-caption .ink-caps .ink-link
prose .ink-prose .ink-dropcap .ink-quote .ink-dinkus (hr) .ink-rule [--strong] (hr)
reading .ink-page .ink-runninghead .ink-folio .ink-pager .ink-pager__label
.ink-progress (style="--at: 40%") .ink-toc .ink-toc__title .ink-toc__page .ink-end
actions .ink-btn [--primary --quiet --icon --wide] .ink-chip (aria-pressed)
surfaces .ink-card [--sunk] .ink-list .ink-list__hint
forms .ink-field .ink-label .ink-hint .ink-input (aria-invalid)
.ink-check > input + .ink-check__box
.ink-switch > input + .ink-switch__track + .ink-switch__state
feedback .ink-notice [--note] .ink-notice__glyph .ink-notice__actions
icons .ink-icon [--l --xl]
utility .ink-visually-hiddenVariants are --modifier; state is an ARIA attribute or a native checked. Anything not on this list does not exist. In particular there is no .ink-toast, .ink-modal, .ink-carousel, .ink-skeleton or .ink-badge, and there will not be.
Art
Icons: inline the file
bookbookmarkcheckclosecontentslightmenumoonnextpenprevsearchtype<!-- paste the contents of src/icons/bookmark.svg -->
<button class="ink-btn ink-btn--icon"><svg class="ink-icon" viewBox="0 0 24 24" …>…</svg><span class="ink-visually-hidden">Bookmark this page</span></button>Constraints
Not negotiable
- Use only the sixteen gray levels, through semantic tokens. No hue, no
rgba(), nocolor-mix(), no partial opacity. Components read tokens like--text-secondary, never--gray-4, so markup works in both modes. - Nothing moves. No
transition,animation,@keyframesor smooth scroll. Change state in one step. The pressed inversion is built in. - Page long content; don’t scroll it. Use
.ink-pageand.ink-pagerwith the count in view, keep the controls in the same place on every page, and finish with.ink-end. No infinite feeds, no carousels. - Nothing soft. No gradient,
box-shadow,text-shadow, blur or filter. Separate things with a rule, a border or space. - Nothing on hover. Every control is visible and labeled at rest, at least 48px (
--hit). - Nothing updates itself. No ticking clocks, live counters, shimmering skeletons or polling. No modal on load, no toast, no
role="alert", noaria-live="assertive", nosetInterval, no autoplay, noautofocus. A notice sits where the person caused it. - Meaning never rests on gray alone. Say it in words; then use shape, fill and border style. Dashed means look again. A switch shows On or Off as text.
- No red, no punishment. A problem is
aria-invalid="true"(dashed edge) plus a hint that says what to do. Offer undo after anything that changes something. - Lora for reading, Atkinson Hyperlegible Next for operating. No weight below 400 anywhere. Long text goes in
.ink-prose, on a plain surface. - No emoji. Inline an icon from
src/icons/(book, bookmark, check, close, contents, light, menu, moon, next, pen, prev, search, type),aria-hidden="true", with the meaning in the text or a visually hidden label. If none fits, draw one the same way: 24-unit grid, 2-unitcurrentColorstroke on whole coordinates, round caps and joins, no fills. - Never load anything over a network, and never disable pinch zoom.
Most of these are checked: run npm run check. If a requirement you have been given conflicts with one of them, say so rather than resolving it quietly. The conflict is usually the most useful thing you have found.
Copy
Write it like this
Page 3 of 12 not Keep going! Only 9 left!
That’s the end of the chapter. not Next chapter starts in 5… 4… 3…
Bookmarked. Page 113. not Saved! (a toast that slides in)
Your notes didn’t sync. Nothing not ERROR: Sync failed
is lost.
This book ends on page 268. not Invalid inputPlain, quiet and exact, like the front matter of a good book. Sentence case. Say where the person is and what is there; never hurry them, never count down, never cheer.