dark · structured · sans · notes · purple · local-first · developer

DESIGN.md inspired by Obsidian

Near-black canvas, near-white text, a single electric-purple CTA and a crystal mark — a local-first knowledge base that looks like the editor it ships.

By webdesignhot · obsidian.md
$ npx @webdesignhot/design-md add obsidian
Learn more about the CLI
Compare to…
try on →
theme
1440 × 900
mobile · 390 × 844
Tokens webdesignhot/0.1
  • bg #0f0f0f
  • bg-deep #0a0a0a
  • surface #161616
  • surface-elev #1f1f1f
  • surface-hover #262626
  • text AAA · 16.5 #eeeeee
  • text-strong #ffffff
  • text-secondary #b0b0b0
  • text-muted #a3a3a3
  • text-faint AA·LG · 4.0 #737373
  • brand AA·LG · 3.4 #7c3aed
  • brand-hover #6d28d9
  • brand-active #5b21b6
  • brand-text #a78bfa
  • brand-text-hover #c4b5fd
  • brand-soft #2a1a4a
  • on-brand #ffffff
  • border — · 1.3 #2a2a2a
  • border-soft #1f1f1f
  • border-strong — · 1.7 #3a3a3a
  • border-brand #7c3aed
  • shadow-ambient rgba(0,0,0,0.40)
  • shadow-card rgba(0,0,0,0.50)
  • shadow-modal rgba(0,0,0,0.70)
  • scrim rgba(0,0,0,0.65)
  • success #4ade80
  • success-soft #14321f
  • warning #fbbf24
  • warning-soft #33270a
  • danger #f87171
  • danger-soft #3a1717
  • info #a78bfa
Typography
Ship faster than ever.
display-hero ui-sans-serif 60px w600 -0.02em
Ship faster than ever.
display-lg ui-sans-serif 48px w600 -0.018em
Ship faster than ever.
h1 ui-sans-serif 40px w600 -0.015em
Built for teams that ship.
h2 ui-sans-serif 32px w600 -0.012em
A complete kit
h3 ui-sans-serif 24px w600 -0.005em
The quick brown fox jumps over the lazy dog.
h4 ui-sans-serif 20px w600 0
The quick brown fox jumps over the lazy dog.
title-lg ui-sans-serif 18px w600 0
The quick brown fox jumps over the lazy dog.
body-lg ui-sans-serif 18px w400 0
The quick brown fox jumps over the lazy dog.
body ui-sans-serif 16px w400 0
The quick brown fox jumps over the lazy dog.
button ui-sans-serif 15px w500 0
The quick brown fox jumps over the lazy dog.
nav-link ui-sans-serif 15px w500 0
The quick brown fox jumps over the lazy dog.
body-sm ui-sans-serif 14px w400 0
npx @webdesignhot/design-md add stripe
code ui-monospace 14px w400 0
OUR DESIGN SYSTEM
label ui-sans-serif 13px w500 0
OUR DESIGN SYSTEM
caption ui-sans-serif 12px w500 0.02em
npx @webdesignhot/design-md add stripe
code-micro ui-monospace 12px w400 0
The quick brown fox jumps over the lazy dog.
overline ui-sans-serif 11px w600 0.08em
Spacing
  • step-0 0px
  • step-1 4px
  • step-2 8px
  • step-3 12px
  • step-4 16px
  • step-5 24px
  • step-6 32px
  • step-7 48px
  • step-8 64px
  • step-9 96px
  • step-10 128px
Radius
  • micro 2px
  • sm 4px
  • md 8px
  • lg 12px
  • xl 16px
  • pill 9999px
Components
Text link →
Card preview A complete kit — everything your product needs. Hero, pricing, FAQ, dashboard, docs — every layout your product needs.
New Stable v1.0
Design roles 6/8 mapped · webdesignhot/0.1

Maps the 8 canonical role names to this entry's actual tokens. Use these to plug the design into role-aware tools — shadcn/ui themes, role-aware Tailwind plugins, atelier-lint — without hard-coding token names.

  • background bg
  • foreground text
  • primary
  • primary-foreground
  • accent brand
  • muted text-muted
  • border border
  • ring brand
Export 4 formats · paste-ready
Tailwind

theme.extend block for tailwind.config.js

tailwind.config.js
CSS variables

:root { --bg, --text, --brand, … } you can paste anywhere

design.css
DTCG JSON

W3C Design Tokens Community Group format

design.tokens.json
Figma Variables

Importable into Figma → Variables → Import

figma-variables.json
The file
---
name: Obsidian
tagline: Near-black canvas, near-white text, a single electric-purple CTA and a crystal mark — a local-first knowledge base that looks like the editor it ships.
updated_at: 2026-05-28T23:12:43.991Z
published_at: 2026-05-28T23:12:43.991Z
author: webdesignhot
source_url: https://obsidian.md
spec: webdesignhot/0.1
quality: curated
featured: false
categories: [saas]
tags: [dark, structured, sans, notes, purple, local-first, developer]
preview_swatch: ['#0f0f0f', '#7c3aed', '#a78bfa']
related: [notion, bear-app, linear]
description: 'Obsidian''s site is the editor it sells, rendered as a marketing page — a near-black `#0f0f0f` canvas, near-white `#eeeeee` body text, and a single electric-purple `#7c3aed` CTA ("Get Obsidian for macOS", `8px` radius, white text) that carries the entire chromatic load. The hero "Sharpen your thinking" sets at 60px / 600 in the platform''s own UI sans (`ui-sans-serif` — no webfont loaded, a deliberate local-first / privacy gesture). The crystal-facet logo is the only ornament. Everything else is dark surface, hairline borders, and disciplined restraint: the page reads as a developer tool that respects your attention, not a SaaS funnel that mines it. Obsidian is the rare site where "your notes are yours" is a design philosophy you can see — no gradients to load, no tracking pixels to dodge, no system font to download.'


# Canonical 8-role aliases (bg / text / brand / border / accent / muted / surface / danger).
# Maps role names to this entry's actual token names so role-aware
# downstream tools resolve `theme.background` → entry's `bg`, etc.
# Auto-generated by scripts/add-aliases.mjs — do not edit manually;
# regenerate after changing color token names.
aliases:
  background: bg
  foreground: text
  accent: brand
  muted: text-muted
  border: border
  ring: brand

colors:
  bg: '#0f0f0f'                  # near-black page canvas — the editor metaphor
  bg-deep: '#0a0a0a'            # deepest well — behind elevated panels, footer
  surface: '#161616'            # raised card / panel surface, one step off canvas
  surface-elev: '#1f1f1f'       # nested card / hovered surface
  surface-hover: '#262626'      # interactive hover fill (ghost button, list row)
  text: '#eeeeee'               # primary body + display copy — near-white, never pure
  text-strong: '#ffffff'        # rare peak — single heaviest display moment
  text-secondary: '#b0b0b0'     # secondary running-text, deck copy
  text-muted: '#a3a3a3'         # captions, metadata, footer links
  text-faint: '#737373'         # disabled / placeholder / fine print
  brand: '#7c3aed'              # electric purple — the single CTA voltage
  brand-hover: '#6d28d9'        # pressed / hover state — one stop darker
  brand-active: '#5b21b6'       # active / depressed CTA
  brand-text: '#a78bfa'         # lightened purple for links/text on dark (AA-safe)
  brand-text-hover: '#c4b5fd'   # hover for purple text links
  brand-soft: '#2a1a4a'         # purple-tinted soft fill for badges/highlights
  on-brand: '#ffffff'           # white text on the purple CTA
  border: '#2a2a2a'             # default hairline divider on dark
  border-soft: '#1f1f1f'        # near-invisible structural divider
  border-strong: '#3a3a3a'      # focused input / emphasized edge
  border-brand: '#7c3aed'       # focus ring + active-input edge
  shadow-ambient: 'rgba(0,0,0,0.40)'   # subtle lift on dark
  shadow-card: 'rgba(0,0,0,0.50)'      # raised card / dropdown
  shadow-modal: 'rgba(0,0,0,0.70)'     # heavy lift for modals/popovers
  scrim: 'rgba(0,0,0,0.65)'            # modal backdrop over canvas
  success: '#4ade80'            # confirmation green
  success-soft: '#14321f'
  warning: '#fbbf24'            # advisory amber
  warning-soft: '#33270a'
  danger: '#f87171'             # form-error red on dark
  danger-soft: '#3a1717'
  info: '#a78bfa'               # informational accent — same family as brand-text

typography:
  display:
    family: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif'
    weights: [500, 600, 700]
    opentype-features: ['kern', 'liga']
  body:
    family: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif'
    weights: [400, 500, 600]
  mono:
    family: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace'
    weights: [400, 500]
  scale:
    display-hero:    { size: 60, weight: 600, lineHeight: 1.05, tracking: '-0.02em',  family: display, opentype: ['kern'] }
    display-lg:      { size: 48, weight: 600, lineHeight: 1.08, tracking: '-0.018em', family: display }
    h1:              { size: 40, weight: 600, lineHeight: 1.10, tracking: '-0.015em', family: display }
    h2:              { size: 32, weight: 600, lineHeight: 1.20, tracking: '-0.012em', family: display }
    h3:              { size: 24, weight: 600, lineHeight: 1.25, tracking: '-0.005em', family: display }
    h4:              { size: 20, weight: 600, lineHeight: 1.30, tracking: '0',        family: body }
    title-lg:        { size: 18, weight: 600, lineHeight: 1.40, tracking: '0',        family: body }
    body-lg:         { size: 18, weight: 400, lineHeight: 1.60, tracking: '0',        family: body }
    body:            { size: 16, weight: 400, lineHeight: 1.55, tracking: '0',        family: body }
    body-sm:         { size: 14, weight: 400, lineHeight: 1.50, tracking: '0',        family: body }
    label:           { size: 13, weight: 500, lineHeight: 1.40, tracking: '0',        family: body }
    button:          { size: 15, weight: 500, lineHeight: 1.20, tracking: '0',        family: body }
    nav-link:        { size: 15, weight: 500, lineHeight: 1.40, tracking: '0',        family: body }
    caption:         { size: 12, weight: 500, lineHeight: 1.40, tracking: '0.02em',   family: body }
    overline:        { size: 11, weight: 600, lineHeight: 1.30, tracking: '0.08em',   family: body, transform: uppercase }
    code:            { size: 14, weight: 400, lineHeight: 1.55, tracking: '0',        family: mono }
    code-micro:      { size: 12, weight: 400, lineHeight: 1.50, tracking: '0',        family: mono }

radius:
  micro: 2
  sm: 4
  md: 8         # the CTA + buttons + inputs — the dominant rounding
  lg: 12        # cards / panels
  xl: 16        # large feature shells / screenshots
  pill: 9999

spacing:
  base: 4
  scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96, 128]

layout:
  page-width: 1280
  prose-width: 720
  header-height: 64
  hero-height: 640

