# SmartStack CLI Documentation Generator

Generates the static HTML documentation served by `ss docs` from:

- **Skill metadata** — every `templates/skills/**/SKILL.md` YAML frontmatter
  (`name`, `description`, `argument-hint`, `allowed-tools`, `phase`, …)
- **Page narrative** — `docs-src/*.md` with frontmatter for slug, title, icon,
  chosen page template and optional `layout: wide` (wide column, no TOC)
- **Sidebar layout** — `docs-src/_data/sidebar.json`: two audience zones,
  `discover` (non-technical readers, rendered first) then `tech`; each section
  declares its `audience`. The breadcrumb is derived from it.
- **Package version** — `package.json:version` (auto-injected as the badge)

Output, committed to git so the npm package ships ready-to-view documentation:

- `.documentation/*.html` — one page per `docs-src/*.md`;
- `.documentation/manifest.json` — the page list `ss docs` reads at runtime;
- `.documentation/js/search-index.js` — the search index. `ss docs` opens the
  site over `file://`, where `fetch()` is refused, so the index is a script
  setting `window.SS_DOCS_INDEX`. The build fails if an indexed anchor is
  missing from its page.

Every `<h2>`/`<h3>` gets an accent-free `id` at build time (marked emits
none); the h2 list feeds the "on this page" column and the search index.

## Commands

```bash
npm run build:docs          # one-shot regeneration
npm run build:docs:watch    # rebuild on change (chokidar)
npm run docs:check          # exit 1 on drift (CI gate)
npm run docs:dev            # build + serve at http://localhost:8080
```

The `prebuild` npm hook automatically runs `build:docs` before `npm run build`,
and `prepublishOnly` chains `docs:check && build` so a stale tree cannot ship.

## Architecture

```
scripts/generate-docs/
├── index.ts                # orchestrator
├── lib/
│   ├── skill-parser.ts     # walks templates/skills/**/SKILL.md
│   ├── markdown-parser.ts  # gray-matter + marked on docs-src/*.md
│   ├── sidebar-builder.ts  # loads + validates docs-src/_data/sidebar.json (zones, audience)
│   ├── page-outline.ts     # heading ids + FR/EN section text of a rendered page
│   ├── search-index.ts     # js/search-index.js + dead-anchor check
│   ├── i18n-types.ts       # Lang / Localised helpers
│   ├── context-builder.ts  # per-page Handlebars context
│   ├── handlebars-setup.ts # helpers + partial registration
│   ├── stats.ts            # counts skills/agents/hooks/cli commands
│   └── version.ts          # reads package.json
├── templates/
│   ├── layout.hbs          # outer HTML shell
│   ├── partials/           # header, sidebar, toc, search, icons, deploy-flow, skill-list, ...
│   └── pages/              # one .hbs per logical page kind
└── README.md               # this file
```

The generator NEVER touches `.documentation/css/styles.css`,
`.documentation/js/app.js` or `.documentation/img/` — those are hand-maintained.
The stylesheet defines every color as a token, dark by default and light when
the OS asks for it (`prefers-color-scheme`) or the header toggle sets
`data-theme`.

## How do I…

### Add a new page

1. Create `docs-src/<slug>.md` with frontmatter (see existing pages).
2. Either reuse `pages/_generic.hbs` (set `page: _generic`) or add a custom
   template under `templates/pages/<slug>.hbs`.
3. Add an entry to `docs-src/_data/sidebar.json` (validation enforces this):
   in the `discover` zone for a page aimed at non-technical readers, in a
   `tech` section otherwise.
4. Open the page with an "En bref" box (`<div class="tldr">`) and fold deep
   content into `<details class="more">` — keep the h2 headings visible.
5. Run `npm run build:docs` and commit the new `.documentation/<slug>.html`
   and `js/search-index.js`.

### Use a partial inside a markdown page

The markdown body is pre-processed by Handlebars, so `{{> deploy-flow}}`
(the branch / environment schema) works in `docs-src/*.md`. A partial used
that way must contain no blank line: a blank line ends a raw HTML block in
markdown.

### Rename a skill

1. Update the skill's `SKILL.md` frontmatter (`name:`) and rename the folder
   under `templates/skills/`.
2. The installer's deploy rule (`src/lib/installer.ts:remapSkillPath`) and the
   doc generator's identical mirror (`templates/skills/lib/skill-slug.ts`)
   both pick up the new slug — no other change needed.
3. `npm run build:docs` regenerates every page that lists the skill (commands,
   business-analyse, ba-develop, etc.).

### Add a new sidebar section

Edit `docs-src/_data/sidebar.json` → `sections[]`. Each section has an
`audience` (`discover` | `tech`) and, in the `tech` zone, a `title`. Each item
references a page slug; missing slugs fail the build (see
`sidebar-builder.ts:validateSidebar`).

### Debug a render

`{{json someValue}}` Handlebars helper dumps any context value. Useful when
extending partials. Remove before committing.

## Anti-patterns

- ❌ **Do not edit `.documentation/*.html` directly.** They carry an
  `AUTO-GENERATED` header comment; CI rejects hand-edits via `docs:check`.
- ❌ **Do not duplicate skill descriptions** in `docs-src/*.md`. The whole point
  is that the YAML frontmatter is the single source of truth.
- ❌ **Do not bake the version number** into any markdown — it is injected at
  build time from `package.json`.
