teaser v8: a 58 s story instead of a feature list (the game is done; the stores pile up; one missing line; hand it to your AI; a montage of builds, screenshots, products, forms, consoles; the scan turns green; one button is yours; Waiting for review; the end card), one short line per scene, cuts on the 120 BPM beat; music rewritten for the arc (calm, tension, near silence, a driving build, a stop, a resolve), mastered with one gain instead of dynamic loudnorm; the pile shows real console plan, Data safety CSV and price sheet lines, the builds beat real apple / play build dry runs; desktop.ts captures submit-ready (Send for review before the press); tests check every line, the beat-aligned cuts and the caption times; two unused teaser icons dropped

This commit is contained in:
CRTkafa 2026-10-13 04:48:27 +08:00
parent d5ffc159c0
commit 0b6c8cd7a0
11 changed files with 1117 additions and 1041 deletions

View file

@ -1,76 +1,74 @@
# storebound teaser (62 s, 16:9)
# storebound teaser (v8, 58 s, 16:9)
A calm, scripted motion piece: from an empty folder to everything ready on both stores. 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.
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.
One idea per scene, 4-5 s each (whole half seconds, so every cut lands on a beat of the music), one camera move per
scene (a quick ease-out that settles before the cut), short dissolves on the cuts, no whips or rapid montages. Long terminal output streams faster rather than being cut. Each scene
has one plain-English caption at the top, fully on screen for at least 3 s; below it, the real product.
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 | caption |
|---|---|---|
| 0-4.5 | the demo game's icon, "Done"; the stores' to-do list line by line; one rejection mail (Guideline 2.1) | Your app is done. The stores are not. |
| 4.5-9 | an empty folder; `bunx storebound init` is typed; the files it creates list in | storebound takes it from an empty folder. |
| 9-14 | the prompt "Get my app ready for both stores."; `storebound release plan 1.0.0`: 26 steps in fix order | You ask once. It plans every step. |
| 14-19 | the demo game's store text in 4 languages; its renders in 7 store sizes x 4 languages | Store text and screenshots. Every language, every size. |
| 19-23.5 | `play products --dry` (174 regions), then `catalog diff` (175 / 174 region prices, 0 mismatches) | In-app products on both stores, priced in 175 countries. |
| 23.5-28.5 | the scan's declarations proposal: detected answers with file:line, one "ask owner" line highlighted; 768 Data safety answers | The forms, answered from your code. It asks what it can't know. |
| 28.5-33.5 | `storebound console plan apple-app-privacy`: steps, answer sheet, the never-press list and "Final button (the owner's): Publish" highlighted (40 steps, 92 answers); then the desktop app's console plan panel (App info) with that real plan, at the final button the owner keeps | No API? Your AI fills the console. It stops at Publish. |
| 33.5-38.5 | `storebound scan`: three findings, each with a plain reason; fixed, the re-scan is clean | It catches rejections before Apple does. |
| 38.5-43 | the desktop app's Portfolio: every app of three studios, App Store and Google Play per app, rollout %, crash-rate sparklines | Stop switching between two consoles. Every app, both stores, one window. |
| 43-47.5 | the Growth chart (visx) with the pointer sweeping across it, the crosshair and tooltip moving day by day; then the Health tab's crash rate, swept the same way | Installs, conversion and crashes, charted. |
| 47.5-52 | the Prices tab: products x key territories, both stores' prices per country, the gaps between them marked | Products and prices on both stores, side by side. |
| 52-57 | Releases › Send for review, back from App Review (UNRESOLVED_ISSUES): the rejected version item ("marked resolved when you resubmit"), build 52 picked, the pointer resting on Resubmit | Rejected? Fix it, resubmit in one click. |
| 57-62 | Submit for review: the plan panel with the dry run (nothing sent yet) and the pointer resting on "Continue" (it never clicks); then the card with the new submission "Waiting for review"; then the end card: storebound.dev, Open source · CLI · Desktop app | You press Submit. That's it. |
| 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 |
v6's "Both stores, one view. Ready for review." scene (release timeline, Store readiness) does not fit the 62 s; its
point lives on in the submit scene's dry run. The native confirm dialog that follows "Continue" is the system's
(macOS), outside the web view, so the video shows the app's own plan step before it and never draws a system dialog.
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` (callout and pointer targets, the hover sweeps) -> `out/desktop/`. The chart hovers are real: the mouse moves across the chart in small steps and a frame is taken for every day the tooltip shows; the video moves its pointer the same way and shows the day it has reached. The console plan panel gets the real `storebound console plan apple-app-privacy --json` of a fresh `storebound init` folder in place of the fixture's shortened plan; the send-for-review frames press "Read state", pick build 52 and open the plan panel as the owner would; the "Waiting for review" frame serves the fixture's apple status with the new submission waiting |
| `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 (D major, one chord per scene: pads, a soft pluck every half second, a quiet sub) and soft sound design: a bell and an airy swell on each scene change (each on a beat), key clicks, quiet ticks, chimes for the fixes and the submission |
| `render.ts` | frames at 60 fps blended to 30 fps -> ffmpeg (H.264 high, yuv420p), sound -> loudnorm (-16 LUFS, -1.5 dBTP), mux, poster, the 1280x720 web version |
| `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):
clock prefix and the "(0s)" timer left out), in a fresh `storebound init` folder with two products:
- `storebound init` in an empty temp folder.
- `storebound release plan 1.0.0`, `play products --dry` and `catalog diff` in that folder, with the stores answered by
`tests/helpers/teaser-store-mock.ts` (preloaded through a `bunfig.toml` in the folder, so the children `release plan`
starts use it too; nothing reaches the network): a brand-new app record with nothing on it for the plan and the dry
run, then the two products on both stores for the diff. Regions: the App Store's 175 storefronts, Google Play 174
(the count Play answered in a recorded read-only run).
- `storebound scan` of `tests/fixtures/scan/teaser` (findings, declarations proposal) and of `teaser-fixed` after the
fixes, and the Data safety answer count of `storebound check`.
- `storebound console plan apple-app-privacy` in the init folder (offline): the lines in order, the step and answer
counts of the pill, the never-press list and the owner's final button.
- `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 --dry` and `storebound play build --dry` in a minimal Capacitor project.
- `storebound play products --dry` and `catalog diff`, with the stores answered by
`tests/helpers/teaser-store-mock.ts` (preloaded through a `bunfig.toml` in the folder; nothing reaches the network).
- `storebound scan` of `tests/fixtures/scan/teaser` (the 5.1.1(v) finding, all five findings, the declarations
proposal) and of `teaser-fixed` after the fixes.
The plain reasons under the findings and the callouts on the desktop frames are annotations, set apart from the CLI
text. The store text is `examples/demo-game/store/shots/copy.json`, the screenshots its real renders, the app icon its
`store/icon/icon.png`. The mail row is fictional: no real names or addresses, no mail-app branding. The test also checks
the timing (scenes 4-5 s in whole half seconds, captions on screen at least 3 s, 60-65 s in total, 16:9 only, a chord
for every scene) and that every desktop frame a
scene names is one `desktop.ts` captures, and, where they were captured, that each file is there (2560x1600 JPEG, one
sweep frame per hovered day).
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 renders:
game's store captures and renders:
```sh
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,30.5,57.8 # PNG stills in out/stills for a quick layout check
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)
```