Skip to content

feat(media): hero streaming-demo assets generated from source (pnpm gen:media)#440

Merged
rejifald merged 14 commits into
mainfrom
worktree-streaming-demo-media
Jul 4, 2026
Merged

feat(media): hero streaming-demo assets generated from source (pnpm gen:media)#440
rejifald merged 14 commits into
mainfrom
worktree-streaming-demo-media

Conversation

@rejifald

@rejifald rejifald commented Jul 3, 2026

Copy link
Copy Markdown
Owner

What

Marketing campaign topic A0 — the hero demo for the README, Show HN, Product Hunt, and X. Ships the assets and the pipeline that regenerates them from source (pnpm gen:media):

asset size
docs/media/streaming-demo[-dark].mp4 — 1280×720, 30 fps, ~20 s loop 810 / 737 KB
docs/media/streaming-demo[-dark].webp — README embed via <picture> 770 / 744 KB (24-bit, no palette banding)
docs/media/streaming-demo[-dark].gif — for gif-only channels (PH gallery etc.) 2446 / 2486 KB (< 2.5 MB budget)
docs/media/streaming-demo-square[-dark].mp4 — 1:1 for social 849 / 763 KB

Nine feature chapters — one per core feature

One loop cycles every core feature, with a chapter-dot indicator: streaming-first, validation + drift (drift(User)), data shaping (unwrap: 'data'), resilience (retry/throttle/timeout), caching (cache: { ttl, scope } — MISS→HIT, derived keys), auth (bearer(env()) — capability, not credential), observability (trace: 'console', stitch trace), any request style (llm()/graphql/sse — one engine), and agent-native (stitch run/stitch mcprun_stitch). Every snippet is verified against README/core shapes and package JSDoc examples. The full ~45 s tour ships as mp4 + WebP; the GIF is a fixed 4-chapter marquee cut (via the scene's ?chapters= param) so it stays at full 1280 px quality under its 2.5 MB budget no matter how many chapters the tour gains.

The scene is a docs-site page, not a mockup

apps/docs/app/demo/streaming (noindexed) reuses CodePanel, Logo, BrandBackdrop, the Signal tokens and type stacks. Visit /demo/streaming on a dev server to watch it live (rAF-driven; static end-state under prefers-reduced-motion). Light/dark both work — the capture matrix records each via colorScheme emulation.

New design-system token

Success states needed a color the palette didn't have; rather than hard-coding a hex (forbidden by tokens.css), this adds a semantic --ok status token (light #15803d / dark #4ade80 + --ok-soft/--ok-line tints, exposed as bg-ok-soft/text-ok/border-ok-line). The "✓ …" badges and success rows use it.

Generated from source, not hand-recorded

Every frame is a pure function of time (window.__seek(t); ?capture freezes CSS animations and hides the Next dev indicator). The generator boots the docs dev server on a dedicated port (refusing to reuse an unknown server), frame-steps headless Chromium at 30 fps / 2× DPR, and assembles with ffmpeg; GIF encoding walks a quality ladder until it fits the budget.

Verified

  • All four chapters + both themes eyeballed from extracted frames; legible at 600 px
  • Loop seam: panels are blank-to-blank at the boundary (only the designed chapter-dot handoff differs); chapter out-fades complete a beat before the boundary
  • retry: { attempts, on }, throttle: { rate: '10/s' }, timeout, cache, drift(User), stitch run/stitch mcp all match README/core

Follow-up (separate PR): wire the GIF into the README hero via the <picture> snippet in docs/media/README.md.

🤖 Generated with Claude Code

rejifald and others added 8 commits July 3, 2026 18:54
…en:media)

docs/media/streaming-demo.{mp4,gif} + streaming-demo-square.mp4 are rendered
from a deterministic HTML scene (every frame is a pure function of time via
__seek(t)) by frame-stepping headless Chromium and assembling with ffmpeg —
no hand recording, fully reproducible. GIF is auto-stepped down until it fits
the < 2.5 MB budget (currently 285 KB at 1280px/15fps). The on-screen snippet
mirrors the real useStitchStream JSDoc example.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ponents

Replace the hand-built HTML scene with apps/docs/app/demo/streaming — a
real (noindexed) page reusing CodePanel, Logo, BrandBackdrop, and the
Signal tokens, so the capture always matches the live brand (fonts,
palette, amber ✓ chip instead of an off-system green). The generator now
boots the docs dev server on a dedicated port and frame-steps the page;
determinism is unchanged (render is a pure function of t, CSS animations
frozen and the Next dev indicator hidden in capture mode). Visitors get
the same scene self-running via rAF at /demo/streaming.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…token

