Extending the Platform beta
All extension follows the same flow: Idea → Activity → RFC (if architectural) → Code → Tests → Docs → PR. Same flow regardless of subsystem.
Add a Markdown Pass
The compiler is a topologically-sorted DAG of Passes. Each Pass has a phase, declared reads/writes keys, and a run function. Adding one:
- Create
config/mdsvex/passes/<my-feature>.jsimplementing thePassinterface — see Pass Definition. - Register in
config/mdsvex/engine/pass-groups.jsunder the appropriate phase (pre | remark | rehype | validate | post | extract). - Add unit test at
config/mdsvex/passes/<my-feature>.test.js— coverage must be 100% on the new Pass. - If the Pass changes the manifest schema, declare a new diagnostic code, or affects feature-flag chunking → write an ADR (evolution/workflow.md).
- Update
docs/platform/architecture/markdown-pipeline.md— at minimum the relevant phase section.
Add a UI Component
UI lives under FSD layers. Pick by scope:
- Reusable primitive →
src/shared/ui/<Component>.svelte. - Self-contained capability →
src/features/<name>/. - Page-level composition →
src/widgets/<name>/.
Imports flow upward only: shared → entities → features → widgets → routes. Never reach down.
Reuse before building: CodeBlock, CodeTabs, CopyButton, MathCopy, Seo, Breadcrumb, StaticHtml, Logo, KaTeXStyles.
If the component is allowed inside markdown content, it also needs a registry entry — see "Add a markdown-allowed component" below.
Add a Feature
- Scaffold an activity: copy
operations/templates/activities.md→operations/activities/YYYY/MM/<id>.md. Fillkind,subtype,intent. - If the feature touches architecture (new top-level capability, new contract, new render path) — open an RFC first.
- Implement under the correct FSD layer.
- ≥ 90% coverage (Vitest), Playwright spec for any user flow.
- Update
docs/platform/architecture/<subsystem>.mdif behavior changes. - PR:
gh pr create --fill.
Add a Markdown-allowed Component
If your post needs a custom Svelte component:
- Add the component to
src/shared/ui/(or appropriate FSD layer). - Register it in
config/mdsvex/registry.jswithkind(block | inline) andallowedProps(whitelist). - If the component accepts a URL or HTML attribute, add a security fixture in the registry tests.
- Document the component in writer/index.md (and link from
frontmatter.mdif it adds a feature flag).
Update Docs
- Same PR as the code change. Never «docs PR later».
- Frontmatter
last_updated→ today (YYYY-MM-DD). - ≥ 1 cross-reference link inside the body to a related doc.
- If terminology changes → update mentions across all docs (use
sdfor project-wide substitutions, notsed).
Add an ADR
- Get next number:
ls docs/evolution/adr | tail -1. - Copy
operations/templates/rfc.md→docs/evolution/adr/NNNN-<slug>.md. - Status flow:
Draft → Proposed → Accepted(after PR merge). - Append-only: never edit accepted ADRs. To revise, write a new ADR and add
Superseded by: NNNNto the old one.
Anti-Patterns (do NOT do)
- Adding a feature without an Activity record.
- Editing architecture docs without an ADR for the underlying decision.
- Creating new top-level folders in
docs/platform/outside spec — onlywriter/,developer/,architecture/are allowed. - Documenting structure outside architecture/index.md → Directory Structure.
- Mocking internals in tests — only system boundaries (WebGPU, fetch, localStorage).
- Deep customizing the VitePress theme — keep default.