name: wiki-readme-slideshow description: Build a narrated, fullscreen-capable slideshow INSIDE a wiki page's readme.html - per-slide TTS audio, arrow-key navigation, auto-advance on audio end - without losing the markdown README (fold it in below the show). Born on the adom-theme page (2026-08-02, John's ask while driving). Trigger words - readme slideshow, narrated readme, slideshow in readme, audio tour, page tour, narrated tour, embeddable slideshow, readme with audio, slide deck on a wiki page.

A narrated slideshow inside readme.html

The live reference implementation is adom/adom-theme (readme.html + docs/slides/*.mp3). Read wiki-readme-html FIRST - every sandbox rule there applies. This skill adds the slideshow recipe on top.

The shape

  1. Slides are the page's existing images - reference them by absolute /blob/<type>/<slug>/... URLs (same-origin media loads fine in the sandbox; fetch does not). Do NOT re-encode images as base64; keep readme.html small.
  2. One TTS clip per slide - adom-tts say "<15-25s script>" --out slideN.mp3 (no --play; you are synthesizing files, not narrating). Push the mp3s to the page repo (e.g. docs/slides/) and reference them by /blob/... URLs in <audio>.
  3. The player - one <img> stage + caption + a control bar:
    • Play button toggles the narrated tour: sets audio.src per slide, audio.play().
    • audio.onended advances to the next slide while playing (auto-advance).
    • Back/Forward buttons + ArrowLeft/ArrowRight keydown, and dot navigation.
    • A Fullscreen button calling requestFullscreen() WITH a .catch(()=>{}) - see the sandbox caveat below.
  4. Keep the markdown: readme.html SHADOWS README.md on the page, so convert README.md to HTML (python3 -c "import markdown..." with tables,fenced_code) and append it below the show. Keep README.md in the repo for the Files tab and clone readers; every page-visible edit now goes through the readme.html rebuild.
  5. Height contract: fixed-pixel stage (NEVER vh - the resize feedback loop), plus the standard readme-height postMessage reporter from wiki-readme-html.

Sandbox truths that shape the design

  • In the page's iframe (sandbox="allow-scripts allow-downloads") there is no allow-fullscreen: requestFullscreen() rejects. The show still works embedded; catch the rejection silently. TRUE fullscreen happens on the raw endpoint: https://wiki.adom.inc/readme/<owner>/<type>/<slug>?variant=public is your file served top-level - no sandbox, fullscreen and audio both work. That URL is what you open in pup to present the show on the user's screen (window-maximize via desktop_set_window_state; valid states are maximize|minimize - there is no "fullscreen" state).
  • Audio needs a user gesture. Embedded: the visitor clicks Play. Presenting via pup: browser_click {selector:'#play'} is CDP input = a real gesture that unlocks audio (a pup browser_eval .click() is NOT trusted and audio stays blocked). Note the pup click can report "timed out" yet have landed - verify by screenshot (button state), not by the error.
  • No fetch, no popups, no wiki API - the show is display-only. All state in-page.

Publish checklist

  • readme.html at the publish-tree root AND listed in package.json files[], then pkg publish (the page renders the PUBLISHED layer) AND repo push readme.html + the mp3s (the /blob URLs serve the repo layer). Do both or you get a stale/half page.
  • Verify: curl the readme endpoint and md5-compare your bytes; open the page in pup (iframe mode renders, styles applied, height grows past the 600px fallback); trusted- click Play and confirm audio + auto-advance.
  • Narration etiquette: clips are page content, not adom-tts player traffic - do NOT also narrate the same content through the shared player at the same time; the two audio paths overlap on the user's speakers.