The demo loop now cycles four chapters — streaming-first, validation +
drift, resilience, agent-native — each with real verified API usage
(retry/throttle/timeout/cache shapes, drift(User), stitch run/mcp front
doors) and a chapter-dot indicator. The '✓' badge and success rows use a
new --ok status token (light #15803d / dark #4ade80 + soft/line tints)
added to tokens.css/global.css instead of the amber accent. gen:media now
renders a theme × layout matrix: streaming-demo[-dark].{mp4,gif} +
streaming-demo-square[-dark].mp4, via Playwright colorScheme emulation.
Chapter out-fades land a beat before the boundary so the loop seam stays
clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
streaming-demo[-dark].webp (libwebp_anim, 15 fps, q70): 24-bit color with
no palette banding at ~770 KB vs the ~2.45 MB GIFs. GitHub renders
animated WebP, so the README <picture> snippet now uses it; the GIFs stay
for channels that only accept .gif uploads.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ements example

Also drops cache from the resilience snippet so each chapter owns one
feature (resilience = retry/throttle/timeout). GIF ladder stepped down to
12fps/128c as designed and both GIFs stay under the 2.5 MB budget.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… managed renewal

Agent chapter's third row becomes discovery/flat-context (code-mode) so
the capability message lives in one place. GIF ladder stepped to 1120px
(light) / 960px (dark).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Trace scene: per-stitch trace: 'console', STITCH_TRACE_FILE + stitch
trace summary rows, secrets-scrubbed-at-sink. The scene now accepts
?chapters=<keys> (refs re-keyed from index to chapter key), and the
generator captures GIFs from the 4-chapter marquee cut at full
1280px/15fps — GIF size is now constant as the tour grows, while
mp4/webp carry all 7 chapters (35.2 s).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ure has a scene

Full tour is now 9 chapters (45 s): streaming, drift, shaping (unwrap),
resilience, caching, auth, observability, request styles (llm/graphql/
sse — one engine), agent-native. Snippets mirror the llm() JSDoc and the
README hero's unwrap example. GIFs stay the fixed 4-chapter marquee cut.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@rejifald rejifald left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

review-sweep (re-review at 47c5b8b — supersedes the unposted payloads for 643664c and e70a8fa): 8 findings — 4 medium, 4 low; all in-diff, none security. Headlines: the hero snippet still wouldn't stream, the new caching chapter animates a cache HIT that the snippet (run verbatim) refuses to serve, and the branch now carries four generations of regenerable binaries (21 MB of blobs). A related pre-existing README issue (deprecated maxEntries in the Caching example) is filed separately. See inline comments.

Comment thread apps/docs/app/(home)/demo/scene.tsx
Comment thread apps/docs/app/(home)/demo/scene.tsx
Comment thread apps/docs/app/(home)/demo/scene.tsx
Comment thread docs/media/README.md
Comment thread scripts/gen-streaming-demo.mjs Outdated
Comment thread scripts/gen-demo.mjs
Comment thread scripts/gen-demo.mjs
Comment thread docs/media/README.md Outdated
rejifald and others added 6 commits July 3, 2026 22:51
seam() declares the cross-cutting config once (SeamConfig: base, auth,
throttle…); members inherit it via api.stitch() and share one runtime.
Full tour: 10 chapters, 50 s. GIF stays the fixed 4-chapter marquee cut.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…an tracked set, retina

Scene: chapter 1 now uses sse({ url }) (the surface that actually emits
delta chunks — mirrors integrations/react.mdx); caching chapter adds
cache.version so the snippet is honestly cacheable without a registered
fingerprinter (README announcements example gets the same fix).

Quality (the ghosting report): crossfades shortened to 0.22 s; GIF
re-encoded at 256 colors, dither=none, full-frame updates (measured both
cleaner AND smaller — 1729 KB vs 2434 KB); webp is now lossless (beats
q95 on this content); mp4 crf 14; new @2x retina exports (2560×1440).

Repo size: only the README-embedded @2x webp pair stays tracked —
mp4/gif/square variants are gitignored and regenerate via pnpm gen:media
(squash-merge recommended for this PR).

Pipeline: ffmpeg+libwebp preflight before the server boots; dev server
killed on the startup-timeout path; chromium launched inside try with
SIGINT/SIGTERM handlers; all encodes stage in a temp dir and publish to
docs/media only after every variant succeeds.

Drift gate: scripts/check-media-freshness.mjs (pnpm check:media-fresh,
lefthook pre-push) fails a branch that edits the scene/generator without
regenerating the committed pair; STITCH_MEDIA_STALE_OK=1 defers.
Reproducibility claim softened to visually-reproducible.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The loop covers ten features now, so 'streaming-demo' undersells it:
assets are demo*, the live page is /demo, the component is <DemoMedia />
(theme via the site's .dark class, 1x/@2x via srcset density). README
gets the theme+density <picture> after the badge block, linked to the
live tour; the homepage gets a 'See it run' Demo section after Problem.
copy-demo-media skips missing files (gen:media boots the dev server
before the assets exist on a fresh clone).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Proof before pitch: most visitors never reach viewport 4, and the demo's
closing chapter is the agent story, so it sets up 'Built for agents'
rather than upstaging it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The page was a fixed full-viewport overlay with no way out. It now lives
in the route group with the navbar, a heading, and a playground link;
the stage renders in-flow at its 1280×720 design size, scaled to the
page column (ScaledStage — no reflow, just zoom). ?capture=1 keeps the
exact-viewport opaque overlay, so the generator's pixel contract and the
committed assets are unchanged (verified against a 1280×720 capture
screenshot). Page is now indexable with a proper title/description;
export renamed StreamingScene→DemoScene.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rejifald rejifald merged commit 395090b into main Jul 4, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant