Vellum

Minimal design system for jamesatk.in.

Palette

Named colours. Use CSS tokens, not raw hex values.

Typography

Bell MT for content. PT Mono for metadata, UI, and code. Never swap them.

Bell MT — headings & body

h1 · 2rem

The quick brown fox

h2 · 1.5rem

The quick brown fox

h3 · 1.25rem

The quick brown fox

h4 · 1rem

The quick brown fox

h5 · 0.875rem
The quick brown fox
h6 · 0.75rem
The quick brown fox
body · 1.0625rem

Language is the dress of thought, and a clear sentence is a well-fitted garment.

caption · 0.8125rem"Manchester from Kersal Moor" — William Wyld

PT Mono — metadata, UI & code

subtitle · 0.95remHow to persist learning in the age of AI.
date · 0.8rem2026-03-27
tag · 0.7rem
ui label · 0.7remSection title
inline codenpm install

Spacing & Shape

Consistent radii and structural dividers.

Border radius — cards, code blocks, buttons --border-amount: 8px
Nav divider .nav-divider
Heavy rule — post header, section heading 2px solid
Light rule — post hr, table rows 1px solid / 0.2 opacity
Post / index max-width 680px

Components

Live rendered. Hover to see interactive states.

Link — default (animated underline)

a (global) · underline via background-size trick

Link — body / post (red-ochre)

.post__link

Link — external (with arrow)

.post__link.post__link--external

Tags

.post-meta__tag · vergaut border & colour

Inline code

Install with npm install or run make build.

.post__codespan · ecru background

Code block

func greet(name string) string {
    return fmt.Sprintf("Hello, %s", name)
}
.post__pre[data-lang] / .post__code · ecru background, lang label top-right

Blockquote

The hand, the head, and the heart of a craftsman must go together.

.post__blockquote · 3px deep-black left border, italic

Horizontal rule


.post__hr · 1px, 0.2 opacity

Writing list item

.writing-list / .writing-list__link / .writing-list__title / .writing-list__subtitle

Portfolio card

.portfolio-box / .project-name2 · 2px deep-black border, border-radius

Icon buttons

.icon-btn · 1px deep-black border, hover reveals coloured fill

Syntax Highlighting

Kimbie Light via highlight.js. Background overridden to --ecru for palette cohesion.

def fibonacci(n: int) -> list[int]:
    sequence = [0, 1]
    while len(sequence) < n:
        sequence.append(sequence[-1] + sequence[-2])
    return sequence[:n]
type Repository interface {
    FindByID(ctx context.Context, id string) (*User, error)
    Save(ctx context.Context, user *User) error
}

Usage Rules

For porting Vellum to a new surface (Obsidian, Markdeep, etc.), apply these constraints.

  • Page background is always off-white #faf8f4. Never ecru — ecru is a surface colour only.
  • Red ochre is currently the only interactive accent. Use it for links and active states. Do not introduce other accent colours for interactivity.
  • Vergaut is currently for taxonomic elements only — tags, categories, labels. Not for links or buttons.
  • Woad is another accent. Use it if a third accent is genuinely required, or for dark-mode surfaces.
  • Bell MT is the reading font. Use it for all long-form prose and headings. Fallback: Georgia, serif.
  • PT Mono signals metadata, system, or code context. Never use it for running prose. Fallback: monospace.
  • Code blocks and inline code always use an ecru background. On dark surfaces, use a darkened ecru equivalent rather than a pure black terminal look.
  • Borders and rules use deep-black at varying opacity: 100% structural, ~15% subtle containers, ~8% hairlines.
  • Border radius is 8px everywhere. Do not mix radius values.
  • The animated underline on links (CSS background-size transition) is a core interaction pattern — preserve it on any ported theme that supports CSS transitions.