docs
Generate a documentation site from your ADRs and specs. Use when the user says "generate docs", "create a docs site", or wants to publish their architecture decisions.
Governing Artifactsโ
Usageโ
/sdd:docs [project name or options] [--module <name>]
Required Tools
BashReadWriteEditGlobGrepTaskAskUserQuestion
Overviewโ
Transform ADRs and OpenSpec specs (located via the Artifact Path Resolution pattern from references/shared-patterns.md) into a polished documentation website with:
- RFC 2119 keyword highlighting (MUST, SHALL, MAY, etc.)
- ADR cross-reference linking (๐ ADR-0001 becomes a clickable link)
- SPEC cross-reference linking (PREFIX-NNN links to spec requirement anchors)
- Status/Date/Domain badge components
- Requirement box components for spec tables
- Consequence keyword highlighting (Good/Bad/Neutral) in ADRs
- Dark mode support
- Auto-generated sidebars
Supports two modes:
- Scaffold mode: Creates a standalone
docs-site/with its own Docusaurus installation - Integration mode: Generates a build-time plugin into an existing Docusaurus site
Processโ
Step 0: Resolve Artifact Pathsโ
<!-- Governing: ADR-0016 (Workspace Mode), SPEC-0014 REQ "Artifact Path Resolution" -->
Follow the Artifact Path Resolution pattern from references/shared-patterns.md to determine the ADR and spec directories. If $ARGUMENTS contains --module <name>, resolve paths relative to that module; otherwise, in a workspace, aggregate across all modules. The resolved ADR directory is \{adr-dir\} and spec directory is \{spec-dir\}.
<!-- Governing: ADR-0016 (Workspace Mode), SPEC-0014 REQ "Cross-Module Aggregation" -->
Cross-module aggregation: When in aggregate mode (no --module, workspace detected), include all modules' artifacts in the docs site. Organize the sidebar navigation by module:
Architecture/
โโโ api/
โ โโโ ADRs/
โ โ โโโ ADR-0001: Choose REST over GraphQL
โ โ โโโ ADR-0002: Choose PostgreSQL
โ โโโ Specs/
โ โโโ SPEC-0001: Web Dashboard
โโโ worker/
โ โโโ ADRs/
โ โ โโโ ADR-0001: Choose Redis for queues
โ โโโ Specs/
โ โโโ SPEC-0001: Job Processing
โโโ Overview (cross-module index page)
Each module's artifacts are transformed independently and placed under a module-named directory in the docs output. The index page lists all modules with artifact counts. When --module is provided, generate docs for that single module only (flat structure, no module subdirectory). When in single-module mode (no workspace), operate normally with the existing flat structure.
Step 1: Pre-flight Checksโ
- Check if Node.js is installed. If not, tell the user: "Node.js is required to run the docs site. Please install it from https://nodejs.org/ and re-run this command." and stop.
- Check if
\{adr-dir\}has any ADR.mdfiles - Check if
\{spec-dir\}has any spec directories (containingspec.md). Validate spec pairing perreferences/shared-patterns.mdยง "Spec Pairing Validation". - If NEITHER has content, tell the user: "No ADRs or specs found. Create some first with
/sdd:adror/sdd:spec, then re-run/sdd:docs." and stop. - If only one has content, proceed but note which is empty (e.g., "No specs found yet -- the docs site will only include ADRs for now.")
Step 2: Detect Existing Docusaurus Site and Upgrade Stateโ
2.1: Check for upgrade manifestโ
Check if .sdd-docs.json exists at the project root.
If .sdd-docs.json exists:
- Read and parse the manifest
- Check if the
siteDirreferenced in the manifest still exists on disk- If siteDir exists โ enter Upgrade Mode (Step 3C). Skip Steps 2.2 and 2.3.
- If siteDir is missing โ warn the user: "Found
.sdd-docs.jsonbut the site directory\{siteDir\}no longer exists." UseAskUserQuestionto offer:- "Re-scaffold a new docs site" โ proceed with Scaffold Mode (Step 3A)
- "Cancel" โ stop
If .sdd-docs.json does NOT exist, continue to Step 2.2.
2.2: Scan for existing Docusaurus sitesโ
Scan the project root for directories containing docusaurus.config.ts or docusaurus.config.js:
find . -maxdepth 2 -name 'docusaurus.config.*' -not -path './docs-site/*' -not -path './node_modules/*' 2>/dev/null
2.3: Choose modeโ
If an existing docs site directory is detected (docs-site/ exists or an integration site was found in 2.2) but no .sdd-docs.json:
- Warn: "Upgrade tracking unavailable โ
.sdd-docs.jsonnot found." - Use
AskUserQuestionto offer:- "Create manifest from current state" โ compute SHA-256 checksums of all managed files in the existing site, write
.sdd-docs.jsonusing the current state as baseline, then enter Upgrade Mode (Step 3C) - "Continue without upgrade tracking" โ proceed to mode selection below
- "Cancel" โ stop
- "Create manifest from current state" โ compute SHA-256 checksums of all managed files in the existing site, write
If an existing non-scaffold Docusaurus site is found (from Step 2.2), use AskUserQuestion to let the user choose:
- Option A: "Integrate into {directory}" -- proceed with Integration Mode (Step 3B)
- Option B: "Scaffold a new docs site" -- proceed with Scaffold Mode (Step 3A)
If no existing site is found, proceed directly with Scaffold Mode (Step 3A).
Step 3A: Scaffold Modeโ
Read and follow the plugin's skills/docs/references/scaffold-mode.md for the full scaffold workflow. After completion, proceed to Step 4 below.
Step 3B: Integration Modeโ
Read and follow the plugin's skills/docs/references/integration-mode.md for the full integration workflow. After completion, proceed to Step 4 below.
Step 3C: Upgrade Modeโ
Read and follow the plugin's skills/docs/references/upgrade-mode.md for the full upgrade workflow. This handles manifest-based file management, conflict resolution, and new template detection.
Step 4: Create Manifestโ
Runs after Step 3A or 3B to establish upgrade tracking.
Determine managed files based on mode:
- Scaffold: files in
docs-site/plugins/sdd-content/,docs-site/src/components/,docs-site/src/css/,docs-site/src/theme/ - Integration: files in
\{site\}/plugins/sync-spec-docs/,\{site\}/src/components/design-docs/,\{site\}/src/css/design-docs.css,\{site\}/src/theme/MDXComponents.tsx(if created/modified)
Compute SHA-256 checksum for each file (shasum -a 256 \{file-path\}), then write .sdd-docs.json:
{
"version": "<plugin version from .claude-plugin/plugin.json>",
"mode": "scaffold" | "integration",
"siteDir": "<relative path to site dir>",
"createdAt": "<ISO 8601>",
"updatedAt": "<ISO 8601>",
"files": {
"<relative-path>": { "checksum": "sha256:<hex-digest>", "managed": true }
}
}
Tell the user: "Created .sdd-docs.json with {N} tracked files. Future runs of /sdd:docs will detect changes and offer upgrades."
Rulesโ
- Always read templates from the plugin directory, don't recreate from memory
- Configure the Docusaurus site for the current project (title, URLs, etc.)
- The transform scripts must work with the project's actual directory structure
- Don't include OpenAPI plugin config unless the project has an OpenAPI spec
- Keep
spec-emojis.jsonandspec-mapping.jsonas generated files (populated by build-spec-mapping.js) - In integration mode, NEVER overwrite the existing site's
docusaurus.config.tswholesale -- only add the plugin entry and CSS import - In integration mode, ALWAYS namespace components under
design-docs/to avoid collisions with existing components - In integration mode, generated files go to
\{site\}/docs/architecture/-- this directory is gitignored and regenerated on every build - Always create
.sdd-docs.jsonafter a fresh scaffold or integration install (Step 4) - Never delete or skip manifest creation -- it is required for upgrade tracking
- During upgrades (Step 3C), always ask before overwriting user-modified files
- The manifest
filesobject uses project-root-relative paths as keys - Checksum format is always
sha256:<hex-digest>(lowercase hex) - When creating a manifest from an existing site (Step 2.3 "Create manifest from current state"), set all files to
managed: trueand use their current checksums as the baseline - In workspace aggregate mode, MUST organize docs navigation by module with per-module subdirectories (Governing: ๐ ADR-0016, SPEC-0014 REQ "Cross-Module Aggregation")
- In workspace aggregate mode, MUST generate a cross-module index page listing all modules with artifact counts
- In workspace aggregate mode, transform scripts run per-module with output directed to module-named subdirectories
- When
--moduleis provided, generate docs for that single module only using flat structure
Key Template Files Referenceโ
Scaffold Mode Templates (templates/docusaurus/)โ
The templates directory contains production-ready versions of all files. The cp -r approach copies everything; you only need to customize docusaurus.config.ts and package.json.
Docusaurus Plugin (plugins/sdd-content/)โ
index.js-- Consolidated Docusaurus plugin that:- Uses
lib-artifact-transformsfor YAML frontmatter parsing (replaces ~120 lines of custom YAML) - Builds the artifact graph per SPEC-0018 edge schema with 5 ADR edge types + 4 spec edge types
- Generates MDX files from ADRs and specs with badges, RFC 2119 keyword highlighting, cross-references (Governing: ๐ ADR-0006, SPEC-0004)
- Generates index pages (landing page, ADR section, spec section) with sidebar hierarchy diagrams
- Generates the artifact graph page with stats, full Mermaid flowchart, and orphan lists
- Implements
getPathsToWatch()for native Docusaurus hot reload (replaces chokidar-cli + concurrently)
- Uses
Integration Mode Templates (templates/integration/sync-spec-docs/)โ
A self-contained Docusaurus plugin with adapted transform scripts.
Plugin Entryโ
index.js-- Docusaurus plugin that runs transforms duringloadContent()and watches source files viagetPathsToWatch()
Transform Scripts (lib/)โ
transform-adrs.js-- ADR transforms with parameterized pathstransform-openspecs.js-- OpenSpec transforms with parameterized pathstransform-utils.js-- Shared utilities (RFC 2119 keywords, cross-references, link fixing)mdx-escape.js-- MDX v3 safety escapingbuild-spec-mapping.js-- Spec ID mapping (returns data instead of writing files)generate-index.js-- Index page generation with parameterized paths
Shared: React Components (templates/docusaurus/src/components/)โ
Used by both modes. In scaffold mode, they live at docs-site/src/components/. In integration mode, they're copied to \{site\}/src/components/design-docs/.
StatusBadge.tsx-- Status with emoji (accepted, proposed, draft, etc.)DateBadge.tsx-- Date display with calendar emojiDomainBadge.tsx-- Domain/category badgePriorityBadge.tsx-- P0-P4 priority levelsSeverityBadge.tsx-- Critical/High/Medium/Low/InfoRFCLevelBadge.tsx-- Maps RFC 2119 keywords to severity colorsRequirementBox.tsx-- Bordered container for spec requirements with ID anchorsField.tsx/FieldGroup.tsx-- Metadata label-value pairs
Shared: Theme and CSS (templates/docusaurus/src/)โ
src/theme/MDXComponents.tsx-- Registers all custom components for use in MDXsrc/css/custom.css-- All badge, keyword, component, and dark mode styles
Referenceโ
integration-mode.mdโ
Generates a build-time Docusaurus plugin into an existing site. The plugin runs the same transforms as scaffold mode but writes output into the existing site's docs tree.
Let \{site\} be the path to the existing Docusaurus site directory (e.g., website/).
3B.1: Install dependencies and copy the pluginโ
First, install lib-artifact-transforms in the site's package.json:
cd {site} && npm install lib-artifact-transforms@github:joestump/lib-artifact-transforms#main
Then copy the integration plugin template from the plugin's templates/integration/sync-spec-docs/ directory to \{site\}/plugins/sync-spec-docs/:
cp -r {plugin-path}/templates/integration/sync-spec-docs {site}/plugins/sync-spec-docs
If \{site\}/plugins/sync-spec-docs/ already exists, ask the user before overwriting.
3B.2: Copy React componentsโ
Copy all component files from \{plugin-path\}/templates/docusaurus/src/components/ to \{site\}/src/components/design-docs/:
mkdir -p {site}/src/components/design-docs
cp {plugin-path}/templates/docusaurus/src/components/*.tsx {site}/src/components/design-docs/
3B.3: Add CSS stylesโ
Read \{plugin-path\}/templates/docusaurus/src/css/custom.css and create \{site\}/src/css/design-docs.css containing ONLY the design-specific styles. Exclude the :root \{ ... \} and [data-theme='dark'] \{ ... \} CSS variable blocks at the top of the file (the ones that set --ifm-color-primary-* and --docusaurus-highlighted-code-line-bg). These are Docusaurus theme colors that would override the existing site's color scheme.
Include everything from the /* Badge Components */ comment onwards.
Then add the CSS import. Check how the site loads custom CSS:
- If the site's
docusaurus.config.tshas acustomCssoption, add'./src/css/design-docs.css'as an additional entry (it can be an array) - Otherwise, add
@import './design-docs.css';at the top of the site's existing custom CSS file
3B.4: Register MDX componentsโ
Check if \{site\}/src/theme/MDXComponents.tsx exists:
If it does NOT exist, create it:
import React from 'react';
import MDXComponents from '@theme-original/MDXComponents';
import DateBadge from '@site/src/components/design-docs/DateBadge';
import DomainBadge from '@site/src/components/design-docs/DomainBadge';
import PriorityBadge from '@site/src/components/design-docs/PriorityBadge';
import SeverityBadge from '@site/src/components/design-docs/SeverityBadge';
import StatusBadge from '@site/src/components/design-docs/StatusBadge';
import RFCLevelBadge from '@site/src/components/design-docs/RFCLevelBadge';
import RequirementBox from '@site/src/components/design-docs/RequirementBox';
import Field from '@site/src/components/design-docs/Field';
import FieldGroup from '@site/src/components/design-docs/FieldGroup';
export default {
...MDXComponents,
DateBadge,
DomainBadge,
PriorityBadge,
SeverityBadge,
StatusBadge,
RFCLevelBadge,
RequirementBox,
Field,
FieldGroup,
};
If it DOES exist, read the existing file and merge the design-docs imports: add import lines for each component from @site/src/components/design-docs/, add component names to the default export, and preserve all existing imports and registrations.
3B.5: Register the plugin in docusaurus.configโ
Read \{site\}/docusaurus.config.ts (or .js) and add the sync plugin to the plugins array. Determine the correct projectRoot by computing the relative path from \{site\} to the project root.
Example -- if the site is at website/ and the project root is ..:
plugins: [
['./plugins/sync-spec-docs', {
projectRoot: '..',
docsPath: 'docs', // adjust to match the site's existing docs path
}],
],
To find the existing docs path, look for the path option in the classic preset's docs config. If not specified, Docusaurus defaults to 'docs'.
If the config already has a plugins array, append to it. If not, add a new plugins property.
3B.6: Add .gitignore entriesโ
Check for .gitignore at the project root. Add entries for the generated output directory:
# Design docs (generated by sync-spec-docs plugin)
{site}/docs/architecture/
3B.7: Run initial build and verifyโ
cd {site} && npx docusaurus build 2>&1 | tail -20
If the build fails, diagnose and fix. Common problems:
- Missing dependencies: run
npm installin the site directory - MDXComponents merge conflict: check the merge was done correctly
- Plugin path error: verify the relative
projectRootis correct
3B.8: Update .claudeignoreโ
Add entries to ignore the site's build artifacts:
{site}/node_modules/
{site}/build/
{site}/.docusaurus/
3B.9: Report resultsโ
Tell the user what was created:
- Plugin installed at
\{site\}/plugins/sync-spec-docs/ - Components installed at
\{site\}/src/components/design-docs/ - CSS added at
\{site\}/src/css/design-docs.css - Generated docs will appear at
\{site\}/docs/architecture/ - The plugin auto-syncs when ADRs or specs change during
npm run start
Then ask: "Integration complete! Want me to start the dev server? (cd \{site\} && npm run start)"
After completion, proceed to Step 4: Create Manifest (back in SKILL.md).
scaffold-mode.mdโ
Creates a standalone Docusaurus site at docs-site/.
-
Check for existing docs-site: Look for
docs-site/in the project root. If it exists, ask the user before overwriting. -
Copy the plugin's Docusaurus templates using
cp -rfrom the plugin'stemplates/docusaurus/directory todocs-site/in the project root. -
Customize for the project by reading and modifying only these files:
docs-site/package.json-- update the project name from$ARGUMENTSor inferred from the repodocs-site/docusaurus.config.ts-- update title, baseUrl, and GitHub URL for this project- Optionally customize the
sdd-contentplugin options if your ADRs/specs are in non-standard locations:adrsDir(default:../docs/adrs)specsDir(default:../docs/openspec/specs)outputDir(default:../docs-generated)
-
Run
npm installin the docs-site directory. -
Update
.claudeignore: Check if.claudeignoreexists at the project root. If not, create it. Add entries to ignore:docs-site/node_modules/
docs-site/build/
docs-site/.docusaurus/If
.claudeignorealready exists, append any missing entries. -
Report and offer to start: Tell the user what was created, then ask: "Docs site created! Want me to start the dev server? (
cd docs-site && npm run start)"
After completion, proceed to Step 4: Create Manifest (back in SKILL.md).
upgrade-mode.mdโ
Entered when .sdd-docs.json exists and the referenced siteDir is present on disk. Updates an existing docs installation to the latest plugin templates while preserving user customizations.
Read the manifest from .sdd-docs.json. Let \{mode\} be the manifest's mode field ("scaffold" or "integration"), and \{site\} be the resolved siteDir.
3C.1: Determine template source pathsโ
Based on the manifest's mode:
- Scaffold: template root is
\{plugin-path\}/templates/docusaurus/ - Integration: template root is
\{plugin-path\}/templates/integration/sync-spec-docs/for plugin files, and\{plugin-path\}/templates/docusaurus/src/components/for shared components
3C.2: Process each managed fileโ
For each entry in the manifest's files object where managed is true:
- Compute the current SHA-256 of the file on disk
- Compare against the manifest's stored
checksum:- Checksums match (file unmodified by user) โ replace silently with the new template version
- Checksums differ (user has modified the file) โ use
AskUserQuestion:- "Accept new version" โ overwrite with the template version
- "Keep current" โ leave as-is, update manifest checksum to current hash
- "Opt out of management" โ set
managed: falsein manifest (skip in future upgrades)
- File missing from disk โ re-create from the template
For entries where managed is false, skip entirely.
3C.2b: Pre-plugin migration detection (Scaffold mode only)โ
If scaffold mode AND \{site\}/scripts/ exists BUT \{site\}/plugins/ does NOT exist:
This is a pre-plugin installation (using the old 8-script approach). Offer the user:
- "Migrate to new plugin" โ delete
\{site\}/scripts/,\{site\}/src/data/spec-mapping.json,\{site\}/src/data/spec-emojis.json(if present); install the newplugins/sdd-content/index.js; updatepackage.json(remove chokidar-cli, concurrently, build-content/watch-content scripts); updatedocusaurus.config.tsto register the plugin - "Keep current setup" โ do not migrate; set all managed files to
managed: false
3C.3: Detect new template filesโ
Check for files in the current plugin templates that are NOT listed in the manifest:
- For scaffold: scan
templates/docusaurus/plugins/sdd-content/,templates/docusaurus/src/components/,templates/docusaurus/src/css/,templates/docusaurus/src/theme/ - For integration: scan
templates/integration/sync-spec-docs/,templates/docusaurus/src/components/
For each new file: install it to the appropriate location and add to the manifest with managed: true and its SHA-256 checksum.
3C.4: Update the manifestโ
Write the updated .sdd-docs.json:
- Set
versionto the current plugin version from.claude-plugin/plugin.json - Set
updatedAtto the current ISO timestamp - Update all
checksumvalues to reflect the current on-disk state - Preserve
createdAtandmodefrom the original manifest
3C.5: Ensure .claudeignore existsโ
Check if .claudeignore includes ignore entries for \{site\}/node_modules/, \{site\}/build/, and \{site\}/.docusaurus/. If any are missing, append them.
3C.6: Run build and verifyโ
- For scaffold: run
npm installin\{site\}ifpackage.jsonchanged, then offer to start the dev server - For integration: run a Docusaurus build to verify the plugin still works
3C.7: Report resultsโ
Tell the user:
- Files updated silently (checksum matched)
- Files with conflicts and what the user chose for each
- New files added
- Files skipped (managed: false)
- New plugin version recorded in the manifest
Example Invocationsโ
generate the docs site from our ADRs and specs
/sdd:docs
scaffold a Docusaurus site that mirrors our design artifacts
rebuild the documentation site with the latest ADRs
set up a docs site so we can publish our architecture decisions