← Corpus / lossless-monorepo / prompt
Port Astro Deck Sections to Slides
Decision rules and the wrapper-import warning for taking working Astro scroll-deck sections and producing fixed-aspect 16:9 slide files that play left-to-right like Keynote/PPT — without leaking adaptations back into the scroll deck. The two are different artifacts; treating them as one is the trap we keep falling into.
- Path
- prompts/Port-Astro-Deck-Sections-to-Slides.md
- Authors
- Michael Staton
- Augmented with
- Claude Code on Claude Opus 4.7
- Tags
- Scroll-to-Slide-Adaptation · Slide-Tier · Slide-Canvas · Keynote-Style-Playback · Fixed-Aspect-16-9 · Wrapper-Trap-Documented · Copy-Paste-Adaptation · Section-by-Section-Workflow · Decision-Rules · Astro-Sections · Deck-Iteration-Workflow
Note to Agents:
We have a working scroll deck (calmstorm-decks: /thesis, /thesis/version-2, /thesis/version-3) where each “slide” is an Astro section component composed into a single scrolling page. The scroll-deck approach is intentional and valuable — agents reasoning about a whole-deck narrative produce more coherent design than agents reasoning slide-by-slide. That motion is documented in the existing deck-iteration-workflow skill at ~/.claude/skills/deck-iteration-workflow/SKILL.md.
The motion this prompt covers: taking those scroll-deck sections and producing independent, fixed-aspect 16:9 slide files that play left/right like Keynote/PPT, without changing the existing scroll-deck sections and as a new tier alongside the existing wireframe variants on the /{slug} chooser pages.
Core constraint we keep getting wrong: the act of “porting” a scroll-deck section to a slide is not a wrapper around the original. It’s a copy/paste adaptation into a new file that lives independently and can be tuned for the 16:9 canvas without leaking edits back into the scroll deck. We have learned this the hard way. If a future agent thinks “I’ll just import the existing section into a SlideCanvas wrapper,” that agent is about to repeat a mistake we’ve made and noticed.
Why scroll → slide is genuinely hard (the lived experience)
When you design a scroll deck end-to-end you get visual coherence for free — the agent reasons about the whole arc, every section knows it’s in conversation with the others, color and rhythm and density harmonize because one mind held the whole thing at once.
When you split that into individual slides played left-to-right at a fixed aspect ratio:
- Some sections fit the canvas naturally. The cover, the vision/mission slide, the simple stat slides — these were always single-screen-ish in design intent.
- Some sections don’t fit at all. Sections written with multiple stat panels, dense person grids, or tall text columns assume vertical breathing room that a fixed 16:9 box doesn’t have.
- Some sections fit but lose rhythm — they were authored with the section above and below in mind. Played alone in a fullscreen canvas, the framing reads weird.
- You can’t tell which is which from a
curlresponse. Visual inspection in the browser at fullscreen is the only honest measurement. This is why the workflow is iterative: generate, inspect, fix, move on.
Knowing when to do this adaptation work is part of the value of having a skill at all. Don’t trigger it during initial design. Don’t trigger it before the scroll deck feels done. Trigger it when there’s a real need to play the deck Keynote-style or export to PPT/Reveal/PDF for an audience that expects fixed-aspect playback.
Naming convention: not yet final, evolving
Where adapted slide files live:
src/slides/by-title/{NN}-{slug}-v{N}.astro
NNis the slide number (01through17), zero-padded for filesystem sort.slugis the kebab-case slug fromsrc/lib/slides.ts(lowercase only —investment-team-lpacnotinvestment-team-LPAC, even though the registry keeps the latter for display).v{N}is the variant — currentlyv1/v2/v3mapping to which scroll-deck source inspired it (teaser / teaser-v2 / teaser-v3). This may evolve as new variants are generated independently of the scroll decks.
The folder choice is src/slides/, not src/layouts/slides/ or src/components/slides/. Astro treats anything outside src/pages/ and src/content/ identically — the folder name signals semantics for humans, not Astro. slides/ says “these are slide files.” by-title/ leaves room for future organization axes (by-theme/, by-audience/, by-stage/) as the deck-builder shopping experience matures.
Open question, not yet answered: there is also a “theme” axis lurking. The scroll decks v1/v2/v3 each have a coherent visual treatment because they were designed in one go (warm/light, dark/inverted, magazine-editorial respectively). When new variants are generated outside that initial coherence, tracking which theme they belong to gets harder. The naming may eventually need a theme tag (e.g. 01-disclaimer-confidential-warm-v1.astro, 01-disclaimer-confidential-magazine-v2.astro). Flagging for later — go with what feels natural for now.
The workflow (section-by-section, iterative)
Do one section title at a time. For each section, produce 3 adaptations (one per scroll-deck variant), have the user inspect them in the player, get feedback, iterate. Do not speculatively generate all 17 × 3 = 51 files in a single pass — you cannot tell from a curl whether they look right, the user has to see each one, and bulk-generating without inspection burns iterations.
For each section:
- Read the three source files in
src/layouts/sections/teaser/,teaser-v2/,teaser-v3/. - Copy the content into three new files at
src/slides/by-title/{NN}-{slug}-v{1,2,3}.astro. - Wrap each in
SlideCanvas(the canvas component handles the 16:9 aspect ratio + scale-to-fit transform). - Adapt the styles for the 16:9 canvas: smaller fonts, tighter spacing, restructured layout where needed. Be conservative on the first pass — the user is going to tell you which ones need more aggressive adaptation.
- Tell the user which section is ready for inspection. Provide the link to the per-section player.
- Wait for feedback. Statuses to expect:
urgent-redo,non-urgent-could-be-better,passable,perfect. - Move to the next section based on user direction.
What you must NOT do:
- Edit any file under
src/layouts/sections/teaser{,-v2,-v3}/. Those are scroll-deck source. Untouchable. - Generate all 17 sections in one pass without user inspection.
- Treat the new slide files as wrappers that import the originals. They are independent copies. Per-slide adaptations live in the slide file itself.
The infrastructure (already built, don’t redo)
The first iteration produced these pieces. They’re correct and stay; only the slide files themselves change.
src/components/slides/SlideCanvas.astro— the fixed-aspect 16:9 wrapper. Design size 1920×1080 by default, scale-to-fit container via JS ResizeObserver. Force-resolves[data-reveal]animations and resets.slideheight inside the canvas.src/pages/play/index.astro— the keyboard-driven player. Cross-fades between slides viaaria-hiddentoggling. Bindings: ←/→/Space navigate, F fullscreen, C toggle chrome, Esc exits fullscreen. URL hash updates so/play#7jumps to slide 7.src/pages/index.astro— the deck index has a ”▶ Play (next-gen slide tier)” tile linking to/play.
What still needs to be built once the per-section workflow takes shape:
src/pages/play/section/[slot]/index.astro— dynamic route that walks just one section’s 3 variants. So/play/section/01plays slides 01-v1 → 01-v2 → 01-v3. This is what the per-section inspection workflow points at.src/pages/data-assets/slides.astro— audit surface listing all 17 sections, each with a “Play 3 variants” link and a status pill (urgent-redo/non-urgent-could-be-better/passable/perfect). Same shape as the existing/data-assets/companiesand/data-assets/peoplepages. Status persistence TBD — could be a sibling status registry file, or a top-of-file frontmatter comment in each slide.- A way to declare which variant is preferred per slot. Once a section is reviewed and one variant is “perfect,” the player should walk that variant for that slot. Implementation candidates: a
src/decks/canonical.tsregistry, or a “canonical” symlink/copy convention.
What we got wrong in the first iteration (preserved as a warning)
The first attempt at this prompt produced 51 wrapper files at src/slides/by-title/{NN}-{slug}-v{1,2,3}.astro that imported the corresponding scroll-deck section directly:
---
import SlideCanvas from "../../components/slides/SlideCanvas.astro";
import Section from "../../layouts/sections/teaser/T01-DisclaimerCover.astro";
---
<SlideCanvas><Section /></SlideCanvas>
This LOOKS clever — minimal duplication, single source of truth. But it’s wrong because:
- Per-slide adaptations leak. Any CSS tweak you add to make the slide fit the canvas modifies the rendering of the imported section, which renders inside the scroll deck too. You can’t constrain to “only when in slide mode” without flag-passing through the section, which defeats the simplicity.
- The slide file doesn’t have its own DNA. The file is just an import statement; you can’t quickly read what’s on the slide without opening the source section. This becomes painful when a human is “shopping through 100 slides” picking 12 for a meeting — they want to scan the slide files themselves.
- It conflates source and presentation. The scroll-deck section is the agent’s coherent design moment. The slide file is the presentation moment. Different concerns; should be different files.
The fix: replace each wrapper with a copy/paste of the source section’s content, then adapt the copy for the canvas. The wrappers can be bulk-deleted once the copies exist.
Worked example: T01 (Disclaimer / Confidential)
The first section to actually adapt this way. Three source files exist:
src/layouts/sections/teaser/T01-DisclaimerCover.astro(warm/light, full-bleed cover)src/layouts/sections/teaser-v2/T01-DisclaimerCover.astro(dark/inverted, vertical wordmark on the left)src/layouts/sections/teaser-v3/T01-DisclaimerCover.astro(magazine-editorial, with plate marks top/bottom and 2-column justified disclaimer)
The pilot produces:
src/slides/by-title/01-disclaimer-confidential-v1.astro— adaptation of the warm cover for 16:9src/slides/by-title/01-disclaimer-confidential-v2.astro— adaptation of the dark cover (already mostly fixed-height in design, since the v2 wordmark is rotated and the body is a fixed grid; should adapt cleanly)src/slides/by-title/01-disclaimer-confidential-v3.astro— adaptation of the magazine cover (already authored against absolute-positioned plate marks; should adapt cleanly)
Probable adaptation needs per variant for T01 specifically:
- v1: the disclaimer text at the bottom is 0.65rem and may need to shrink or wrap differently inside the canvas. The hero wordmark uses
clamp()which the canvas’s transform handles — should rescale fine. - v2: the rotated wordmark on the left edge fits only because the section assumes
height: 100vhwith a fixed grid. Inside the canvas, height becomes the canvas height (fine) and the rotation still works. - v3: the plate marks are
position: absolutewith explicittop/bottom. Inside the canvas they’ll position relative to the canvas, which is what we want. The 2-column disclaimer at the bottom usesposition: absolute; bottom: 3rem— should work.
After producing T01 v1/v2/v3, expect the user to play /play/section/01 and report which of the three variants is perfect / passable / etc.
See also
~/.claude/skills/deck-iteration-workflow/SKILL.md— the original forward-arc skill that builds the scroll deck. This prompt picks up after that motion, when scroll mode is “done” and a slide tier is needed.sites/calmstorm-decks/src/components/slides/SlideCanvas.astro— the canvas primitive. Read this before adapting any slide.sites/calmstorm-decks/src/pages/play/index.astro— the player. Currently hardcoded to walk v1 of each slot; per-section route is the natural next.sites/calmstorm-decks/scripts/export-decks.ts— the existing exporter. Once enough slides areperfect, the slide tier can have its own exporter that’s much simpler than the scroll-deck DOM-walker (just iterate the slide files at native 1920×1080 and screenshot).sites/calmstorm-decks/context-v/changelogs/2026-05-07_01.md— the export-pipeline changelog where Path 3 (“strict 16:9 canvas baked in from day one”) is the architectural precondition this work operationalizes.sites/calmstorm-decks/src/pages/data-assets/{companies,people}.astro— pattern for the slides-audit page when it gets built.