ADR-007: Quartz + Obsidian for Developer Documentation
Status: Accepted
Context
Developer documentation needs a home that is:
- Editable in the repository — docs change with code in the same PR; no external service to keep in sync
- Navigable locally — engineers can browse docs offline and cross-link between notes
- Publishable — the same source can be built into a static site (e.g. GitHub Pages) without a separate CMS
- Zettelkasten-compatible — notes can cross-link with
[[wikilinks]], ADRs and technical docs form a connected graph
Options considered:
| Tool | Format | Local browse | Static site | Wikilinks | Git-native |
|---|---|---|---|---|---|
| Notion | Proprietary | ❌ | Via export | ❌ | ❌ |
| Confluence | Proprietary | ❌ | ❌ | ❌ | ❌ |
| MkDocs | Markdown | CLI only | ✅ | Plugin | ✅ |
| Docusaurus | MDX | Dev server | ✅ | ❌ | ✅ |
| Obsidian + Quartz | Markdown + frontmatter | Obsidian app | ✅ | ✅ | ✅ |
Decision
Store all developer documentation as Markdown files with Zettelkasten frontmatter inside the docs/ directory. Use Obsidian for local authoring and browsing, and Quartz for publishing to a static site.
The vault is configured in quartz.docs.config.ts at the repository root.
Note structure:
docs/
├── index.md ← vault home
├── adr/
│ ├── index.md ← ADR register
│ └── <timestamp-RAND>.md
└── technical/
├── index.md ← technical doc register
└── <timestamp-RAND>.md
Note IDs use a Zettelkasten format: <unix-timestamp>-<4-char-random>. This ensures:
- Global uniqueness (no sequential collision)
- Stable links even if notes are renamed (links use the ID, not the title)
- Temporal ordering without a database
Frontmatter schema:
---
id: 1775595191-7MZ8
title: Human Readable Title
aliases:
- Human Readable Title
tags:
- adr # or: technical
---Cross-note links use Obsidian wikilink syntax: [[id|Display Text]].
Consequences
Positive
- Docs live in the repository — every doc change is a commit; history and blame work normally
- Obsidian renders the vault as a graph; engineers can explore ADR → technical doc connections visually
- Quartz can publish the vault to GitHub Pages with
quartz build— no separate CMS account - Zettelkasten IDs mean notes can be renamed without breaking links
- Markdown with YAML frontmatter is plain text — any editor works; Obsidian is optional
Negative / Risks
- Quartz requires a Node.js build step for publishing (not Bun-native)
- Obsidian is a local desktop app — there is no web-based collaborative editing (unlike Notion/Confluence)
- The ID generation step (
date +%s+ random) is manual; there is no tooling to enforce uniqueness in CI [[wikilinks]]do not resolve in standard Markdown renderers (GitHub, VS Code preview) — links appear as plain text outside Obsidian/Quartz