page-template
Scaffold a sitemap-organized HTML showcase site (provenance reports, contractor showcases, telemetry dashboards, weekly digests, audit results).
What this skill does
# HTML Showcase — Page Template
> **Self-Evolving Skill**: This skill improves through use. If instructions
> are wrong, parameters drifted, or a workaround was needed — fix this file
> immediately, don't defer. Only update for real, reproducible issues.
A static HTML mini-site whose **navigation structure is the filesystem
layout itself**. Every page links to a shared CSS kernel served from
jsDelivr; an auto-discovered nav rail and a master `site-map.html` are
generated by `scripts/build-nav.py` from whatever directories you create
under the site root. Pages are pure HTML with optional per-page CSS
overrides. The architecture is built on five principles — **read
[`references/principles.md`](references/principles.md) first** to
internalize the WHY before extending or forking, and
[`references/sitemap.md`](references/sitemap.md) for the navigation
contract.
## The sitemap is the default
Every site this skill produces has the same shape:
```
<site-root>/
index.html ← site home (recommended)
overrides.css ← optional per-site tweaks
auto-nav.css ← generated by build-nav.py
auto-nav.js ← generated by build-nav.py
site-map.html ← generated by build-nav.py
<section-1>/ ← any subdirectory becomes a "section"
index.html
page-a.html
page-b.html
<2026-05-02-audit>/ ← YYYY-MM-DD- prefix sorts sections newest-first
index.html
findings.html
```
You don't hand-write the nav. You add HTML files in the directory shape
you want, then run `scripts/build-nav.py --root <site-root>`. The script
walks the tree, generates `site-map.html`, writes the rail's CSS/JS, and
injects the same nav rail into every page using comment markers. Re-runs
are idempotent.
For the architecture and trade-offs, see
[`references/sitemap.md`](references/sitemap.md).
## Read this skill at the principle level, not the instruction level
Every concrete artifact in this skill (class names, file paths, the
specific CDN URL, the commit-message conventions, even the "section"
naming) is an _instance_ of a small set of underlying principles. If you
understand the principles, you can deviate intelligently from any
specific instance without breaking the architecture. If you only follow
the instructions, you'll bend the system out of shape the first time
something doesn't fit your case.
The principles are catalogued in [`references/principles.md`](references/principles.md):
1. **Single source of truth** — every visual decision lives in one file
2. **Semantic over atomic** — class names describe what an element _is_
3. **Token-driven** — every concrete value flows from a CSS custom property
4. **Cascade discipline** — `@layer` ordering enforces specificity globally
5. **No hidden state** — no JS, no inline CSS, no scattered overrides
6. **Filesystem-as-sitemap** — directory layout IS the navigation graph
Plus AI-collaboration patterns (why this design is LLM-friendly), and
the rationale for using a CDN rather than copies.
## Three-layer hierarchy
| Layer | Mutability | What it controls | Where it lives |
| -------------------- | ------------------------------ | --------------------------------------------------------------- | ------------------------------------ |
| **H1 — Kernel** | Edit once → ripples everywhere | Tokens (color, spacing, type), reset, base elements, components | `assets/showcase.css` (jsDelivr CDN) |
| **H2 — Composition** | Per-page | Section order, content, semantic markup | The HTML file itself |
| **H3 — Overrides** | Per-page (optional) | Color or density tweaks for ONE page | `overrides.css` next to the HTML |
The kernel is the SSoT for every visual decision. HTML never invents
styles; it only arranges components defined by the kernel. To customize
one page, drop a few CSS variables into `overrides.css`. To customize
EVERY page, edit the kernel.
The auto-nav rail is _generated_, not hand-written. Its styling lives in
`auto-nav.css` (written by `build-nav.py`); its content is injected
between `<!-- AUTO-NAV-START -->` and `<!-- AUTO-NAV-END -->` markers in
each page's `<body>`.
The rail and the master `site-map.html` are **always dark** (slate-950
surface, slate-300 text, indigo-400 accents), regardless of the host
page's theme. The rail is the constant element across every page; pinning
its theme keeps it visually stable whether the page it overlays is a
light contractor showcase or a dark telemetry dashboard.
Pages within a section render in **creation order**, not alphabetical:
- `index.html` always first.
- Pages following the `index_iter_<N>_<slug>.html` naming convention sort
by `N` numerically (so `iter_10` comes after `iter_9`, not after `iter_1`).
- Other top-level pages sort by filesystem birthtime (`st_birthtime` on
macOS — never moved by edits or rebuilds).
- Nested pages fall back to the original subdir + index-first + alpha grouping.
The rail's runtime behavior:
- **First load**: width auto-fits to the longest unwrapped link (uses
`width: max-content` to measure each link's true intrinsic width,
independent of the rail's current size), clamped to `[220, 760]px`.
- **Drag the right-edge handle**: resize manually within `[220, 1200]px`;
the chosen width is persisted in `localStorage`.
- **Double-click the handle**: clears the saved width and re-runs
auto-fit (semantically: "reset to smart default").
- The handle is a 14px hit zone with an always-visible 2px indicator
line and a hover tooltip explaining the dual gesture.
- **Within-section Prev/Next**: pages inside a section get compact `‹ ›`
buttons on the "Site" header row (zero added height) plus a Chrome-safe
bare `[` / `]` keyboard shortcut. `‹` / `[` goes to the sibling above
(newer), `›` / `]` to the one below (older); both are greyed out at the
ends of the list. The keys ignore presses while a modifier is held or
while focus is in the search box, so they never interrupt typing.
## Search is on by default
Every rail (and the master `site-map.html`) gets a **Search** section
mounted at the top, powered by [Pagefind](https://pagefind.app/) — a
Rust-built static-search tool that produces a self-contained index with
no server, no build pipeline, and a ~70KB client UI.
How it's wired:
- `build-nav.py` injects 4 tags into every page's `<head>` in strict
order: pagefind CSS → auto-nav CSS → pagefind JS → auto-nav JS.
- The rail's first section is `<div id="auto-nav-search"></div>`;
`auto-nav.js` calls `new PagefindUI({...})` once Pagefind has loaded.
- The actual index lives at `<site-root>/pagefind/`, generated by
running `pagefind --site <site-root>`.
- `scripts/site.sh nav` runs `build-nav.py` AND `pagefind --site` —
search refreshes automatically every time the rail is rebuilt.
If `pagefind` isn't installed, the rail still renders with the search
input present but inert; `auto-nav.js`'s `mountSearch()` short-circuits
when `window.PagefindUI` is undefined. Install via `brew install
pagefind` (or follow the [official install docs](https://pagefind.app/docs/installation/)).
## Push-as-hook auto-resync
`install.sh --hook` installs a pre-push git hook at `.githooks/pre-push`
and wires `git config core.hooksPath .githooks`. After that, every
`git push main` automatically:
1. Auto-detects every site dir in your repo (any directory containing a
`site-map.html`)
2. Runs `scripts/site.sh nav <site-dir>` (rebuilds rail + search index)
3. Runs `scripts/site.sh push <site-dir>` (rsync to bigblack via
Tailscale)
The hook is **non-blocking** — if rsync fails (cellular, coffee shop,
bigblack down), the push continues to GitHub anyway. Skip env vars:
| Variable | Effect |
| -----------------------Related in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.