components:
  cta-primary:
    bg: '#7c3aed'
    color: '#ffffff'
    radius: 8
    padding: '10px 16px'
    height: 40
    font: button
    use: 'The signature CTA — "Get Obsidian for macOS". Electric purple, white text, 8px radius. The only saturated element on the page.'
  cta-primary-hover:
    bg: '#6d28d9'
    color: '#ffffff'
    radius: 8
    use: 'Hover — one stop darker purple. No transform, no glow.'
  button-ghost:
    bg: 'transparent'
    color: '#eeeeee'
    border: '1px solid #2a2a2a'
    radius: 8
    padding: '10px 16px'
    height: 40
    font: button
    use: 'Secondary action — outlined ghost on dark. Fill warms to #262626 on hover.'
  button-quiet:
    bg: 'transparent'
    color: '#b0b0b0'
    radius: 8
    padding: '8px 12px'
    use: 'Tertiary / nav-adjacent text button. Text brightens to #eeeeee on hover, no border.'
  cta-platform-split:
    bg: '#7c3aed'
    color: '#ffffff'
    radius: 8
    use: 'The download CTA with an OS-selector caret on the right edge (macOS / Windows / Linux / mobile). Caret region divides with a subtle on-brand hairline.'
  card:
    bg: '#161616'
    color: '#eeeeee'
    border: '1px solid #2a2a2a'
    radius: 12
    padding: '24px'
    use: 'Feature panel — raised one step off canvas via surface tone + hairline, not shadow.'
  card-elev:
    bg: '#1f1f1f'
    color: '#eeeeee'
    border: '1px solid #3a3a3a'
    radius: 12
    use: 'Nested / hovered card — a second tonal step up.'
  input:
    bg: '#0f0f0f'
    color: '#eeeeee'
    border: '1px solid #2a2a2a'
    radius: 8
    height: 40
    padding: '8px 12px'
    placeholder: '#737373'
    focus: 'border becomes #7c3aed (1px) + faint purple ring'
    use: 'Text input — inset darker than card, purple focus edge.'
  badge-soft:
    bg: '#2a1a4a'
    color: '#a78bfa'
    radius: 9999
    padding: '3px 10px'
    font: caption
    use: 'Inline tag / status chip — purple-tinted soft fill, lightened-purple text. Used sparingly ("New", "v1.x").'
  badge-neutral:
    bg: '#1f1f1f'
    color: '#a3a3a3'
    border: '1px solid #2a2a2a'
    radius: 9999
    padding: '3px 10px'
    font: caption
    use: 'Neutral metadata chip — platform / category tags.'
  nav-top:
    bg: '#0f0f0fcc'
    color: '#eeeeee'
    height: 64
    border: '0 0 1px 0 solid #2a2a2a'
    use: 'Sticky top nav — translucent near-black with backdrop blur, hairline bottom border. Crystal mark left, links centre, purple CTA right.'
  link-inline:
    color: '#a78bfa'
    use: 'Inline body link — lightened purple (AA-safe on dark). Underline appears on hover.'

motion:
  ease-standard: 'cubic-bezier(0.4, 0, 0.2, 1)'
  ease-out: 'cubic-bezier(0.0, 0, 0.2, 1)'
  ease-emphasized: 'cubic-bezier(0.2, 0, 0, 1)'
  duration-fast: 150
  duration-standard: 240
  duration-slow: 320
  button-hover: 'background 150ms standard — colour only, no transform'
  link-underline: 'underline fades in over 150ms on hover'
  scroll-reveal: 'sections fade + 8px rise over 320ms ease-out on viewport entry'
  graph-pulse: 'optional node-graph ornament gently animates connection lines — decorative only'
  reduced-motion: 'respects prefers-reduced-motion: reduce — scroll-reveal becomes static render, graph animation pauses, transforms suppressed'

breakpoints:
  mobile: 640
  tablet: 1024
  desktop: 1280
  wide: 1536

shadows:
  ambient: 'rgba(0,0,0,0.40) 0 1px 2px 0'
  card: 'rgba(0,0,0,0.50) 0 8px 24px -8px'
  modal: 'rgba(0,0,0,0.70) 0 24px 64px -16px'
  ring: '0 0 0 3px rgba(124,58,237,0.40)'

accessibility:
  contrast-text-on-bg: 16.5          # #eeeeee on #0f0f0f — AAA
  contrast-text-on-surface: 14.6     # #eeeeee on #161616 — AAA
  contrast-on-brand: 5.7             # #ffffff on #7c3aed — AA (CTA label)
  contrast-brand-on-bg: 3.4          # #7c3aed on #0f0f0f — AA large only (never body text)
  contrast-brand-text-on-bg: 7.0     # #a78bfa on #0f0f0f — AAA (the safe purple for links/text)
  contrast-secondary-on-bg: 8.8      # #b0b0b0 on #0f0f0f — AAA
  contrast-muted-on-bg: 7.6          # #a3a3a3 on #0f0f0f — AAA
  focus-ring: '3px rgba(124,58,237,0.40) ring + 1px solid #7c3aed border on focusable controls'
  reduced-motion-honored: true
  touch-target-min: 40

dark-mode: 'dark-only'   # The marketing site is dark-only — it mirrors Obsidian's default dark editor theme. The app itself ships full light/dark + community themes, but the public site renders near-black canvas exclusively as a brand-identity choice.
---

## 1. Visual Theme & Atmosphere

Obsidian's site is the editor it sells, rendered as a marketing page. The canvas is a near-black `#0f0f0f` — the exact mood of the app's default dark theme — and the body copy sits in a near-white `#eeeeee` that never tips to pure white. The hero, "Sharpen your thinking", sets at 60px in the platform's own UI sans (`ui-sans-serif`) at weight 600 — not 700, not bold-marketing impact, just confident. The single saturated element on the entire page is the electric-purple `#7c3aed` "Get Obsidian for macOS" button at 8px radius. Everything else is dark surface, hairline borders, and the crystal-facet logo. The page does not so much sell you a tool as *show* you the room the tool lives in.

The atmosphere is **developer-tool restraint**: a page built by people who treat your attention as something to be respected rather than harvested. There are no gradient washes to download, no hero video, no animated illustrations beyond an optional gently-pulsing node-graph ornament that nods at Obsidian's signature graph view. The whole composition reads as *quiet competence* — closer to a well-configured terminal or a Linear/Vercel dashboard than to a consumer-SaaS funnel. The single purple CTA does all the chromatic work; remove it and the page would be a pure greyscale study.

The most telling decision is the typography: **no webfont is loaded.** The page renders entirely in `ui-sans-serif` / `system-ui` — San Francisco on Mac, Segoe on Windows, Roboto on Android. This is not laziness; it is the brand's local-first ethos made visible. A product whose entire pitch is "your notes are plain files on your own disk, no cloud required" refuses to make your browser phone home for a font. The page loads instantly, works offline-ish, and tracks nothing — the medium *is* the message.

Colour is rationed with monastic discipline. The palette is a near-black canvas, a near-white ink, a stepped greyscale of surfaces (`#0f0f0f` → `#161616` → `#1f1f1f` → `#262626`), hairline borders in `#2a2a2a`, and exactly one accent: purple. Purple is the brand voltage and the CTA fill; on dark backgrounds where the saturated `#7c3aed` fails contrast as text, it is lightened to a violet `#a78bfa` for links. The page never introduces a second accent. There is no teal, no amber-for-warmth, no blue-for-trust — just purple-on-near-black, the way the crystal logo glints against the editor.

The result is a page that signals its values before you read a word: **dark because that is where focused work happens; system-font because your machine is yours; purple-and-crystal because that is the mark; nothing else, because everything else is noise.** Obsidian is the rare site where "your notes are yours" is a design philosophy you can actually see.

**Key Characteristics:**
- Near-black canvas (`#0f0f0f`) — the app's default dark editor theme, lifted to marketing
- Near-white ink (`#eeeeee`) — never pure white; calmer on dark, hits 16.5:1 AAA contrast
- A single accent — electric purple (`#7c3aed`) — carrying the entire chromatic load
- System UI sans (`ui-sans-serif`), no webfont — the local-first / privacy ethos made literal
- Hero at 60px / weight 600 — confident, not bold-marketing-loud
- Crystal-facet logo as the only ornament; optional pulsing node-graph nod to graph view
- Stepped greyscale surfaces (`#0f0f0f` → `#161616` → `#1f1f1f` → `#262626`) for elevation, not shadow stacks
- Hairline `#2a2a2a` borders define structure; depth comes from tone, not drop shadow
- 8px radius on the CTA / buttons / inputs — crisp, developer-tool corners (not pill, not sharp)
- Purple lightens to `#a78bfa` for text/links on dark (the saturated brand fails AA as small text)
- Page loads instantly and tracks nothing — performance and privacy are aesthetic choices

## 2. Color Palette & Roles

### Primary
- **Canvas** (`#0f0f0f`) [→ `bg`]: near-black page floor — the editor metaphor; the default of everything.
- **Deep Well** (`#0a0a0a`) [→ `bg-deep`]: the darkest tone — behind elevated panels and in the footer.
- **Ink** (`#eeeeee`) [→ `text`]: primary body and display copy — near-white, never pure `#ffffff`.
- **Ink Strong** (`#ffffff`) [→ `text-strong`]: rare; the single heaviest display moment per page.

### Brand
- **Brand Purple** (`#7c3aed`) [→ `brand`]: the one accent — CTA fill, focus edge, the crystal-logo voltage.
- **Brand Hover** (`#6d28d9`) [→ `brand-hover`]: CTA hover — one stop darker.
- **Brand Active** (`#5b21b6`) [→ `brand-active`]: pressed CTA — two stops darker.
- **Brand Soft** (`#2a1a4a`) [→ `brand-soft`]: purple-tinted soft fill for badges and inline highlights.

### Accent
There is no decorative accent beyond purple. The page is greyscale + a single purple voltage. Any "second accent" is a violation of the system.

### Interactive
- **Brand Text** (`#a78bfa`) [→ `brand-text`]: inline links and purple text *on dark* — lightened so it passes AAA where `#7c3aed` would fail. **Use this, not `brand`, for any purple text.**
- **Brand Text Hover** (`#c4b5fd`) [→ `brand-text-hover`]: link hover — lighter still; underline fades in.
- **On-Brand** (`#ffffff`) [→ `on-brand`]: white label on the purple CTA fill.
- **Focus Ring** (`rgba(124,58,237,0.40)`) [→ `border-brand`]: 3px purple ring + 1px purple border on focused controls.
- **Disabled** (`#737373` text on `#161616` fill): drained grey, no purple.

### Neutral Scale
- **Ink Strong** (`#ffffff`) — peak display, single moment per page
- **Ink** (`#eeeeee`) — body, primary display, the dominant text colour
- **Secondary** (`#b0b0b0`) — deck copy, secondary running-text (8.8:1 AAA)
- **Muted** (`#a3a3a3`) — captions, metadata, footer links (7.6:1 AAA)
- **Faint** (`#737373`) — disabled, placeholder, fine print

### Surface & Borders
- **Canvas** (`#0f0f0f`) — page floor
- **Surface** (`#161616`) — raised card / panel, one step off canvas
- **Surface Elev** (`#1f1f1f`) — nested / hovered card, second step
- **Surface Hover** (`#262626`) — interactive hover fill (ghost button, list row)
- **Border** (`#2a2a2a`) — default hairline divider
- **Border Soft** (`#1f1f1f`) — near-invisible structural divider
- **Border Strong** (`#3a3a3a`) — focused input / emphasized edge

### Shadow Colors
Obsidian uses **pure-black** shadows (`rgba(0,0,0,…)`) at higher opacities than a light site would — on a near-black canvas, shadow must be deeper than the surface to register at all. Most surfaces, however, use *no shadow*; elevation is communicated by stepping the surface tone up (`#0f0f0f` → `#161616` → `#1f1f1f`) and adding a `#2a2a2a` hairline. Shadow is reserved for genuinely floating chrome.

- `rgba(0,0,0,0.40) 0 1px 2px 0` — ambient lift (sticky nav at scroll)
- `rgba(0,0,0,0.50) 0 8px 24px -8px` — raised card / dropdown
- `rgba(0,0,0,0.70) 0 24px 64px -16px` — modal / popover

### Semantic
- **Success** (`#4ade80` on `#14321f`) — confirmation green, brightened for dark legibility.
- **Warning** (`#fbbf24` on `#33270a`) — advisory amber.
- **Danger** (`#f87171` on `#3a1717`) — form-error red, softened for dark (a saturated `#dc2626` would vibrate on black).
- **Info** (`#a78bfa` on `#2a1a4a`) — informational accent — *intentionally* the same violet as the link colour. Obsidian treats "information" and "brand" as one voice.

## 3. Typography Rules

### Font Family

**Display & Body (one family)**: `ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif`. There is **no webfont**. Display and body share the system UI sans — they differ only by weight and size, never family. On macOS this resolves to San Francisco, on Windows to Segoe UI, on Android to Roboto. The page deliberately uses whatever native sans the reader's OS provides.

**Mono**: `ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace` — used for code samples, file paths (`~/vault/notes.md`), and any moment that demonstrates Obsidian's plain-text-files-on-disk pitch.

**OpenType features**: `kern` and `liga` on, inherited from the system face. No custom stylistic sets — the brand uses the OS font exactly as the OS ships it.

The single-family decision is the brand's typographic fingerprint, and it is doing ideological work. Most note-apps load a webfont to feel "designed" (Bear ships two in-house cuts; Notion loads its own sans). Obsidian's refusal to load *any* webfont is the most on-brand move on the page: a local-first product that won't make your browser fetch a remote asset to render a marketing headline. The type looks "designed" by being calm and well-spaced, not by being bespoke.

### Hierarchy

| Role | Font | Size | Weight | Line Height | Letter Spacing | OT Features | Notes |
|------|------|------|--------|-------------|----------------|-------------|-------|
| display-hero | system sans | 60 | 600 | 1.05 | -0.02em | kern | Hero "Sharpen your thinking" — peak moment (live-probed at 60/600) |
| display-lg | system sans | 48 | 600 | 1.08 | -0.018em | — | Large section opener |
| h1 | system sans | 40 | 600 | 1.10 | -0.015em | — | Page / section heading |
| h2 | system sans | 32 | 600 | 1.20 | -0.012em | — | Sub-section opener |
| h3 | system sans | 24 | 600 | 1.25 | -0.005em | — | Feature title |
| h4 | system sans | 20 | 600 | 1.30 | 0 | — | Card title |
| title-lg | system sans | 18 | 600 | 1.40 | 0 | — | Inline emphasis title |
| body-lg | system sans | 18 | 400 | 1.60 | 0 | — | Hero deck — slightly larger body |
| body | system sans | 16 | 400 | 1.55 | 0 | — | Default running-text (live-probed at 16/400) |
| body-sm | system sans | 14 | 400 | 1.50 | 0 | — | Card meta, secondary copy |
| label | system sans | 13 | 500 | 1.40 | 0 | — | Form label, small UI label |
| button | system sans | 15 | 500 | 1.20 | 0 | — | CTA / button label |
| nav-link | system sans | 15 | 500 | 1.40 | 0 | — | Top-nav item |
| caption | system sans | 12 | 500 | 1.40 | 0.02em | — | Timestamp, fine metadata |
| overline | system sans | 11 | 600 | 1.30 | 0.08em | uppercase | Section eyebrow |
| code | mono | 14 | 400 | 1.55 | 0 | — | Code / file-path sample |
| code-micro | mono | 12 | 400 | 1.50 | 0 | — | Inline `⌘P`-style shortcut bubble |

### Principles

- **One family, no webfont.** Display and body are the same system UI sans, differing only by weight/size. Loading a webfont would betray the local-first ethos — don't.
- **Display tops out at weight 600, not 700.** The hero is confident, not loud. Weight 600 at 60px reads as "engineered" rather than "marketed". Pushing to 700/800 tips the page toward generic startup-bold.
- **Near-white ink, never pure white.** Body copy is `#eeeeee` — on a near-black canvas, pure `#ffffff` vibrates and fatigues. The slightly-off white is calmer and still hits 16.5:1 AAA.
- **Negative tracking on display only.** Hero `-0.02em`, h1 `-0.015em`, tapering to `0` by h4. Body and below stay at `0`; only the tiny caption/overline get positive tracking.
- **16px body at 1.55 line-height.** Comfortable web body, generous leading — the editor's own reading rhythm.
- **Mono for anything plain-text.** File paths, code, shortcuts render in `ui-monospace` — the page makes the product's core promise (plain `.md` files on disk) typographic.
- **Inter is the closest substitute** if a build can't use the system sans. Inter at weight 400/600 approximates SF / Segoe cleanly. Never substitute a serif or a "designer" sans — the point is system-native neutrality.

## 4. Component Stylings

### Buttons

**`cta-primary`** — The signature CTA. Electric-purple `#7c3aed` fill, white text at 15px / 500, **8px radius**, 10×16px padding, 40px height. This is the only saturated element on the page — "Get Obsidian for macOS". Everything visual on the page funnels to this one button.

**`cta-primary-hover`** — Pointer hover. Fill darkens to `#6d28d9` over 150ms standard. **No transform, no scale, no glow** — colour only. Active state goes to `#5b21b6`.

**`cta-platform-split`** — The download CTA with an OS-selector caret (macOS / Windows / Linux / iOS / Android). The caret region is divided from the label by a subtle on-brand hairline; clicking the caret opens a small dropdown of platform options.

**`button-ghost`** — Secondary action. Transparent fill, `#eeeeee` text, 1px `#2a2a2a` border, 8px radius. On hover the fill warms to `#262626` (no border change). Used for "Read the docs", "Browse plugins".

**`button-quiet`** — Tertiary / nav-adjacent text button. No border, no fill; `#b0b0b0` text that brightens to `#eeeeee` on hover. Used for utility links ("Sign in", "Sync", "Pricing").

### Cards

**`card`** — Feature panel. `#161616` fill (one tonal step off canvas), `#eeeeee` text, 1px `#2a2a2a` hairline border, **12px radius**, 24px padding. **No shadow** — the surface step plus hairline is the elevation language. Inside: h4 title in `#eeeeee`, body in `#b0b0b0`.

**`card-elev`** — Nested or hovered card. `#1f1f1f` fill, `#3a3a3a` border — a second tonal step up. Used for cards-within-cards (a plugin card inside a feature panel) or as the hover state of `card`.

**`feature-screenshot`** — App screenshot of the editor itself (showing the dark theme with purple accents — the page literally pictures itself). 16px radius, optional `rgba(0,0,0,0.50) 0 8px 24px -8px` shadow to float it off the canvas.

### Badges, Tags, Pills

**`badge-soft`** — Purple-tinted chip. `#2a1a4a` fill, `#a78bfa` text, 9999px radius, 3×10px padding, 12px caption. Used sparingly for "New", version tags, "Free". The only place soft purple appears outside the CTA.

**`badge-neutral`** — Neutral metadata chip. `#1f1f1f` fill, `#a3a3a3` text, 1px `#2a2a2a` border, pill radius. Platform tags (macOS / Windows / Linux), category labels in the plugin directory.

### Inputs / Forms

**`input`** — Text input. `#0f0f0f` fill (inset *darker* than the surrounding card — the field reads as "below" the surface), `#eeeeee` text, 1px `#2a2a2a` border, 8px radius, 40px height, 8×12px padding. Placeholder in `#737373`. On focus, the border becomes `#7c3aed` (1px) with a faint `rgba(124,58,237,0.40)` 3px ring. Newsletter / search / vault-name fields.

**`select` / `dropdown`** — Same chassis as input; chevron in `#a3a3a3`. Open panel uses `card` surface (`#161616`) with `shadow-card`.

### Navigation

**`nav-top`** — Sticky top nav, 64px height. Translucent near-black (`#0f0f0fcc`) with a backdrop blur so content blurs behind it on scroll, and a 1px `#2a2a2a` bottom hairline. **Crystal-facet logo + "Obsidian" wordmark** flush left in `#eeeeee` — the logo is the only ornament in the chrome. Centre: nav links (Features, Pricing, Plugins, Docs) in 15px / 500 `#eeeeee`. Right: a `button-quiet` ("Sign in") + the purple `cta-primary` ("Download").

**`nav-link`** — `#eeeeee` at rest, no underline. Hover brings a subtle `#a78bfa` underline / colour lift. Active page link sits at full `#ffffff`.

**`footer`** — `#0a0a0a` deep-well background, column heads in 13px / 600 `#eeeeee`, links in 14px / 400 `#a3a3a3`. The crystal mark reappears, muted. Multi-column: Product / Community / Resources / Company.

### Decorative

**`graph-ornament`** — An optional node-graph SVG (nodes + connecting edges) that nods at Obsidian's signature graph view. Edges may gently pulse / draw on viewport entry. Rendered in muted purple (`#a78bfa` at low opacity) on the canvas. Purely decorative — `aria-hidden="true"`.

## 5. Layout Principles

### Spacing System

- Base unit: **4px**
- Scale: `0 · 4 · 8 · 12 · 16 · 24 · 32 · 48 · 64 · 96 · 128`
- Section padding (vertical): 96–128px between major bands — generous, lets the dark canvas breathe
- Card internal padding: 24px on feature cards; 16px on compact list rows
- Inter-card gutters: 24px in feature grids
- The dark canvas does a lot of the spacing work — empty near-black space reads as deliberate, not unfinished

### Grid & Container

- Max content width: **1280px** — standard modern marketing width, wider than Bear's magazine-tight 1080px
- Prose / reading column: 720px for long-form (docs, blog)
- Hero: single-column, centred — H1 + deck + the purple CTA + an editor screenshot beneath
- Feature grid: 3-up at desktop → 2-up at tablet → 1-up at mobile
- 24px gutters; the grid sits inside the 1280px container with generous side margins on wide screens

### Whitespace Philosophy

On a near-black canvas, **negative space is the primary compositional tool.** Where a light site fills space with subtle tints and borders, Obsidian leaves the canvas dark and empty — the void reads as focus, not absence. Surfaces (cards) appear only where there is content to hold; between them is pure `#0f0f0f`. This is the editor's own aesthetic: a dark workspace where the only bright things are the words you wrote and the one action you can take.

### Section Cadence

A typical Obsidian page runs:

1. **Hero** — 60px / 600 H1 ("Sharpen your thinking"), 18px deck in `#b0b0b0`, purple `cta-primary` with OS-selector, editor screenshot floating beneath (optional graph-ornament behind)
2. **Feature spread** — 3-up cards on the dark canvas (Local files, Links & graph, Plugins) — each a `#161616` panel with hairline border
3. **Graph showcase** — the signature node-graph view, large, with a short caption — the product's most recognizable surface
4. **Plugins / community** — grid of plugin cards, neutral badges, a "Browse 2,000+ plugins" ghost button
5. **Sync / Publish band** — the paid tiers, presented as calm feature cards, not aggressive pricing tables
6. **Closing CTA band** — a centred restatement of the purple CTA over empty canvas
7. **Footer** — deep-well `#0a0a0a`, muted multi-column links, crystal mark

The page does not alternate light/dark — it is dark throughout. The "alternation" is canvas (`#0f0f0f`) vs. card surface (`#161616`) tonal contrast.

## 6. Shapes & Radius Scale

| Tier | Value | Use |
|------|-------|-----|
| Micro | 2px | Inline code chips, tiny indicators |
| Small | 4px | Nested elements, fine controls |
| Standard | 8px | CTA, buttons, inputs — the dominant rounding |
| Comfortable | 12px | Cards, panels |
| Large | 16px | Feature shells, app screenshots |
| Pill | 9999px | Badges, neutral chips |

Obsidian's radius hierarchy is **developer-tool crisp** — the dominant 8px on buttons and inputs is the modern-app sweet spot: rounded enough to feel finished, sharp enough to feel engineered (not the soft 12–16px of consumer apps, not the pill-everything of marketing sites). Cards step to 12px; the largest shells and screenshots to 16px. Pill radius is reserved for badges only — the page never makes a pill button, because a pill CTA would read as "consumer", and Obsidian is positioning as a serious tool.

## 7. Depth & Elevation

| Level | Treatment | Use |
|-------|-----------|-----|
| 0 — Canvas | no shadow, `#0f0f0f` | The page floor, hero, empty space (~70% of surface) |
| 1 — Surface | tonal step to `#161616` + 1px `#2a2a2a` hairline, no shadow | Feature cards, panels |
| 2 — Elevated surface | tonal step to `#1f1f1f` + `#3a3a3a` border | Nested / hovered cards |
| 3 — Floating | `rgba(0,0,0,0.40) 0 1px 2px 0` | Sticky nav at scroll, subtle inputs |
| 4 — Raised | `rgba(0,0,0,0.50) 0 8px 24px -8px` | Dropdowns, popovers, screenshots |
| 5 — Modal | scrim `rgba(0,0,0,0.65)` + `rgba(0,0,0,0.70) 0 24px 64px -16px` | Sign-in / vault dialog |

### Shadow Philosophy

On a near-black canvas, **shadow is a weak signal** — a `rgba(0,0,0,…)` shadow against `#0f0f0f` is barely darker than the floor it sits on. So Obsidian inverts the usual elevation strategy: **depth is communicated by stepping the surface *lighter*, not by casting a shadow darker.** A raised card is `#161616` (lighter than canvas) with a hairline border; a more-raised card is `#1f1f1f`. Shadow is reserved for chrome that genuinely floats over content (dropdowns, modals, the sticky nav), and even then it is used at high opacity (0.50–0.70) purely so it registers at all. The hairline `#2a2a2a` border, not the shadow, is what draws the eye to a surface edge. This is the dark-mode elevation discipline that Linear, Vercel, and well-built developer dashboards all share.

## 8. Interaction & Motion

### Easing

- **Standard**: `cubic-bezier(0.4, 0, 0.2, 1)` — default for hover colour swaps, border transitions
- **Out**: `cubic-bezier(0.0, 0, 0.2, 1)` — scroll-reveal entrances
- **Emphasized**: `cubic-bezier(0.2, 0, 0, 1)` — modal entry, dropdown open

### Durations

| Bucket | Value | Use |
|--------|-------|-----|
| Fast | 150ms | Button hover, link underline, focus-ring fade |
| Standard | 240ms | Card hover, dropdown open, border transitions |
| Slow | 320ms | Scroll-reveal, modal entry, graph-line draw |

### Per-Component Recipes

- **CTA hover**: fill `#7c3aed` → `#6d28d9` over 150ms standard. **No transform, no scale.** Active → `#5b21b6`.
- **Ghost button hover**: transparent → `#262626` fill over 150ms; border unchanged.
- **Card hover**: surface lifts a tonal step (`#161616` → `#1f1f1f`) and border brightens (`#2a2a2a` → `#3a3a3a`) over 240ms. No translate.
- **Link hover**: colour `#a78bfa` → `#c4b5fd`; underline fades in over 150ms.
- **Focus**: 3px `rgba(124,58,237,0.40)` ring + 1px purple border appears over 150ms on keyboard focus.
- **Scroll-reveal**: sections fade in + rise 8px over 320ms ease-out on first viewport entry. One-shot.
- **Graph ornament**: connection edges gently draw / pulse — decorative, low-amplitude, never demands attention.

### Page Transitions

Navigation is a quiet 240ms cross-fade; the sticky nav stays fixed. Anchored links smooth-scroll over 320ms emphasized. Nothing is showy — motion exists to soften state changes, not to perform.

### Reduced Motion

Respects `prefers-reduced-motion: reduce`. Scroll-reveal becomes static render-on-mount (no fade, no rise). The graph-ornament animation pauses to a static frame. Hover transforms (none exist) and all translate/scale are suppressed. Colour-only transitions (button hover, link colour) may remain since they don't induce motion.

## 9. Accessibility & A11y

### Contrast Pairs

| Pair | Ratio | Level |
|------|-------|-------|
| #eeeeee ink on #0f0f0f canvas | 16.5 | AAA |
| #eeeeee ink on #161616 surface | 14.6 | AAA |
| #ffffff label on #7c3aed CTA | 5.7 | AA (passes for the 15px/500 button label) |
| #7c3aed brand on #0f0f0f | 3.4 | **AA large only — never use as body text** |
| #a78bfa brand-text on #0f0f0f | 7.0 | AAA — the safe purple for links / small text |
| #b0b0b0 secondary on #0f0f0f | 8.8 | AAA |
| #a3a3a3 muted on #0f0f0f | 7.6 | AAA |

The critical accessibility nuance: **the brand purple `#7c3aed` only reaches 3.4:1 on the canvas** — it passes for large UI and as a button fill (with white text), but it *fails* as small purple text on dark. The page therefore uses the lightened `#a78bfa` (7.0:1, AAA) for every inline link and purple text run. Treating `brand` and `brand-text` as two distinct tokens is not optional polish — it is what keeps the dark theme readable.

### Focus Indicators

Focus is a 3px `rgba(124,58,237,0.40)` ring plus a 1px solid `#7c3aed` border on the focused control. On the dark canvas the semi-transparent purple ring is clearly visible against `#0f0f0f` without being garish. Focus is never removed; keyboard and pointer users get the same target.

### ARIA Patterns

- **Top nav**: `<nav>` landmark with `aria-label="Primary"`. The crystal logo is an `<img alt="Obsidian">` linking home.
- **Platform-split CTA**: the OS-selector caret is a `<button aria-haspopup="menu" aria-expanded>`; the dropdown is `role="menu"` with `role="menuitem"` per platform.
- **Plugin grid**: each card is a link with an accessible name; neutral badges are decorative text, not separate controls.
- **Graph ornament**: `aria-hidden="true"` — purely visual.
- **Modal** (sign-in / vault): focus trap, Esc closes, click-outside closes, focus returns to trigger.

### Keyboard Navigation

- Top nav: Tab logo → Features → Pricing → Plugins → Docs → Sign in → Download
- Platform-split CTA: Tab to the button; Enter downloads default OS; the caret button opens the menu, arrow keys navigate platforms
- Cards: Tab moves card → card; Enter activates the link
- Modal: Tab cycles within the dialog only

### Screen Reader Hints

The crystal logo carries `alt="Obsidian"`. App screenshots carry descriptive alt text ("Obsidian editor in dark theme, a note open with a backlinks panel and the graph view in the sidebar"). The graph ornament is `aria-hidden`. The CTA's accessible name includes the platform ("Download Obsidian for macOS").

### Reduced Motion

All entrance animations degrade to static render. The graph ornament freezes. Colour-only hover transitions may remain. No essential information is conveyed by motion alone.

## 10. Responsive Behavior

### Breakpoints

| Name | Width | Key Changes |
|------|-------|-------------|
| Mobile | <640px | Nav collapses to logo + hamburger; hero h1 drops 60 → 36px; CTA goes full-width; feature cards 1-up; graph ornament hidden |
| Tablet | 640–1024px | Inline nav links may persist; hero h1 at ~44px; feature cards 2-up; screenshot at 90% width |
| Desktop | 1024–1280px | Full nav; hero h1 at 60px; feature cards 3-up; screenshot up to 1100px |
| Wide | >1280px | Content caps at 1280px; canvas absorbs the extra width as empty near-black margin |

### Touch Targets

- Purple CTA: 40px height; on mobile it goes full-width for an easy thumb target (44px+ effective row)
- Nav links: minimum 44×44px hit area in the mobile sheet
- Plugin / feature cards: the whole card is the tap target
- Inputs: 40px height, 44px+ effective with padding

### Collapsing Strategy

- Top nav links collapse into a hamburger sheet below 640px; the purple CTA stays visible in the collapsed bar
- Feature grids: 3 → 2 → 1 columns
- The graph-view showcase scales down; on mobile it may switch to a simpler static node image to keep payload light (the no-webfont/perf ethos carries into imagery)
- App screenshots scale by viewport, never crop; 16px radius scales proportionally

### Image Behavior

Editor screenshots render at 2x as PNG/WebP with 16px radius and optional `rgba(0,0,0,0.50)` shadow. They scale `width: 100%; height: auto`. Because the canvas is dark and the screenshots *are* of the dark editor, screenshots blend seamlessly into the page — there is no light-on-dark seam to manage.

### Container Queries

Used on the platform-split CTA: when the available width is too narrow for "Get Obsidian for macOS" + caret, the label shortens to "Download" and the OS name moves into the dropdown.

## 11. Content & Voice

### Tone

Plainspoken, technical, quietly confident. Obsidian's voice trusts the reader to be the kind of person who wants their notes as plain files — it doesn't over-explain, doesn't hype, doesn't use exclamation marks. Headlines are short imperatives or claims ("Sharpen your thinking", "Your thoughts are yours", "A second brain, for you, forever"). The copy assumes competence and rewards it.

### Microcopy Patterns

- **Button verbs**: "Get Obsidian", "Download", "Read the docs", "Browse plugins" — direct, outcome-named
- **Error message recipe**: `[What went wrong] + [What to try]` — e.g., "Couldn't open that vault. Check the folder still exists, then try again."
- **Success confirmations**: short, factual — "Synced." / "Vault created."
- **Field labels**: minimal — "Email", "Vault name" — no friendly framing

### Empty States

The empty-vault state in screenshots: "Create your first note." — single declarative line. The paid-feature gate (Sync / Publish): "Obsidian Sync keeps your vault in sync across devices. Try it free." — names the value, offers the path, no pressure.

### CTA Verb Conventions

- Primary action: **"Get Obsidian"** / **"Download"** (with OS selector)
- Secondary action: **"Read the docs"**, **"Browse plugins"**, **"Learn more"**
- Tertiary text: **"Sign in"**, **"See pricing"**, **"Join the community"**
- Avoided: "Get started free!", "Sign up now", "Click here", "Buy" — Obsidian uses calm outcome verbs, never funnel-urgency

## 12. Dark Mode & Theming

**Dark-only marketing surface.** The public site renders exclusively on the near-black `#0f0f0f` canvas — it mirrors Obsidian's default dark editor theme as a deliberate brand-identity choice. This is the inverse of most sites (which are light-only and ship a dark *app*): here the *site* is dark because the *brand* is dark, and the dark editor is the product's most recognizable face.

The app itself, by contrast, ships a full theming system — light and dark base themes plus a large community-theme ecosystem and per-vault CSS snippets (theming your own vault is a core feature). The marketing site does not expose a light toggle; it commits to dark to *show* the default experience.

If a light variant were ever shipped, the token swap would be: canvas `#ffffff`, surface `#f6f6f6`, ink `#1a1a1a`, border `#e5e5e5`, brand purple **unchanged** at `#7c3aed` (it passes AA as a CTA fill on white and is legible as text on light, so the `brand-text` lightening would no longer be needed). The greyscale stack would simply invert; the single purple accent would carry over intact.

## 13. Lineage & Influences

Obsidian's design sits at the intersection of three traditions. First, the **developer-tool dark aesthetic** — the near-black canvas, hairline-bordered surfaces, single-accent restraint, and system-font neutrality that Linear, Vercel, and well-built dashboards share. Second, the **local-first / plain-text software movement** — the lineage of iA Writer, Roam Research, TiddlyWiki, and the broader "your data in open formats on your own disk" ethos, where the refusal to load a webfont or a tracker is itself a design statement. Third, the **personal-knowledge-management (PKM) tradition** — the Zettelkasten method, wikis, and the graph-of-linked-notes idea that Obsidian's signature graph view makes visible.

The most distinctive — and most ideological — design decision is the absence of a webfont. Where Bear ships two in-house typefaces and Notion loads a custom sans, Obsidian renders entirely in the reader's own system UI font. For a product whose entire pitch is "your notes are plain Markdown files on your own machine, no cloud required, no lock-in", a marketing page that makes your browser phone home for a font would be a contradiction. The system-font choice, the instant load, and the zero tracking are the same value expressed three ways: *your machine, your data, your attention — ours to respect, not to harvest.*

What Obsidian rejects: gradient washes, hero video, animated illustrations, a second accent colour, pill CTAs, urgency microcopy, and webfonts. The page is dark, near-monochrome, system-set, and funnels to a single purple button — the visual equivalent of a clean plain-text file.

