| .. | ||
| icons | ||
| desktop.ts | ||
| index.html | ||
| music.js | ||
| poster.jpg | ||
| README.md | ||
| render.ts | ||
| script.js | ||
| site-shots.ts | ||
| teaser.js | ||
storebound teaser (v8, 58 s, 16:9)
A short story, not a feature list: the game is done, the stores pile up work, one missing line sends you back to the
start, so you hand it all to your AI, it does the work, and one button stays yours. Little text (one short line per
scene at most, big and calm), real product footage only, and the music carries the arc: calm, tension, near silence,
a driving build, a stop, a resolve. Every frame is a pure function of time, rendered from an HTML/CSS/JS timeline in
headless Chrome and encoded with ffmpeg. The music and the sound design are original and synthesized from scratch in
the same browser (Web Audio OfflineAudioContext): no samples, no downloaded audio, nothing to license.
120 BPM: every cut lands on a beat (whole half seconds). The story scenes dissolve and drift slowly; the montage cuts hard on the beat with one quick push each.
| s | shows | text | music |
|---|---|---|---|
| 0-5 | the demo game's own screens (its store captures), floating, a slow drift | The game is done. | calm: a warm D major pad, a slow pluck |
| 5-11 | store work lands card after card, faster and faster: the App Privacy answer sheet and console steps, the Data safety CSV (768 rows), the screenshot sizes, the price sheet | Then come the stores. | tension: B minor, a growing low pulse, a ticking clock, a riser; a thud per card |
| 11-15 | one real scan finding (BLOCKER 5.1.1(v), at Planner/LoginView.swift:11) grows until it fills the frame; the picture goes dark | One missing line, and you start over. | a low boom, a dark drone sinking to nothing |
| 15-19 | in the dark, one request is typed to the AI agent: "Get this game ready for review on both stores." | So I handed it all to my AI. | near silence: room tone, key clicks, a swell into the drop |
| 19-23 | apple build --dry and play build --dry: build 52, versionCode 52 |
Builds. | the drop: kick, bass, arpeggio |
| 23-27 | the demo game's renders: 7 store sizes x 4 languages | Screenshots, every size. | + hats |
| 27-30.5 | play products --dry (174 regions), catalog diff (175 / 174 region prices, 0 mismatches) |
Products, 175 countries. | + claps |
| 30.5-34 | the scan's declarations proposal (one "ask owner" line), the Data safety rows filling, 768 answers | Forms. | + sixteenths |
| 34-37 | console plan apple-app-privacy, then the desktop app's plan panel with that real plan, at the owner's Publish |
Consoles. | + a brighter lead |
| 37-42 | storebound scan: five findings turn green one per beat, the re-scan is clean (0 blocker, 0 high) |
Nothing left for a reviewer to catch. | the drive peaks, a chime per fix |
| 42-48 | the desktop app's Releases › Send for review (build 52 picked); the camera settles on "Submit for review", the pointer rests on it | One button is yours. | the music stops; a quiet low pulse |
| 48-53 | the click; the same card shows the new submission "Waiting for review" (the app's own state) | (none) | the resolve: a wide D major chord, bells |
| 53-58 | the storebound mark (brand/logo-mark-256.png) | From an empty folder to Submit. · Open source · storebound.dev | the chord holds, fades |
The demo game has 4 languages (en, tr, ja, ar), so the screenshot beat says "every size", not a language count. The video shows no drawn system dialog and no mail: between the click and "Waiting for review" the real app shows its own dry-run plan and then the system's confirm dialog, which the story skips.
| file | what |
|---|---|
script.js |
the timeline: scenes in seconds, camera moves, captions, every line shown, the sound cues |
desktop.ts |
the desktop frames: apps/desktop's Vite dev server in fixture mode (VITE_FIXTURES=1, example.com-style data), captured headlessly in dark at 1280x800 @2x with the dev markers hidden, plus boxes.json (ring and pointer targets) -> out/desktop/. The console plan panel gets the real storebound console plan apple-app-privacy --json of a fresh storebound init folder; the send-for-review frames press "Read state" and pick build 52 as the owner would (submit-ready), and the "Waiting for review" frame serves the fixture's apple status with the new submission waiting. It also captures the frames the site uses (site-shots.ts) |
index.html + teaser.js |
the picture; window.teaser.seek(t) sets every element for time t |
music.js |
music and sound design, one section per part of the arc (see the table) |
render.ts |
frames at 60 fps blended to 30 fps -> ffmpeg (H.264 high, yuv420p); sound: one gain to about -16 LUFS with the true peak at or below -1.5 dBTP (no dynamic normalization, so the quiet parts stay quiet), mux, poster, the 1280x720 web version |
icons/ |
the mouse cursor and the UI icons: Phosphor files copied unchanged by bun tools/site-icons.ts (no hand-written SVG; CI checks it) |
Every CLI line in the video is real output, and tests/teaser.test.ts runs each command and checks every line (the
clock prefix and the "(0s)" timer left out), in a fresh storebound init folder with two products:
storebound console plan apple-app-privacy(offline): the answer sheet and step lines of the pile, the plan lines of the consoles beat, the never-press list and the owner's final button.storebound play data-safety --dry(the CSV lines),storebound check(768 rows),storebound prices ppp --offline --dry(the price rows).storebound apple build --dryandstorebound play build --dryin a minimal Capacitor project.storebound play products --dryandcatalog diff, with the stores answered bytests/helpers/teaser-store-mock.ts(preloaded through abunfig.tomlin the folder; nothing reaches the network).storebound scanoftests/fixtures/scan/teaser(the 5.1.1(v) finding, all five findings, the declarations proposal) and ofteaser-fixedafter the fixes.
The test also checks the timing (every cut on a half-second beat, scenes 3-6 s, the montage at 19-37 s speeding up with
cuts rather than dissolves, captions of at most 8 words fully on screen at least 2.5 s inside their scene, 56-62 s in
total, 16:9 only), that the game screens and screenshot tiles are the demo game's own, and that every desktop frame a
scene names is one desktop.ts captures (where they were captured: each file there, 2560x1600 JPEG).
Render
Needs Bun, ffmpeg, Playwright (repo devDependency; Playwright's Chromium or an installed Google Chrome) and the demo game's store captures and renders:
cd examples/demo-game && bun serve.ts & bun ../../cli/index.ts shots capture && bun ../../cli/index.ts shots fonts && bun ../../cli/index.ts shots render
# from the repo root
bun media/teaser/render.ts > media/teaser/out/render.log 2>&1 & # master, sound, poster, web version: about 20 min
bun media/teaser/render.ts --desktop # capture the desktop app frames again (after a UI change)
bun media/teaser/render.ts --stills 2.5,13.5,46 # PNG stills in out/stills for a quick layout check
bun media/teaser/render.ts --sound # the music only (out/music.wav)
bun media/teaser/render.ts --serve --port 8750 # live preview: /index.html?play=1 (or ?t=12.5)
Outputs (gitignored) in media/teaser/out/: teaser-1920x1080.mp4 (master), teaser-web.mp4 (1280x720, about
6.7 MB) with poster-web.jpg, teaser-1920x1080-silent.mp4, poster-1920x1080.jpg, music.wav.