Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
terrylica avatar

Page Template

  • 33 installs
  • 62 repo stars
  • Updated August 3, 2026
  • terrylica/cc-skills

Helps with ai & agent building tasks.

About

page-template is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.

  • page-template
  • AI & Agent Building
  • AI-coding skill

Page Template by the numbers

  • 33 all-time installs (skills.sh)
  • Ranked #8,975 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/terrylica/cc-skills --skill page-template

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs33
repo stars62
Last updatedAugust 3, 2026
Repositoryterrylica/cc-skills

What it does

Helps with ai & agent building tasks.

Files

SKILL.mdMarkdownGitHub ↗

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` 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`.

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`:

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

LayerMutabilityWhat it controlsWhere it lives
H1 — KernelEdit once → ripples everywhereTokens (color, spacing, type), reset, base elements, componentsassets/showcase.css (jsDelivr CDN)
H2 — CompositionPer-pageSection order, content, semantic markupThe HTML file itself
H3 — OverridesPer-page (optional)Color or density tweaks for ONE pageoverrides.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 — 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).

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:

VariableEffect
NO_HTMLSHOWCASE_HOOK=1Skip the hook entirely
NO_HTMLSHOWCASE_SYNC=1Run nav + search but skip the rsync
NO_HTMLSHOWCASE_SEARCH=1Skip the pagefind regen step
HTMLSHOWCASE_SITES="a b c"Override auto-detection with explicit list

Four contributor stances

Pick the role that matches your task. Full workflow for each in `references/contributing.md`.

RoleExample taskEditsAffects
Consumer"Make me a contractor showcase site"Your HTMLJust your site
Customizer"Re-theme this site with our brand teal"overrides.cssJust your site
Contributor"Add a .timeline component to the kernel"Kernel CSS upstreamEvery site using this kernel
Publisher"Our team forks the kernel and publishes from our own GitHub"Your fork's kernelSites that pin to _your_ CDN URL

When to use this skill

  • Creating a static HTML site (one page or many) that records structured

work: audits, commits, metrics, reports, contractor showcases, telemetry views, weekly digests

  • Replacing inline-CSS pages with the shared design system + auto-nav
  • Bootstrapping a multi-page mini-site that grows into a contractor

portfolio, weekly-digest archive, or release-notes hub — without ever hand-maintaining the navigation

Do NOT use for: blog posts, marketing landing pages, interactive web apps.

What ships in this skill

PathRole
templates/index.htmlSite home skeleton (hero + 3 example sections + footer + markers)
templates/section-index.htmlSection landing-page skeleton
templates/overrides.css.exampleReference for per-site customization (rename to overrides.css)
templates/lychee.tomlLink-checker config
scripts/build-nav.pyUniversal sitemap builder — auto-nav + site-map.html generator
scripts/check-orphan-pages.pyPure-stdlib orphan-page graph validator
scripts/site.shBuild nav + validate + push to bigblack via Tailscale (see below)
scripts/install.shOne-shot bootstrap: install all 3 scripts into any repo
references/principles.mdThe WHY — five principles + AI patterns
references/sitemap.mdThe HOW — filesystem-as-sitemap contract, rail rendering
references/contributing.mdThe HOW — four stances with full workflows
references/publishing.mdThe WHERE — delivery surfaces (CDN vs tailnet) + bigblack setup

The CSS kernel itself lives at the plugin level (plugins/html-showcase/assets/showcase.css) and is served from jsDelivr — the skeleton HTML references the public CDN URL, not a local file.

Where finished sites get hosted

Two surfaces, two roles:

SurfaceWhat goes thereWhen to use
jsDelivr CDN (public)The kernel CSS onlyAlways — every page imports the kernel from one shared URL
bigblack on the tailnetYour rendered sitesDefault for internal audiences (no DNS, no auth UI, no public exposure)
jsDelivr / Pages / WorkersYour rendered sitesOnly when an external reader genuinely needs the page

For internal-audience sites (audit reports, contractor showcases, telemetry views, weekly digests), the bigblack tailnet path is the lowest-friction option. Adopting it in any repo is one command:

PLUGIN=${CLAUDE_PLUGIN_ROOT:-~/.claude/plugins/marketplaces/cc-skills/plugins/html-showcase}
bash "$PLUGIN/skills/page-template/scripts/install.sh"

That installs all three pipeline scripts (build-nav.py, check-orphan-pages.py, site.sh) into <repo>/scripts/ and appends **/.published.json to .gitignore. The installer is idempotent (re-running it is a no-op) and non-destructive (--force to overwrite). To also seed a starter site directory:

bash "$PLUGIN/skills/page-template/scripts/install.sh" --site contractor-site

Then scripts/site.sh push <site-dir> regenerates the sitemap, validates locally (lychee + orphan check), and rsyncs to bigblack:~/sites/<repo>/<site-dir>/, served at https://bigblack.tail0f299b.ts.net:8448/<repo>/<site-dir>/. Push-side gating (build-nav + lychee + orphan check) is the only gate. Full mechanics, the URL formula, when NOT to use bigblack, and the bigblack one-time setup are in `references/publishing.md`.

Universal density knobs

Two CSS custom properties at the top of showcase.css control the entire visual rhythm. Override either in overrides.css to retune one site:

:root {
  --density: 0.85; /* spacing multiplier; 1.0 baseline, lower = tighter */
  --font-scale: 0.94; /* type multiplier; 1.0 baseline, lower = smaller */
}

Every padding, gap, margin, and section rhythm in the kernel derives from the spacing scale; the spacing scale derives from --density. Body font size derives from --font-scale. There are no scattered magic numbers in component CSS — see Principle 3 in references/principles.md.

Component vocabulary

The kernel defines these semantic classes; HTML uses them. To inspect the full set, open the kernel CSS and search for class selectors.

ClassPurpose
.hero + .hero__inner / __eyebrow / __title / __lede / __cta-rowTop banner with gradient
.chip--solid / .chip--ghostHero CTA buttons
.metric-grid + .metric-cardAt-a-glance number panel; modifiers --accent, --success, --warning
.phase-grid + .phase-cardPhased timeline cards; modifiers --audit, --fix, --perf
.commit-stack + .commit-cardDetailed commit cards with SHA chip + details grid
.bug-grid + .bug-card (--high modifier)Compact issue cards
.feature-grid + .feature-cardGeneric 4-column showcase grid with icon
.reco-list + .reco-item (--p0 / --p1 / --p2)Priority-ordered recommendations
.badge (--high / --medium / --low / --success / --info / --neutral / --accent)Severity / status labels
.section-head / .section-introPer-section title row + framing paragraph
.shellCentered content shell with max-width and responsive padding
.site-footer + .site-footer__grid / __legalProvenance footer

The auto-nav rail uses its own non-kernel classes (.auto-nav-rail, .rail-link, .rail-section, etc.) defined in auto-nav.css so the nav stays self-contained and a repo can adopt the rail without adopting the kernel.

If your page needs a content component not in this table, you have two choices — both legitimate, both documented in references/contributing.md:

  • Add it to the kernel (Stance 3): semantic class name in the

components @layer, token-referenced values, BEM modifier variants.

  • Use a local override for one-off cases (Stance 2): only if the

pattern is genuinely unique to one page; recurring patterns belong in the kernel.

Quick start (Consumer stance, sitemap-organized)

The fastest path: run the installer to bootstrap the pipeline scripts + a starter site, then iterate.

PLUGIN=${CLAUDE_PLUGIN_ROOT:-~/.claude/plugins/marketplaces/cc-skills/plugins/html-showcase}

# 1. Bootstrap the pipeline + starter site directory
bash "$PLUGIN/skills/page-template/scripts/install.sh" --site contractor-site

# 2. (Optional) Add one or more sections under contractor-site/
mkdir -p contractor-site/2026-05-02-first-section
cp "$PLUGIN/skills/page-template/templates/section-index.html" \
   contractor-site/2026-05-02-first-section/index.html
cp "$PLUGIN/skills/page-template/templates/index.html" \
   contractor-site/2026-05-02-first-section/page-a.html

# 3. Fill {{ PLACEHOLDERS }} in the HTML, then build the sitemap + nav
scripts/site.sh nav contractor-site

# 4. Validate (lychee + orphan check)
scripts/site.sh check contractor-site

# 5. View — any page reaches every other via the rail
open contractor-site/index.html
open contractor-site/site-map.html

Or, if you'd rather copy the templates by hand without the installer:

PLUGIN=${CLAUDE_PLUGIN_ROOT:-~/.claude/plugins/marketplaces/cc-skills/plugins/html-showcase}
DEST=/path/to/your-site
mkdir -p "$DEST"
cp "$PLUGIN/skills/page-template/templates/index.html"   "$DEST/"
cp "$PLUGIN/skills/page-template/templates/lychee.toml"  "$DEST/"
python3 "$PLUGIN/skills/page-template/scripts/build-nav.py" --root "$DEST"

site.sh falls back to the plugin-shipped build-nav.py when no copy is present in <repo>/scripts/, so even without the installer you can push to bigblack from any repo using the plugin-shipped script directly.

For the other three stances (Customizer, Contributor, Publisher), see `references/contributing.md`. For the publishing path to bigblack via Tailscale, see `references/publishing.md`.

CDN versioning

The kernel URL pins to the @main branch during early iteration, then to a tagged release once the kernel stabilizes:

@main      → always-latest         → use during development; jsDelivr cache flushed automatically on each release
@v<X.Y.Z>  → immutable, content-locked → use for production-stable pages
@<sha>     → immutable, commit-locked  → use for forensic-grade pinning

The release flow auto-purges @main and smoke-tests @v<X.Y.Z> after each release. To force-refresh @main between releases (e.g., during heavy iteration on the kernel), run mise run release:cdn-purge from the cc-skills repo. To bypass cache entirely on a single page, append ?v=$(date +%s) to the kernel link.

The auto-nav assets (auto-nav.css, auto-nav.js) are generated locally by build-nav.py and live next to your HTML — they are not CDN-served. The ?v=N query string on those URLs is also a cache-bust knob; bump --asset-version when you change the rail's CSS or JS body inside build-nav.py.

Hard rules

These are baked into the kernel and templates; if you find yourself wanting to break them, fix the kernel instead (see Stance 3 in references/contributing.md).

  • No inline <style> blocks.
  • No style="" attributes on HTML elements.
  • No utility-class soup in HTML — class names are semantic

(.metric-card, .badge--high), never atomic (flex p-4 bg-blue-500).

  • The kernel is the single source of truth for every visual decision.
  • HTML only arranges components; it never invents them.
  • The filesystem layout IS the navigation graph; never hand-author the

rail HTML between <!-- AUTO-NAV-START --> and <!-- AUTO-NAV-END -->. Re-run scripts/build-nav.py after any structural change.

  • Every site must pass Lychee link-check and the orphan-page detector

before it's considered shipped.

Post-Execution Reflection

After this skill completes, reflect before closing the task:

0. Locate yourself. — Find this SKILL.md's canonical path before editing. 1. What failed? — Fix the instruction. If a kernel component was missing, add it (Stance 3). If the sitemap rail rendered something surprising, fix build-nav.py AND references/sitemap.md. If a _principle_ was unclear, fix references/principles.md. 2. What worked better than expected? — If a new section pattern recurs, distill it into a kernel component or into templates/section-index.html. 3. What drifted? — Keep CDN URL pins, override examples, component vocabulary, and the rail HTML markers aligned across SKILL.md, the templates, and build-nav.py. 4. Log it. — Evolution-log entry with trigger, fix, evidence.

Do NOT defer. The next invocation inherits whatever you leave behind.

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.