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.
Compare to…
- 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
- 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
- micro
2px - sm
4px - md
8px - lg
12px - xl
16px - pill
9999px
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
theme.extend block for tailwind.config.js
:root { --bg, --text, --brand, … } you can paste anywhere
W3C Design Tokens Community Group format
Importable into Figma → Variables → Import
---
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]*
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
#2a2a2aborders 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
#a78bfafor 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#7c3aedwould fail. Use this, notbrand, 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 (
#737373text on#161616fill): 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 / dropdownrgba(0,0,0,0.70) 0 24px 64px -16px— modal / popover
Semantic
- Success (
#4ade80on#14321f) — confirmation green, brightened for dark legibility. - Warning (
#fbbf24on#33270a) — advisory amber. - Danger (
#f87171on#3a1717) — form-error red, softened for dark (a saturated#dc2626would vibrate on black). - Info (
#a78bfaon#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#ffffffvibrates 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 to0by h4. Body and below stay at0; 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.mdfiles 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:
- Hero — 60px / 600 H1 (“Sharpen your thinking”), 18px deck in
#b0b0b0, purplecta-primarywith OS-selector, editor screenshot floating beneath (optional graph-ornament behind) - Feature spread — 3-up cards on the dark canvas (Local files, Links & graph, Plugins) — each a
#161616panel with hairline border - Graph showcase — the signature node-graph view, large, with a short caption — the product’s most recognizable surface
- Plugins / community — grid of plugin cards, neutral badges, a “Browse 2,000+ plugins” ghost button
- Sync / Publish band — the paid tiers, presented as calm feature cards, not aggressive pricing tables
- Closing CTA band — a centred restatement of the purple CTA over empty canvas
- 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→#6d28d9over 150ms standard. No transform, no scale. Active →#5b21b6. - Ghost button hover: transparent →
#262626fill 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 witharia-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 isrole="menu"withrole="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
- 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
#eeeeeefor body text, never pure#ffffff— the off-white is calmer on dark and still AAA - Let the single purple
#7c3aedCTA 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
#a78bfafor 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
#2a2a2ahairline 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
#7c3aedas small purple text on dark — it fails AA; use#a78bfa - Don’t use pure white
#fffffffor 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
- 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.
- 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”. - Two purples, two jobs.
#7c3aedis for fills (the CTA);#a78bfais for purple text on dark. Swapping them breaks contrast — the saturated purple as small text fails AA. - Off-white, not white. Body is
#eeeeee. Pure#ffffffvibrates on the near-black canvas and reads as a beginner mistake. - 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. - 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.
- 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.
- 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]
Drop obsidian into your project, then ship the actual sections in an afternoon.
npx @webdesignhot/design-md add obsidian npx agentkit init --design obsidian