**Influences:**
- Linear — dark-canvas developer-tool aesthetic; hairline surfaces, single-accent restraint, [linear.app](https://linear.app)
- Vercel — near-black canvas, system-font neutrality, crisp 8px-radius developer chrome, [vercel.com](https://vercel.com)
- iA Writer — plain-text-as-craft, local files, typographic restraint as positioning, [ia.net/writer](https://ia.net/writer)
- Roam Research — networked-thought / linked-notes lineage and the graph-of-ideas paradigm, [roamresearch.com](https://roamresearch.com)
- TiddlyWiki — single-file, local-first, own-your-data personal-wiki heritage, [tiddlywiki.com](https://tiddlywiki.com)

## 14. Do's and Don'ts

**Do**
- Keep the canvas near-black at `#0f0f0f` — it is the editor metaphor and the brand floor
- Use `#eeeeee` for body text, never pure `#ffffff` — the off-white is calmer on dark and still AAA
- Let the single purple `#7c3aed` CTA carry the entire chromatic load — everything funnels to it
- Render in the system UI sans (`ui-sans-serif`) with no webfont — it is the local-first ethos made visible
- Set the hero at weight 600, not 700 — confident, not bold-marketing-loud
- Lighten purple to `#a78bfa` for any text/links on dark — the saturated brand fails AA as small text
- Step surfaces lighter (`#0f0f0f` → `#161616` → `#1f1f1f`) for elevation, not darker shadows
- Define structure with `#2a2a2a` hairline borders, not drop shadows
- Use 8px radius on buttons and inputs — developer-tool crisp
- Keep the crystal mark as the only ornament; if you add a graph-view nod, keep it muted and decorative
- Ration negative space generously — empty near-black canvas reads as focus, not absence

**Don't**
- Don't introduce a second accent colour — purple is the entire chromatic system
- Don't load a webfont — it contradicts the local-first / privacy ethos the brand sells
- Don't use the saturated `#7c3aed` as small purple text on dark — it fails AA; use `#a78bfa`
- Don't use pure white `#ffffff` for body copy — it vibrates against the near-black canvas
- Don't make the hero weight 700/800 — keep it 600, engineered not loud
- Don't pile up drop shadows for depth — on dark, lighter surface tone is the elevation signal
- Don't make a pill-shaped CTA — pill reads "consumer"; Obsidian is positioning as a serious tool
- Don't add gradient washes, hero video, or animated illustration beyond the muted graph nod
- Don't use urgency microcopy ("Sign up now!", "Limited time") — the voice is calm and trusting
- Don't add tracking pixels or analytics theatre — the page's restraint is the message
- Don't tint the canvas blue or warm — near-neutral near-black is the brand floor

## 15. Agent Prompt Guide

### Quick Color Reference

```
Canvas:       #0f0f0f   (near-black page floor)
Deep well:    #0a0a0a   (footer, behind elevated panels)
Surface:      #161616   (raised card, one step off canvas)
Surface-elev: #1f1f1f   (nested / hovered card)
Ink:          #eeeeee   (body + display, never pure white)
Secondary:    #b0b0b0   (deck copy, secondary text)
Muted:        #a3a3a3   (captions, footer links)
Brand:        #7c3aed   (the one accent — CTA fill only)
Brand-text:   #a78bfa   (purple text/links on dark — AA-safe)
Border:       #2a2a2a   (hairline divider)
On-brand:     #ffffff   (white label on the purple CTA)
```

### Example Component Prompts

- "Create an Obsidian-style hero: near-black canvas (#0f0f0f), a 60px / weight-600 headline 'Sharpen your thinking' in the system UI sans (ui-sans-serif, NO webfont) in #eeeeee with -0.02em tracking and 1.05 line-height. Below: an 18px / 400 deck in #b0b0b0 at 1.6 line-height. Below that: a single electric-purple (#7c3aed) CTA button 'Get Obsidian for macOS', white text at 15px/500, 8px radius, 10×16px padding, with a small OS-selector caret on the right edge. No second accent, no gradient, no webfont. Optionally a muted purple (#a78bfa low-opacity) node-graph SVG floating behind."
- "Design an Obsidian feature card: #161616 fill (one tonal step off the #0f0f0f canvas), 1px #2a2a2a hairline border, 12px radius, 24px padding, NO shadow. Inside: a 20px/600 title in #eeeeee, then 16px/400 body in #b0b0b0 at 1.55 line-height. On hover, lift the surface a tonal step to #1f1f1f and brighten the border to #3a3a3a over 240ms — no translate."
- "Build the Obsidian top nav: 64px tall, translucent near-black (#0f0f0fcc) with backdrop-blur and a 1px #2a2a2a bottom hairline. Left: a crystal-facet logo + 'Obsidian' wordmark in #eeeeee. Centre: nav links (Features, Pricing, Plugins, Docs) in 15px/500 #eeeeee with a subtle #a78bfa underline on hover. Right: a quiet text 'Sign in' link in #b0b0b0, then the purple (#7c3aed) 'Download' CTA at 8px radius."
- "Create an Obsidian text input: #0f0f0f fill (inset DARKER than the surrounding #161616 card), #eeeeee text, 1px #2a2a2a border, 8px radius, 40px height, placeholder in #737373. On focus, set the border to #7c3aed (1px) plus a 3px rgba(124,58,237,0.40) ring."
- "Design an Obsidian inline link + soft badge: links in lightened purple #a78bfa (NOT the saturated #7c3aed — it fails AA on dark) with an underline that fades in on hover toward #c4b5fd. A soft badge: #2a1a4a fill, #a78bfa text, pill radius (9999px), 3×10px padding, 12px caption — used sparingly for 'New' or a version tag."
- "Build an Obsidian closing CTA band: centred on the bare #0f0f0f canvas with generous vertical padding (96–128px), a 32px/600 #eeeeee restatement headline, and the single purple (#7c3aed) 'Get Obsidian' CTA at 8px radius. Nothing else — the empty near-black space is the design."

### Iteration Guide

1. **One accent, always.** Purple is the entire chromatic system. If you find yourself reaching for a second colour, you've left the brand — express the variation in greyscale tone instead.
2. **No webfont, ever.** Render in `ui-sans-serif` / `system-ui`. Loading a font betrays the local-first ethos and is the single fastest way to make the page "not Obsidian".
3. **Two purples, two jobs.** `#7c3aed` is for fills (the CTA); `#a78bfa` is for purple *text* on dark. Swapping them breaks contrast — the saturated purple as small text fails AA.
4. **Off-white, not white.** Body is `#eeeeee`. Pure `#ffffff` vibrates on the near-black canvas and reads as a beginner mistake.
5. **Elevation goes lighter, not darker.** Lift a surface by stepping its tone up (`#0f0f0f` → `#161616` → `#1f1f1f`) and adding a hairline — not by casting a shadow that barely registers on black.
6. **Hero weight 600, not 700.** Keep display confident and engineered. The moment it goes bold-marketing, it stops being Obsidian and starts being a generic startup.
7. **Let the dark breathe.** Negative near-black space is the primary compositional tool. Resist the urge to fill it with tints, gradients, or decoration — the void is the focus.
8. **Calm voice, no urgency.** Microcopy is plainspoken and trusting ("Get Obsidian", "Read the docs"). Never "Sign up now!", never exclamation marks, never a pill CTA.

---

*Theme-toggle audit: score=0, signals=[none]*
Prose

1. Visual Theme & Atmosphere

Obsidian’s site is the editor it sells, rendered as a marketing page. The canvas is a near-black #0f0f0f — the exact mood of the app’s default dark theme — and the body copy sits in a near-white #eeeeee that never tips to pure white. The hero, “Sharpen your thinking”, sets at 60px in the platform’s own UI sans (ui-sans-serif) at weight 600 — not 700, not bold-marketing impact, just confident. The single saturated element on the entire page is the electric-purple #7c3aed “Get Obsidian for macOS” button at 8px radius. Everything else is dark surface, hairline borders, and the crystal-facet logo. The page does not so much sell you a tool as show you the room the tool lives in.

The atmosphere is developer-tool restraint: a page built by people who treat your attention as something to be respected rather than harvested. There are no gradient washes to download, no hero video, no animated illustrations beyond an optional gently-pulsing node-graph ornament that nods at Obsidian’s signature graph view. The whole composition reads as quiet competence — closer to a well-configured terminal or a Linear/Vercel dashboard than to a consumer-SaaS funnel. The single purple CTA does all the chromatic work; remove it and the page would be a pure greyscale study.

The most telling decision is the typography: no webfont is loaded. The page renders entirely in ui-sans-serif / system-ui — San Francisco on Mac, Segoe on Windows, Roboto on Android. This is not laziness; it is the brand’s local-first ethos made visible. A product whose entire pitch is “your notes are plain files on your own disk, no cloud required” refuses to make your browser phone home for a font. The page loads instantly, works offline-ish, and tracks nothing — the medium is the message.

Colour is rationed with monastic discipline. The palette is a near-black canvas, a near-white ink, a stepped greyscale of surfaces (#0f0f0f#161616#1f1f1f#262626), hairline borders in #2a2a2a, and exactly one accent: purple. Purple is the brand voltage and the CTA fill; on dark backgrounds where the saturated #7c3aed fails contrast as text, it is lightened to a violet #a78bfa for links. The page never introduces a second accent. There is no teal, no amber-for-warmth, no blue-for-trust — just purple-on-near-black, the way the crystal logo glints against the editor.

The result is a page that signals its values before you read a word: dark because that is where focused work happens; system-font because your machine is yours; purple-and-crystal because that is the mark; nothing else, because everything else is noise. Obsidian is the rare site where “your notes are yours” is a design philosophy you can actually see.

Key Characteristics:

  • Near-black canvas (#0f0f0f) — the app’s default dark editor theme, lifted to marketing
  • Near-white ink (#eeeeee) — never pure white; calmer on dark, hits 16.5:1 AAA contrast
  • A single accent — electric purple (#7c3aed) — carrying the entire chromatic load
  • System UI sans (ui-sans-serif), no webfont — the local-first / privacy ethos made literal
  • Hero at 60px / weight 600 — confident, not bold-marketing-loud
  • Crystal-facet logo as the only ornament; optional pulsing node-graph nod to graph view
  • Stepped greyscale surfaces (#0f0f0f#161616#1f1f1f#262626) for elevation, not shadow stacks
  • Hairline #2a2a2a borders define structure; depth comes from tone, not drop shadow
  • 8px radius on the CTA / buttons / inputs — crisp, developer-tool corners (not pill, not sharp)
  • Purple lightens to #a78bfa for text/links on dark (the saturated brand fails AA as small text)
  • Page loads instantly and tracks nothing — performance and privacy are aesthetic choices

2. Color Palette & Roles

Primary

  • Canvas (#0f0f0f) [→ bg]: near-black page floor — the editor metaphor; the default of everything.
  • Deep Well (#0a0a0a) [→ bg-deep]: the darkest tone — behind elevated panels and in the footer.
  • Ink (#eeeeee) [→ text]: primary body and display copy — near-white, never pure #ffffff.
  • Ink Strong (#ffffff) [→ text-strong]: rare; the single heaviest display moment per page.

Brand

  • Brand Purple (#7c3aed) [→ brand]: the one accent — CTA fill, focus edge, the crystal-logo voltage.
  • Brand Hover (#6d28d9) [→ brand-hover]: CTA hover — one stop darker.
  • Brand Active (#5b21b6) [→ brand-active]: pressed CTA — two stops darker.
  • Brand Soft (#2a1a4a) [→ brand-soft]: purple-tinted soft fill for badges and inline highlights.

Accent

There is no decorative accent beyond purple. The page is greyscale + a single purple voltage. Any “second accent” is a violation of the system.

Interactive

  • Brand Text (#a78bfa) [→ brand-text]: inline links and purple text on dark — lightened so it passes AAA where #7c3aed would fail. Use this, not brand, for any purple text.
  • Brand Text Hover (#c4b5fd) [→ brand-text-hover]: link hover — lighter still; underline fades in.
  • On-Brand (#ffffff) [→ on-brand]: white label on the purple CTA fill.
  • Focus Ring (rgba(124,58,237,0.40)) [→ border-brand]: 3px purple ring + 1px purple border on focused controls.
  • Disabled (#737373 text on #161616 fill): drained grey, no purple.

Neutral Scale

  • Ink Strong (#ffffff) — peak display, single moment per page
  • Ink (#eeeeee) — body, primary display, the dominant text colour
  • Secondary (#b0b0b0) — deck copy, secondary running-text (8.8:1 AAA)
  • Muted (#a3a3a3) — captions, metadata, footer links (7.6:1 AAA)
  • Faint (#737373) — disabled, placeholder, fine print

Surface & Borders

  • Canvas (#0f0f0f) — page floor
  • Surface (#161616) — raised card / panel, one step off canvas
  • Surface Elev (#1f1f1f) — nested / hovered card, second step
  • Surface Hover (#262626) — interactive hover fill (ghost button, list row)
  • Border (#2a2a2a) — default hairline divider
  • Border Soft (#1f1f1f) — near-invisible structural divider
  • Border Strong (#3a3a3a) — focused input / emphasized edge

Shadow Colors

Obsidian uses pure-black shadows (rgba(0,0,0,…)) at higher opacities than a light site would — on a near-black canvas, shadow must be deeper than the surface to register at all. Most surfaces, however, use no shadow; elevation is communicated by stepping the surface tone up (#0f0f0f#161616#1f1f1f) and adding a #2a2a2a hairline. Shadow is reserved for genuinely floating chrome.

  • rgba(0,0,0,0.40) 0 1px 2px 0 — ambient lift (sticky nav at scroll)
  • rgba(0,0,0,0.50) 0 8px 24px -8px — raised card / dropdown
  • rgba(0,0,0,0.70) 0 24px 64px -16px — modal / popover

Semantic

  • Success (#4ade80 on #14321f) — confirmation green, brightened for dark legibility.
  • Warning (#fbbf24 on #33270a) — advisory amber.
  • Danger (#f87171 on #3a1717) — form-error red, softened for dark (a saturated #dc2626 would vibrate on black).
  • Info (#a78bfa on #2a1a4a) — informational accent — intentionally the same violet as the link colour. Obsidian treats “information” and “brand” as one voice.

3. Typography Rules

Font Family

Display & Body (one family): ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif. There is no webfont. Display and body share the system UI sans — they differ only by weight and size, never family. On macOS this resolves to San Francisco, on Windows to Segoe UI, on Android to Roboto. The page deliberately uses whatever native sans the reader’s OS provides.

Mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace — used for code samples, file paths (~/vault/notes.md), and any moment that demonstrates Obsidian’s plain-text-files-on-disk pitch.

OpenType features: kern and liga on, inherited from the system face. No custom stylistic sets — the brand uses the OS font exactly as the OS ships it.

The single-family decision is the brand’s typographic fingerprint, and it is doing ideological work. Most note-apps load a webfont to feel “designed” (Bear ships two in-house cuts; Notion loads its own sans). Obsidian’s refusal to load any webfont is the most on-brand move on the page: a local-first product that won’t make your browser fetch a remote asset to render a marketing headline. The type looks “designed” by being calm and well-spaced, not by being bespoke.

Hierarchy

RoleFontSizeWeightLine HeightLetter SpacingOT FeaturesNotes
display-herosystem sans606001.05-0.02emkernHero “Sharpen your thinking” — peak moment (live-probed at 60/600)
display-lgsystem sans486001.08-0.018emLarge section opener
h1system sans406001.10-0.015emPage / section heading
h2system sans326001.20-0.012emSub-section opener
h3system sans246001.25-0.005emFeature title
h4system sans206001.300Card title
title-lgsystem sans186001.400Inline emphasis title
body-lgsystem sans184001.600Hero deck — slightly larger body
bodysystem sans164001.550Default running-text (live-probed at 16/400)
body-smsystem sans144001.500Card meta, secondary copy
labelsystem sans135001.400Form label, small UI label
buttonsystem sans155001.200CTA / button label
nav-linksystem sans155001.400Top-nav item
captionsystem sans125001.400.02emTimestamp, fine metadata
overlinesystem sans116001.300.08emuppercaseSection eyebrow
codemono144001.550Code / file-path sample
code-micromono124001.500Inline ⌘P-style shortcut bubble

Principles

  • One family, no webfont. Display and body are the same system UI sans, differing only by weight/size. Loading a webfont would betray the local-first ethos — don’t.
  • Display tops out at weight 600, not 700. The hero is confident, not loud. Weight 600 at 60px reads as “engineered” rather than “marketed”. Pushing to 700/800 tips the page toward generic startup-bold.
  • Near-white ink, never pure white. Body copy is #eeeeee — on a near-black canvas, pure #ffffff vibrates and fatigues. The slightly-off white is calmer and still hits 16.5:1 AAA.
  • Negative tracking on display only. Hero -0.02em, h1 -0.015em, tapering to 0 by h4. Body and below stay at 0; only the tiny caption/overline get positive tracking.
  • 16px body at 1.55 line-height. Comfortable web body, generous leading — the editor’s own reading rhythm.
  • Mono for anything plain-text. File paths, code, shortcuts render in ui-monospace — the page makes the product’s core promise (plain .md files on disk) typographic.
  • Inter is the closest substitute if a build can’t use the system sans. Inter at weight 400/600 approximates SF / Segoe cleanly. Never substitute a serif or a “designer” sans — the point is system-native neutrality.

4. Component Stylings

Buttons

cta-primary — The signature CTA. Electric-purple #7c3aed fill, white text at 15px / 500, 8px radius, 10×16px padding, 40px height. This is the only saturated element on the page — “Get Obsidian for macOS”. Everything visual on the page funnels to this one button.

cta-primary-hover — Pointer hover. Fill darkens to #6d28d9 over 150ms standard. No transform, no scale, no glow — colour only. Active state goes to #5b21b6.

cta-platform-split — The download CTA with an OS-selector caret (macOS / Windows / Linux / iOS / Android). The caret region is divided from the label by a subtle on-brand hairline; clicking the caret opens a small dropdown of platform options.

button-ghost — Secondary action. Transparent fill, #eeeeee text, 1px #2a2a2a border, 8px radius. On hover the fill warms to #262626 (no border change). Used for “Read the docs”, “Browse plugins”.

button-quiet — Tertiary / nav-adjacent text button. No border, no fill; #b0b0b0 text that brightens to #eeeeee on hover. Used for utility links (“Sign in”, “Sync”, “Pricing”).

Cards

card — Feature panel. #161616 fill (one tonal step off canvas), #eeeeee text, 1px #2a2a2a hairline border, 12px radius, 24px padding. No shadow — the surface step plus hairline is the elevation language. Inside: h4 title in #eeeeee, body in #b0b0b0.

card-elev — Nested or hovered card. #1f1f1f fill, #3a3a3a border — a second tonal step up. Used for cards-within-cards (a plugin card inside a feature panel) or as the hover state of card.

feature-screenshot — App screenshot of the editor itself (showing the dark theme with purple accents — the page literally pictures itself). 16px radius, optional rgba(0,0,0,0.50) 0 8px 24px -8px shadow to float it off the canvas.

Badges, Tags, Pills

badge-soft — Purple-tinted chip. #2a1a4a fill, #a78bfa text, 9999px radius, 3×10px padding, 12px caption. Used sparingly for “New”, version tags, “Free”. The only place soft purple appears outside the CTA.

badge-neutral — Neutral metadata chip. #1f1f1f fill, #a3a3a3 text, 1px #2a2a2a border, pill radius. Platform tags (macOS / Windows / Linux), category labels in the plugin directory.

Inputs / Forms

input — Text input. #0f0f0f fill (inset darker than the surrounding card — the field reads as “below” the surface), #eeeeee text, 1px #2a2a2a border, 8px radius, 40px height, 8×12px padding. Placeholder in #737373. On focus, the border becomes #7c3aed (1px) with a faint rgba(124,58,237,0.40) 3px ring. Newsletter / search / vault-name fields.

select / dropdown — Same chassis as input; chevron in #a3a3a3. Open panel uses card surface (#161616) with shadow-card.

nav-top — Sticky top nav, 64px height. Translucent near-black (#0f0f0fcc) with a backdrop blur so content blurs behind it on scroll, and a 1px #2a2a2a bottom hairline. Crystal-facet logo + “Obsidian” wordmark flush left in #eeeeee — the logo is the only ornament in the chrome. Centre: nav links (Features, Pricing, Plugins, Docs) in 15px / 500 #eeeeee. Right: a button-quiet (“Sign in”) + the purple cta-primary (“Download”).

nav-link#eeeeee at rest, no underline. Hover brings a subtle #a78bfa underline / colour lift. Active page link sits at full #ffffff.

footer#0a0a0a deep-well background, column heads in 13px / 600 #eeeeee, links in 14px / 400 #a3a3a3. The crystal mark reappears, muted. Multi-column: Product / Community / Resources / Company.

Decorative

graph-ornament — An optional node-graph SVG (nodes + connecting edges) that nods at Obsidian’s signature graph view. Edges may gently pulse / draw on viewport entry. Rendered in muted purple (#a78bfa at low opacity) on the canvas. Purely decorative — aria-hidden="true".

5. Layout Principles

Spacing System

  • Base unit: 4px
  • Scale: 0 · 4 · 8 · 12 · 16 · 24 · 32 · 48 · 64 · 96 · 128
  • Section padding (vertical): 96–128px between major bands — generous, lets the dark canvas breathe
  • Card internal padding: 24px on feature cards; 16px on compact list rows
  • Inter-card gutters: 24px in feature grids
  • The dark canvas does a lot of the spacing work — empty near-black space reads as deliberate, not unfinished

Grid & Container

  • Max content width: 1280px — standard modern marketing width, wider than Bear’s magazine-tight 1080px
  • Prose / reading column: 720px for long-form (docs, blog)
  • Hero: single-column, centred — H1 + deck + the purple CTA + an editor screenshot beneath
  • Feature grid: 3-up at desktop → 2-up at tablet → 1-up at mobile
  • 24px gutters; the grid sits inside the 1280px container with generous side margins on wide screens

Whitespace Philosophy

On a near-black canvas, negative space is the primary compositional tool. Where a light site fills space with subtle tints and borders, Obsidian leaves the canvas dark and empty — the void reads as focus, not absence. Surfaces (cards) appear only where there is content to hold; between them is pure #0f0f0f. This is the editor’s own aesthetic: a dark workspace where the only bright things are the words you wrote and the one action you can take.

Section Cadence

A typical Obsidian page runs:

  1. Hero — 60px / 600 H1 (“Sharpen your thinking”), 18px deck in #b0b0b0, purple cta-primary with OS-selector, editor screenshot floating beneath (optional graph-ornament behind)
  2. Feature spread — 3-up cards on the dark canvas (Local files, Links & graph, Plugins) — each a #161616 panel with hairline border
  3. Graph showcase — the signature node-graph view, large, with a short caption — the product’s most recognizable surface
  4. Plugins / community — grid of plugin cards, neutral badges, a “Browse 2,000+ plugins” ghost button
  5. Sync / Publish band — the paid tiers, presented as calm feature cards, not aggressive pricing tables
  6. Closing CTA band — a centred restatement of the purple CTA over empty canvas
  7. Footer — deep-well #0a0a0a, muted multi-column links, crystal mark

The page does not alternate light/dark — it is dark throughout. The “alternation” is canvas (#0f0f0f) vs. card surface (#161616) tonal contrast.

6. Shapes & Radius Scale

TierValueUse
Micro2pxInline code chips, tiny indicators
Small4pxNested elements, fine controls
Standard8pxCTA, buttons, inputs — the dominant rounding
Comfortable12pxCards, panels
Large16pxFeature shells, app screenshots
Pill9999pxBadges, neutral chips

Obsidian’s radius hierarchy is developer-tool crisp — the dominant 8px on buttons and inputs is the modern-app sweet spot: rounded enough to feel finished, sharp enough to feel engineered (not the soft 12–16px of consumer apps, not the pill-everything of marketing sites). Cards step to 12px; the largest shells and screenshots to 16px. Pill radius is reserved for badges only — the page never makes a pill button, because a pill CTA would read as “consumer”, and Obsidian is positioning as a serious tool.

7. Depth & Elevation

LevelTreatmentUse
0 — Canvasno shadow, #0f0f0fThe page floor, hero, empty space (~70% of surface)
1 — Surfacetonal step to #161616 + 1px #2a2a2a hairline, no shadowFeature cards, panels
2 — Elevated surfacetonal step to #1f1f1f + #3a3a3a borderNested / hovered cards
3 — Floatingrgba(0,0,0,0.40) 0 1px 2px 0Sticky nav at scroll, subtle inputs
4 — Raisedrgba(0,0,0,0.50) 0 8px 24px -8pxDropdowns, popovers, screenshots
5 — Modalscrim rgba(0,0,0,0.65) + rgba(0,0,0,0.70) 0 24px 64px -16pxSign-in / vault dialog

Shadow Philosophy

On a near-black canvas, shadow is a weak signal — a rgba(0,0,0,…) shadow against #0f0f0f is barely darker than the floor it sits on. So Obsidian inverts the usual elevation strategy: depth is communicated by stepping the surface lighter, not by casting a shadow darker. A raised card is #161616 (lighter than canvas) with a hairline border; a more-raised card is #1f1f1f. Shadow is reserved for chrome that genuinely floats over content (dropdowns, modals, the sticky nav), and even then it is used at high opacity (0.50–0.70) purely so it registers at all. The hairline #2a2a2a border, not the shadow, is what draws the eye to a surface edge. This is the dark-mode elevation discipline that Linear, Vercel, and well-built developer dashboards all share.

8. Interaction & Motion

Easing

  • Standard: cubic-bezier(0.4, 0, 0.2, 1) — default for hover colour swaps, border transitions
  • Out: cubic-bezier(0.0, 0, 0.2, 1) — scroll-reveal entrances
  • Emphasized: cubic-bezier(0.2, 0, 0, 1) — modal entry, dropdown open

Durations

BucketValueUse
Fast150msButton hover, link underline, focus-ring fade
Standard240msCard hover, dropdown open, border transitions
Slow320msScroll-reveal, modal entry, graph-line draw

Per-Component Recipes

  • CTA hover: fill #7c3aed#6d28d9 over 150ms standard. No transform, no scale. Active → #5b21b6.
  • Ghost button hover: transparent → #262626 fill over 150ms; border unchanged.
  • Card hover: surface lifts a tonal step (#161616#1f1f1f) and border brightens (#2a2a2a#3a3a3a) over 240ms. No translate.
  • Link hover: colour #a78bfa#c4b5fd; underline fades in over 150ms.
  • Focus: 3px rgba(124,58,237,0.40) ring + 1px purple border appears over 150ms on keyboard focus.
  • Scroll-reveal: sections fade in + rise 8px over 320ms ease-out on first viewport entry. One-shot.
  • Graph ornament: connection edges gently draw / pulse — decorative, low-amplitude, never demands attention.

Page Transitions

Navigation is a quiet 240ms cross-fade; the sticky nav stays fixed. Anchored links smooth-scroll over 320ms emphasized. Nothing is showy — motion exists to soften state changes, not to perform.

Reduced Motion

Respects prefers-reduced-motion: reduce. Scroll-reveal becomes static render-on-mount (no fade, no rise). The graph-ornament animation pauses to a static frame. Hover transforms (none exist) and all translate/scale are suppressed. Colour-only transitions (button hover, link colour) may remain since they don’t induce motion.

9. Accessibility & A11y

Contrast Pairs

PairRatioLevel
#eeeeee ink on #0f0f0f canvas16.5AAA
#eeeeee ink on #161616 surface14.6AAA
#ffffff label on #7c3aed CTA5.7AA (passes for the 15px/500 button label)
#7c3aed brand on #0f0f0f3.4AA large only — never use as body text
#a78bfa brand-text on #0f0f0f7.0AAA — the safe purple for links / small text
#b0b0b0 secondary on #0f0f0f8.8AAA
#a3a3a3 muted on #0f0f0f7.6AAA

The critical accessibility nuance: the brand purple #7c3aed only reaches 3.4:1 on the canvas — it passes for large UI and as a button fill (with white text), but it fails as small purple text on dark. The page therefore uses the lightened #a78bfa (7.0:1, AAA) for every inline link and purple text run. Treating brand and brand-text as two distinct tokens is not optional polish — it is what keeps the dark theme readable.

Focus Indicators

Focus is a 3px rgba(124,58,237,0.40) ring plus a 1px solid #7c3aed border on the focused control. On the dark canvas the semi-transparent purple ring is clearly visible against #0f0f0f without being garish. Focus is never removed; keyboard and pointer users get the same target.

ARIA Patterns

  • Top nav: <nav> landmark with aria-label="Primary". The crystal logo is an <img alt="Obsidian"> linking home.
  • Platform-split CTA: the OS-selector caret is a <button aria-haspopup="menu" aria-expanded>; the dropdown is role="menu" with role="menuitem" per platform.
  • Plugin grid: each card is a link with an accessible name; neutral badges are decorative text, not separate controls.
  • Graph ornament: aria-hidden="true" — purely visual.
  • Modal (sign-in / vault): focus trap, Esc closes, click-outside closes, focus returns to trigger.

Keyboard Navigation

  • Top nav: Tab logo → Features → Pricing → Plugins → Docs → Sign in → Download
  • Platform-split CTA: Tab to the button; Enter downloads default OS; the caret button opens the menu, arrow keys navigate platforms
  • Cards: Tab moves card → card; Enter activates the link
  • Modal: Tab cycles within the dialog only

Screen Reader Hints

The crystal logo carries alt="Obsidian". App screenshots carry descriptive alt text (“Obsidian editor in dark theme, a note open with a backlinks panel and the graph view in the sidebar”). The graph ornament is aria-hidden. The CTA’s accessible name includes the platform (“Download Obsidian for macOS”).

Reduced Motion

All entrance animations degrade to static render. The graph ornament freezes. Colour-only hover transitions may remain. No essential information is conveyed by motion alone.

10. Responsive Behavior

Breakpoints

NameWidthKey Changes
Mobile<640pxNav collapses to logo + hamburger; hero h1 drops 60 → 36px; CTA goes full-width; feature cards 1-up; graph ornament hidden
Tablet640–1024pxInline nav links may persist; hero h1 at ~44px; feature cards 2-up; screenshot at 90% width
Desktop1024–1280pxFull nav; hero h1 at 60px; feature cards 3-up; screenshot up to 1100px
Wide>1280pxContent caps at 1280px; canvas absorbs the extra width as empty near-black margin

Touch Targets

  • Purple CTA: 40px height; on mobile it goes full-width for an easy thumb target (44px+ effective row)
  • Nav links: minimum 44×44px hit area in the mobile sheet
  • Plugin / feature cards: the whole card is the tap target
  • Inputs: 40px height, 44px+ effective with padding

Collapsing Strategy

  • Top nav links collapse into a hamburger sheet below 640px; the purple CTA stays visible in the collapsed bar
  • Feature grids: 3 → 2 → 1 columns
  • The graph-view showcase scales down; on mobile it may switch to a simpler static node image to keep payload light (the no-webfont/perf ethos carries into imagery)
  • App screenshots scale by viewport, never crop; 16px radius scales proportionally

Image Behavior

Editor screenshots render at 2x as PNG/WebP with 16px radius and optional rgba(0,0,0,0.50) shadow. They scale width: 100%; height: auto. Because the canvas is dark and the screenshots are of the dark editor, screenshots blend seamlessly into the page — there is no light-on-dark seam to manage.

Container Queries

Used on the platform-split CTA: when the available width is too narrow for “Get Obsidian for macOS” + caret, the label shortens to “Download” and the OS name moves into the dropdown.

11. Content & Voice

Tone

Plainspoken, technical, quietly confident. Obsidian’s voice trusts the reader to be the kind of person who wants their notes as plain files — it doesn’t over-explain, doesn’t hype, doesn’t use exclamation marks. Headlines are short imperatives or claims (“Sharpen your thinking”, “Your thoughts are yours”, “A second brain, for you, forever”). The copy assumes competence and rewards it.

Microcopy Patterns

  • Button verbs: “Get Obsidian”, “Download”, “Read the docs”, “Browse plugins” — direct, outcome-named
  • Error message recipe: [What went wrong] + [What to try] — e.g., “Couldn’t open that vault. Check the folder still exists, then try again.”
  • Success confirmations: short, factual — “Synced.” / “Vault created.”
  • Field labels: minimal — “Email”, “Vault name” — no friendly framing

Empty States

The empty-vault state in screenshots: “Create your first note.” — single declarative line. The paid-feature gate (Sync / Publish): “Obsidian Sync keeps your vault in sync across devices. Try it free.” — names the value, offers the path, no pressure.

CTA Verb Conventions

  • Primary action: “Get Obsidian” / “Download” (with OS selector)
  • Secondary action: “Read the docs”, “Browse plugins”, “Learn more”
  • Tertiary text: “Sign in”, “See pricing”, “Join the community”
  • Avoided: “Get started free!”, “Sign up now”, “Click here”, “Buy” — Obsidian uses calm outcome verbs, never funnel-urgency

12. Dark Mode & Theming

Dark-only marketing surface. The public site renders exclusively on the near-black #0f0f0f canvas — it mirrors Obsidian’s default dark editor theme as a deliberate brand-identity choice. This is the inverse of most sites (which are light-only and ship a dark app): here the site is dark because the brand is dark, and the dark editor is the product’s most recognizable face.

The app itself, by contrast, ships a full theming system — light and dark base themes plus a large community-theme ecosystem and per-vault CSS snippets (theming your own vault is a core feature). The marketing site does not expose a light toggle; it commits to dark to show the default experience.

If a light variant were ever shipped, the token swap would be: canvas #ffffff, surface #f6f6f6, ink #1a1a1a, border #e5e5e5, brand purple unchanged at #7c3aed (it passes AA as a CTA fill on white and is legible as text on light, so the brand-text lightening would no longer be needed). The greyscale stack would simply invert; the single purple accent would carry over intact.

13. Lineage & Influences

Obsidian’s design sits at the intersection of three traditions. First, the developer-tool dark aesthetic — the near-black canvas, hairline-bordered surfaces, single-accent restraint, and system-font neutrality that Linear, Vercel, and well-built dashboards share. Second, the local-first / plain-text software movement — the lineage of iA Writer, Roam Research, TiddlyWiki, and the broader “your data in open formats on your own disk” ethos, where the refusal to load a webfont or a tracker is itself a design statement. Third, the personal-knowledge-management (PKM) tradition — the Zettelkasten method, wikis, and the graph-of-linked-notes idea that Obsidian’s signature graph view makes visible.

The most distinctive — and most ideological — design decision is the absence of a webfont. Where Bear ships two in-house typefaces and Notion loads a custom sans, Obsidian renders entirely in the reader’s own system UI font. For a product whose entire pitch is “your notes are plain Markdown files on your own machine, no cloud required, no lock-in”, a marketing page that makes your browser phone home for a font would be a contradiction. The system-font choice, the instant load, and the zero tracking are the same value expressed three ways: your machine, your data, your attention — ours to respect, not to harvest.

What Obsidian rejects: gradient washes, hero video, animated illustrations, a second accent colour, pill CTAs, urgency microcopy, and webfonts. The page is dark, near-monochrome, system-set, and funnels to a single purple button — the visual equivalent of a clean plain-text file.

Influences:

  • Linear — dark-canvas developer-tool aesthetic; hairline surfaces, single-accent restraint, linear.app
  • Vercel — near-black canvas, system-font neutrality, crisp 8px-radius developer chrome, vercel.com
  • iA Writer — plain-text-as-craft, local files, typographic restraint as positioning, ia.net/writer
  • Roam Research — networked-thought / linked-notes lineage and the graph-of-ideas paradigm, roamresearch.com
  • TiddlyWiki — single-file, local-first, own-your-data personal-wiki heritage, tiddlywiki.com

14. Do’s and Don’ts

Do

  • Keep the canvas near-black at #0f0f0f — it is the editor metaphor and the brand floor
  • Use #eeeeee for body text, never pure #ffffff — the off-white is calmer on dark and still AAA
  • Let the single purple #7c3aed CTA carry the entire chromatic load — everything funnels to it
  • Render in the system UI sans (ui-sans-serif) with no webfont — it is the local-first ethos made visible
  • Set the hero at weight 600, not 700 — confident, not bold-marketing-loud
  • Lighten purple to #a78bfa for any text/links on dark — the saturated brand fails AA as small text
  • Step surfaces lighter (#0f0f0f#161616#1f1f1f) for elevation, not darker shadows
  • Define structure with #2a2a2a hairline borders, not drop shadows
  • Use 8px radius on buttons and inputs — developer-tool crisp
  • Keep the crystal mark as the only ornament; if you add a graph-view nod, keep it muted and decorative
  • Ration negative space generously — empty near-black canvas reads as focus, not absence

Don’t

  • Don’t introduce a second accent colour — purple is the entire chromatic system
  • Don’t load a webfont — it contradicts the local-first / privacy ethos the brand sells
  • Don’t use the saturated #7c3aed as small purple text on dark — it fails AA; use #a78bfa
  • Don’t use pure white #ffffff for body copy — it vibrates against the near-black canvas
  • Don’t make the hero weight 700/800 — keep it 600, engineered not loud
  • Don’t pile up drop shadows for depth — on dark, lighter surface tone is the elevation signal
  • Don’t make a pill-shaped CTA — pill reads “consumer”; Obsidian is positioning as a serious tool
  • Don’t add gradient washes, hero video, or animated illustration beyond the muted graph nod
  • Don’t use urgency microcopy (“Sign up now!”, “Limited time”) — the voice is calm and trusting
  • Don’t add tracking pixels or analytics theatre — the page’s restraint is the message
  • Don’t tint the canvas blue or warm — near-neutral near-black is the brand floor

15. Agent Prompt Guide

Quick Color Reference

Canvas:       #0f0f0f   (near-black page floor)
Deep well:    #0a0a0a   (footer, behind elevated panels)
Surface:      #161616   (raised card, one step off canvas)
Surface-elev: #1f1f1f   (nested / hovered card)
Ink:          #eeeeee   (body + display, never pure white)
Secondary:    #b0b0b0   (deck copy, secondary text)
Muted:        #a3a3a3   (captions, footer links)
Brand:        #7c3aed   (the one accent — CTA fill only)
Brand-text:   #a78bfa   (purple text/links on dark — AA-safe)
Border:       #2a2a2a   (hairline divider)
On-brand:     #ffffff   (white label on the purple CTA)

Example Component Prompts

  • “Create an Obsidian-style hero: near-black canvas (#0f0f0f), a 60px / weight-600 headline ‘Sharpen your thinking’ in the system UI sans (ui-sans-serif, NO webfont) in #eeeeee with -0.02em tracking and 1.05 line-height. Below: an 18px / 400 deck in #b0b0b0 at 1.6 line-height. Below that: a single electric-purple (#7c3aed) CTA button ‘Get Obsidian for macOS’, white text at 15px/500, 8px radius, 10×16px padding, with a small OS-selector caret on the right edge. No second accent, no gradient, no webfont. Optionally a muted purple (#a78bfa low-opacity) node-graph SVG floating behind.”
  • “Design an Obsidian feature card: #161616 fill (one tonal step off the #0f0f0f canvas), 1px #2a2a2a hairline border, 12px radius, 24px padding, NO shadow. Inside: a 20px/600 title in #eeeeee, then 16px/400 body in #b0b0b0 at 1.55 line-height. On hover, lift the surface a tonal step to #1f1f1f and brighten the border to #3a3a3a over 240ms — no translate.”
  • “Build the Obsidian top nav: 64px tall, translucent near-black (#0f0f0fcc) with backdrop-blur and a 1px #2a2a2a bottom hairline. Left: a crystal-facet logo + ‘Obsidian’ wordmark in #eeeeee. Centre: nav links (Features, Pricing, Plugins, Docs) in 15px/500 #eeeeee with a subtle #a78bfa underline on hover. Right: a quiet text ‘Sign in’ link in #b0b0b0, then the purple (#7c3aed) ‘Download’ CTA at 8px radius.”
  • “Create an Obsidian text input: #0f0f0f fill (inset DARKER than the surrounding #161616 card), #eeeeee text, 1px #2a2a2a border, 8px radius, 40px height, placeholder in #737373. On focus, set the border to #7c3aed (1px) plus a 3px rgba(124,58,237,0.40) ring.”
  • “Design an Obsidian inline link + soft badge: links in lightened purple #a78bfa (NOT the saturated #7c3aed — it fails AA on dark) with an underline that fades in on hover toward #c4b5fd. A soft badge: #2a1a4a fill, #a78bfa text, pill radius (9999px), 3×10px padding, 12px caption — used sparingly for ‘New’ or a version tag.”
  • “Build an Obsidian closing CTA band: centred on the bare #0f0f0f canvas with generous vertical padding (96–128px), a 32px/600 #eeeeee restatement headline, and the single purple (#7c3aed) ‘Get Obsidian’ CTA at 8px radius. Nothing else — the empty near-black space is the design.”

Iteration Guide

  1. One accent, always. Purple is the entire chromatic system. If you find yourself reaching for a second colour, you’ve left the brand — express the variation in greyscale tone instead.
  2. No webfont, ever. Render in ui-sans-serif / system-ui. Loading a font betrays the local-first ethos and is the single fastest way to make the page “not Obsidian”.
  3. Two purples, two jobs. #7c3aed is for fills (the CTA); #a78bfa is for purple text on dark. Swapping them breaks contrast — the saturated purple as small text fails AA.
  4. Off-white, not white. Body is #eeeeee. Pure #ffffff vibrates on the near-black canvas and reads as a beginner mistake.
  5. Elevation goes lighter, not darker. Lift a surface by stepping its tone up (#0f0f0f#161616#1f1f1f) and adding a hairline — not by casting a shadow that barely registers on black.
  6. Hero weight 600, not 700. Keep display confident and engineered. The moment it goes bold-marketing, it stops being Obsidian and starts being a generic startup.
  7. Let the dark breathe. Negative near-black space is the primary compositional tool. Resist the urge to fill it with tints, gradients, or decoration — the void is the focus.
  8. Calm voice, no urgency. Microcopy is plainspoken and trusting (“Get Obsidian”, “Read the docs”). Never “Sign up now!”, never exclamation marks, never a pill CTA.

Theme-toggle audit: score=0, signals=[none]

Ship with this

Drop obsidian into your project, then ship the actual sections in an afternoon.

1 · install design
npx @webdesignhot/design-md add obsidian
2 · ship landing page
npx agentkit init --design obsidian
How AgentKit reads DESIGN.md