WORK-408
ID:WORK-408Status:done

Gallery generator — layout fixtures

Extend the gallery generator (WORK-407) to a second subject class: layout fixtures — representative sample pages rendered through each LayoutConfig so page chrome (header, nav, sidebar, TOC, mobile panel, footer) is visually covered. Chrome carries as much of a theme's identity as runes, and the skeleton/skin extraction touches styles/layouts/*, so this is what lets the harness guarantee hold for chrome, not just content blocks.

Priority:mediumComplexity:moderateMilestone:v0.22.0Source:SPEC-094
claude/work-408-layout-fixtures View source

Criteria completion

Criteria completion: 3 of 3 (100%) checked; tracking started on Jun 12, no incremental history yet0%25%50%75%100%Jun 12Jun 15

Tracking started Jun 12 — check back for trends.

Branches 2
claude/work-408-layout-fixtures current done
main doneclaude/v0.22.0-theme-foundations pending
History 1
  1. 955acbd
    Created (done)by bjornolofandersson

Scope

  • Render the existing layouts (default, docs, blog-article, plan) via renderPage over a synthetic multi-page context so computed chrome (breadcrumb, TOC, nav tree, prev/next from the aggregate phase) populates.
  • Emit per-layout artifacts suitable for multi-viewport capture (mobile / tablet / desktop).
  • Default pre-enhancement chrome state is the baseline; enhanced states (mobile menu open) are an optional follow-on, out of scope here.

Acceptance Criteria

  • The generator emits a fixture per existing layout, with computed chrome populated from a synthetic content set.
  • Fixtures render correctly at mobile / tablet / desktop widths.
  • Output is deterministic and theme-agnostic, consistent with the rune gallery.

Dependencies

  • Builds on WORK-407 (shared generator command).

References

  • SPEC-094 · packages/transform/src/layouts.ts · packages/html/src/render.ts · packages/lumina/styles/layouts/*.

Resolution

Completed: 2026-06-12

Branch: claude/work-408-layout-fixtures.

What was done

  • buildSyntheticPage() (commands/gallery.ts) — one synthetic LayoutPageData shared across all layouts: a representative article body (headings + prose + a hint), regions for header / nav (the nav fixture) / footer / sidebar / pagination, ~6 pages, headings (for the TOC), and blog frontmatter (title/date/author/tags). This populates the computed chrome (breadcrumb, TOC, nav tree, prev/next) and every region the four layouts source from.
  • Render each built-in layout (defaultLayout, docsLayout, blogArticleLayout, planLayout from @refrakt-md/transform) via layoutTransform → renderToHtml, wrapped by the new renderLayoutDocument() (lib/gallery.ts) — a standalone full-page shell (theme CSS + fonts + behaviors, no gallery cell-grid chrome), so the layout is the page.
  • Refactored the rune pipeline into a shared sourceToTree() (used by both rune cells and layout content/regions).
  • Emits <theme>.layout-<name>.<light|dark>.html (8 files) alongside the rune gallery.

Verified

  • Chrome populates: docs → rf-layout-docs + rf-docs-header + rf-docs-sidebar + rf-breadcrumb + rf-on-this-page/rf-toc + rf-nav; blog-article → article header with date/author/title from frontmatter.
  • Deterministic (layout fixtures byte-identical across runs); theme-agnostic (driven by --theme CSS + the built-in layout configs). 128 CLI tests green (incl. 2 new renderLayoutDocument tests).

Notes

  • Each layout is emitted as one viewport-agnostic document; the responsive layout CSS is width-driven, so the WORK-409 harness shoots each whole-page at mobile/tablet/desktop (per SPEC-094 §5). The gallery doesn't emit per-viewport HTML.
  • Behaviors (mobile-menu, search, theme-toggle, section-nav) are wired by the same inlined initPage bundle as the rune gallery (WORK-416).