79920c9e6c
Three strands of work on the chapter surface, all reading from the same constraint: this site ships no runtime dependencies, so every effect below is native CSS or an .astro component. Motion (src/styles/motion.css, DrawRule.astro). A scroll-driven layer of reveals, hero parallax, section depth, and a hairline that paints itself along its path, scrubbed by `animation-timeline: view()` — 0KB against lottie-web's ~60KB gzipped on the main thread. Every scrubbed rule sits inside `prefers-reduced-motion: no-preference` and `@supports`, so a Firefox reader or an opted-out one gets the complete static page rather than one with holes in it. Ranges key to `cover 40%`-`cover 75%` where the motion is meant to be watched: `view()` ranges key to first visibility, which on a 2600px page is long before anyone is reading the section. `.agents/skills/motion/references/scroll-driven.md` records the technique and the two ways `pathLength` normalisation was broken while building it. Diagrams (StepFlow.astro, WorktreeMap.astro). The `.steps` stack on /skills/, /models/, and /agents/ becomes a numbered flow with connectors, and /agents/ grows the worktree map it was describing in prose — reusing the `trees` collection rather than a second set of strings. The map's static variant is gated one class deeper than full-guide's page styles, so the interactive copy renders byte-identical. Connectors are pseudo-elements, not SVG: a stretched path desynchronises its own dash pattern, and a straight line does not need one. Mermaid was considered and rejected at ~1MB of runtime. Retrieval practice (/rules/, /skills/). A "check yourself" section of native `<details>` question/answer pairs plus a citation row, both bilingual through the existing `data-copy` toggle, and both JavaScript-free. Two audit blind spots surfaced and are closed rather than worked around: `build.inlineStylesheets: 'never'`, because Astro inlined sheets under ~4kB and audit-ui.mjs reads its colour and size baseline from dist/_astro/*.css; and `--columns` declared in the grid components, because an element-level custom property is not a declaration the audit can resolve. legacy/styles/skills.css is renamed and imported for its side effect. Inside a *page*, `?url` resolves to that page's own CSS chunk whatever file it names, so the link pointed at the wrong asset and the sheet was emitted but never loaded — the package preview had been rendering unstyled and overflowing since the Astro cutover. verify.mjs gains 5 assertions for the recall sections and their Portuguese copy: 89 now, against the 84 baseline. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
90 lines
4.9 KiB
Markdown
90 lines
4.9 KiB
Markdown
# Context: architecture
|
|
|
|
## Current (Astro, static output)
|
|
|
|
Ten routes, one `src/pages/` entry each, built to `dist/`:
|
|
|
|
| Route | Page | Islands |
|
|
| -------------------- | ------------------------------- | ----------------------------------------------- |
|
|
| `/` | `src/pages/index.astro` | — |
|
|
| `/full-guide/` | `src/pages/full-guide.astro` | `GuideSelector`, `LanguageToggle`, `CopyPrompt` |
|
|
| `/summary/` | `src/pages/summary.astro` | — |
|
|
| `/models/` | `src/pages/models.astro` | — |
|
|
| `/agents/` | `src/pages/agents.astro` | — |
|
|
| `/skills/` | `src/pages/skills.astro` | `SkillPackageExplorer` |
|
|
| `/rules/` | `src/pages/rules.astro` | `RulesInteractive` |
|
|
| `/skills-review/` | `src/pages/skills-review.astro` | `legacy/skills-review/app.js` |
|
|
| `/hands-on/starter/` | `public/` lab fixture | own |
|
|
| `/hands-on/rules/` | `public/` lab fixture | own |
|
|
|
|
## What is still unmigrated
|
|
|
|
`legacy/` holds the parts the migration did not componentize. They are not dead
|
|
files — the pages listed above import them, and the build fails without them.
|
|
|
|
- **`legacy/styles/guide.css`** (was `styles.css`) — the editorial visual
|
|
system, imported by `full-guide.astro`.
|
|
- **`legacy/styles/audit.css`** (was `full-guide/audit.css`) — responsive audit
|
|
overrides, imported by `full-guide.astro`.
|
|
- **`legacy/styles/chapters.css`** — imported by `ChapterLayout.astro`.
|
|
- **`legacy/styles/skills-chapter.css`**, **`skills-review.css`**,
|
|
**`change-lens.css`** — imported by their respective pages.
|
|
`skills-chapter.css` is imported for its side effect, not through the `?url` +
|
|
`<link slot="styles">` pattern the layout uses: inside a **page**, `?url` on a
|
|
stylesheet resolves to that page's own CSS chunk rather than to the imported
|
|
file, so the link points at the wrong asset and the sheet is emitted but never
|
|
loaded. It was named `skills.css` and silently unloaded that way until
|
|
2026-09-06.
|
|
- **`legacy/skills-review/`** — `app.js` and the module graph under it
|
|
(`catalog.js`, `submitted-catalog.js`, `files.js`, `submitted-files.js`,
|
|
`vote.js`). `catalog.js` + `submitted-catalog.js` are the review desk's real
|
|
data model, 24 entries; they are a content collection in all but name.
|
|
|
|
These sit outside `src/` deliberately: `check-tokens.mjs` sweeps `src`, and
|
|
these files are full of raw hex and unnamed breakpoints. Moving one into `src/`
|
|
means migrating it to tokens in the same change, not adding an exclusion.
|
|
|
|
`responsive.css`, `landing.css`, `app.js`, `rules/app.js`, `rules/styles.css`,
|
|
and `skills/app.js` were deleted at cutover: their content lives in components.
|
|
|
|
## Layout
|
|
|
|
```
|
|
src/
|
|
content/ catalog entries, chapter copy, EN/PT strings (typed collections)
|
|
layouts/ BaseLayout, ChapterLayout, GuideLayout
|
|
components/ .astro by default; islands only where marked
|
|
styles/ tokens.css, base.css, then per-component styles
|
|
pages/ routes mirroring today's URLs exactly
|
|
public/
|
|
hands-on/ lab fixtures copied verbatim, never processed
|
|
```
|
|
|
|
### Non-negotiables
|
|
|
|
- **URLs do not change.** `/full-guide/`, `/skills-review/`,
|
|
`/hands-on/starter/` and the rest must resolve exactly as they do now,
|
|
trailing slash included. Existing links (including `docs/`, SilverBullet, and
|
|
shared URLs with `?author=…&skill=…&view=…` query params) must keep working.
|
|
- **Zero JS by default.** Seven of the ten pages ship no JavaScript. They must
|
|
still ship none. Islands are opt-in, per component, and justified.
|
|
- **`hands-on/` stays vanilla.** It lives in `public/` untouched. It is a lab
|
|
fixture, not a component.
|
|
- **No external runtime requests.** `audit-ui.mjs` enforces this and it is part
|
|
of the site's thesis. Self-host anything you add.
|
|
- **The review desk's query-param deep links keep working** — `?author=`,
|
|
`?skill=`, `?view=`, `?file=`, `?compare=`, `?render=`. They are documented in
|
|
the page footer and shared externally.
|
|
|
|
## Companion service
|
|
|
|
The vote API is a Go service on its own Kubernetes deploy cycle, reached by the
|
|
review desk over `window.SKILLS_REVIEW_VOTE_API`. Its source left this
|
|
repository on 2026-09-06; the deployed service is unchanged, and the review desk
|
|
still calls it. Keep the global, or replace it with a build-time
|
|
`PUBLIC_VOTE_API` env var — but if you do, update the service's own README in
|
|
the same change.
|
|
|
|
Its one-vote-per-IP assertion left `verify.mjs` with it. See
|
|
[`assertion-removals.md`](assertion-removals.md).
|