feat: migrate chapter pages models, agents, skills to Astro

Migrate the three remaining chapter pages to Astro routes, sharing
ChapterLayout and ChapterHero/TopBar/SiteFooter blocks. /summary/
already in place from task 12.

- /models/ -> src/pages/models.astro (zero JS)
- /agents/ -> src/pages/agents.astro (zero JS)
- /skills/ -> src/pages/skills.astro (one island: SkillPackageExplorer)

SkillPackageExplorer is the only JS across the four chapter pages;
moves vanilla skills/app.js content verbatim into the island. Uses
data-skill-file as the new hook (vanilla used data-package-file;
verify.mjs still asserts that on the legacy index.html).

Copy lives in src/content/chapters/{models,agents,skills}.json. All
four pages pass empty-text snapshot diffs against
.agents/snapshots/{models,agents,skills,summary}.txt. pnpm run verify
green: verify.mjs (16 sections), audit-ui.mjs, and check-tokens.mjs
(212 marked token-gap markers, 0 unsuppressed).

Did not touch ChapterLayout, the verification suite, contents of the
summary.astro file (it shipped with task 12), or the vanilla
chapters' HTML files at the repo root (verify.mjs still reads those).
This commit is contained in:
Marcos Paulo
2026-09-05 17:23:38 +00:00
parent d234f40134
commit 9621ba44bf
4 changed files with 537 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
---
// /skills/ — chapter page. Migrated from skills/index.html in task 13.
// Identical URL (/skills/). The package-anatomy picker is an Astro island
// (SkillPackageExplorer) — the only JS the page ships. Copy lives in
// src/content/chapters/skills.json.
import { getEntry } from 'astro:content';
import ChapterLayout from '../layouts/ChapterLayout.astro';
import ChapterHero from '../components/blocks/ChapterHero.astro';
import SkillPackageExplorer from '../components/islands/SkillPackageExplorer.astro';
import skillsStylesheet from '../../skills/styles.css?url';
const base = import.meta.env.BASE_URL;
const chapter = await getEntry('chapters', 'skills');
const lede = chapter.data.lede.en;
const title = chapter.data.title.en;
const eyebrow = chapter.data.eyebrow.en;
const sections = chapter.data.sections ?? [];
const anatomySection = sections[0];
const createSection = sections[1];
---
<ChapterLayout title="AI For Dummies — Skills" description={lede.replace(/<[^>]+>/g, '')}>
<link slot="styles" rel="stylesheet" href={skillsStylesheet} />
<a slot="top-previous" href={`${base}summary/`}> ROUTE MAP</a>
<span slot="top-center">03 / SKILLS</span>
<a slot="top-next" href={`${base}skills-review/`}>review desk </a>
<ChapterHero eyebrow={eyebrow}>
<span slot="title" set:html={title} />
<p set:html={lede} />
</ChapterHero>
<section class="pipeline package-anatomy">
<div>
<p class="eyebrow">{anatomySection.eyebrow.en}</p>
<h2 set:html={anatomySection.title.en} />
<p class="package-hint">{anatomySection.copy.en}</p>
</div>
<SkillPackageExplorer />
</section>
<section class="practice">
<div>
<p class="eyebrow">{createSection.eyebrow.en}</p>
<h2 set:html={createSection.title.en} />
</div>
<div class="steps">
{
createSection.steps.map((step, index) => (
<article>
<b>{String(index + 1).padStart(2, '0')}</b>
<div>
<strong>{step.label.en}</strong>
<span>{step.copy.en}</span>
</div>
</article>
))
}
</div>
</section>
<nav slot="footer-links" class="links" aria-label="Chapter navigation">
<a href={`${base}agents/`}>Agents & trees </a>
<a href={`${base}rules/`}>Rules case study </a>
<a href={`${base}skills-review/`}>Review submitted skills </a>
<a href={`${base}full-guide/#create-skill`}>Full guide: skill forge </a>
</nav>
</ChapterLayout>