scroll-world
SkillAI & modelsBuild an immersive scroll-scrubbed "fly through the world" landing page for any industry or brand using Higgsfield. As the visitor scrolls, a pre-rendered camera flies from outside each scene into its interior, then flows on to the next scene with NO cuts, one continuous connected flight (Emons-style isometric diorama world, or any art direction you pick). The skill interviews the user for the topic, the story beats/sections, and brand kit, then generates cohesive scenes + seamless camera clips with Higgsfield and wires a portable, framework-agnostic scroll-scrub engine. Use when the user wants a "3D world" / "browse-through-the-industry" hero, a scroll cinematic, a diorama landing, or to turn a business into a scrollable world.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the scroll-world skill
What this skill tells your AI
The instructions your AI receives, as published by lev-os/agents in skills-db/design-ux/scroll-world/SKILL.md and read by ahel’s review.
Produces a landing page where scroll drives a camera: it dives from outside a scene into its interior, then flies out and into the next scene, continuously, with no visible cuts. The visuals are AI-generated (Higgsfield); the page just scrubs pre-rendered video by scroll position. This is the same technique behind Apple's scroll-through product pages — the camera genuinely moves, scroll only drives time.
What you generate: N scene stills → N "dive-in" camera clips → N-1 "connector" clips that join consecutive scenes seamlessly → a portable scrub engine that plays the whole chain as one flight.
The one rule that makes or breaks it: seams must be frame-identical. Read The seamless chain before generating any connector. Getting this wrong is the single most common failure and produces a visible "pop" between scenes.
Do not assume a frontend framework. The scrub engine in references/scrub-engine.js is
self-contained vanilla JS (it builds its own DOM + injects its own CSS into a container
you give it), so it drops into plain HTML, Next.js, Vue, a Python-served page, anything.
The value of this skill is the Higgsfield pipeline, the prompts, and the seam method —
not the framework.
Step 0 — Bootstrap
- Higgsfield CLI. If
higgsfieldis not on$PATH, install per thehiggsfield-generateskill. Ifhiggsfield workspace listfails auth, ask the user to runhiggsfield auth login(interactive OAuth — you cannot run it) and, if needed,higgsfield workspace set <id>. Confirm there are enough credits: a full run is roughlyNimage gens +(2N-1)video gens. - ffmpeg / ffprobe on
$PATH(frame extraction + encoding). - An image tool for background knockout if you want floating scenes: PIL
(
python3 -c "import PIL"), orcwebp/sips. Optional — see Step 3. - (Optional) Codex CLI — if
codexis on$PATH(≥ 0.125) andcodex login statusreports a ChatGPT login, the scene stills can be generated through Codex's built-inimage_gen(the same gpt-image-2 model) billed to the user's ChatGPT subscription instead of Higgsfield credits — offer it at Step 1.6, command in Step 2. Absence just removes the option. - Caveats: macOS ships bash 3.2 (no
declare -A); don't use associative arrays in scripts. Higgsfield generations take 3–8 min each — always run them detached (background) and poll, never a foreground blocking call. Reference-by-job-UUID is rejected by media flags — pass local file paths to--image/--start-image/--end-image. Video models differ in accepted params (e.g. Kling has no--resolution) and in whether they support start/end-image conditioning at all — before batching, confirm the chosen model's schema withhiggsfield model get <job_type>and see the Step 4 model table.
Step 1 — Interview the user
The subject is the user's to state — ask it as an open question in plain prose, never a
fabricated multiple-choice. A made-up list of industries biases them and reads as you
deciding their business for them; let them answer in their own words (their real business,
a client's, or any idea). Reserve structured multiple-choice (AskUserQuestion in Claude
Code; a plain either/or question elsewhere) for the genuinely
enumerable, lower-stakes choices below — art direction and brand-kit approach — and even
there, signal they can go their own way ("Other"). Ask only what you can't sensibly
default. Cover:
-
Subject (ask openly, not multiple-choice) — "What should this world be about? Your business, a client's, or any idea — a word or a sentence is fine." Capture the industry/product + a one-line pitch (e.g. "a bubble tea company, from leaf to last sip"), and a brand name if they have one; otherwise you'll propose one below.
-
Brand kit — offer three paths, pick one:
- Import from a URL:
higgsfield marketing-studio brand-kits fetch --url <site> --wait(pulls name, colours, tone). Then read it back withbrand-kits list --json. - The user hands you palette + name + tone directly.
- You propose a palette + name and let them approve. Capture 4–6 named hex values, a display name, and a tone word or two.
- Import from a URL:
-
Art direction — default is "soft matte low-poly clay diorama, isometric, tilt-shift miniature, warm light." Offer alternatives (flat papercraft, glossy toy, claymation, neon night). Whatever is chosen becomes the shared style preamble reused verbatim in every scene prompt (this is what makes the world cohesive).
-
The journey (sections) — the ordered scenes the camera flies through. Propose a set derived from the subject's own value chain and let the user edit. 5–7 works well. Boba example: farms → pearl kitchen → flagship shop → delivery → community plaza → the hero product. Each section needs: a short subject description (what's IN the diorama), an eyebrow, a headline, one line of body, and 0–3 tag pills. The last section is usually the hero product + the CTA.
-
Mobile version — ALWAYS ask this; never silently generate both. Ask as a two-option choice (
AskUserQuestionin Claude Code; a plain question elsewhere): "Want a mobile-optimized version too? The mobile version is a second camera chain rendered natively in 9:16 portrait — composed for phones, not a crop of the landscape film — which roughly doubles the Higgsfield credit spend (state the estimated number)." Options: "Desktop only" / "Desktop + mobile (native 9:16 — ~2× credits)". The credit cost must be stated to the user, not just implied. What the answer gates:- Yes → render the parallel 9:16 portrait chain and ship it as the mobile variants
(Step 6 / pipeline.md §6b): portrait start canvases → 9:16 dives + connectors
frame-locked against their own renders → 720-wide
-m.mp4encodes →stillMobileportrait posters. WireclipMobile/connectorsMobile/stillMobile(Step 7); run the full mobile QA (Step 8). Budget ~2N-1 extra video gens + NSFW re-rolls. Never ship the centre-crop as the mobile version by default — if credits can't cover the portrait chain, say so and offer the crop encodes (pipeline.md §6) as an explicitly-labelled stopgap the user must approve. - No → skip the mobile encodes and wiring entirely. The engine's phone hardening (seek-coalescing, iOS priming, safe-area CSS) is always on regardless — that's not a "mobile version," it's just the page not breaking when a phone visits — so a desktop-only build still degrades gracefully.
- Yes → render the parallel 9:16 portrait chain and ship it as the mobile variants
(Step 6 / pipeline.md §6b): portrait start canvases → 9:16 dives + connectors
frame-locked against their own renders → 720-wide
-
Budget — engines shown by cost, decided before anything renders. Present the render tiers (
AskUserQuestion), then compute and state the estimated total for the user's N scenes —N stills + (2N−1) videos [videos ×2 if mobile] + ~15% re-roll headroom— and get a go before generating.-
Video tier (roster only — every option frame-locks seams, Step 4):
Tier Model Rough cost Draft / previz seedance_2_0_mini(720p)~¼ of Standard Standard (default) seedance_2_0(1080p)baseline Alternate kling3_0(720p native)≈ Standard; different look + content filter Draft doubles as the previz path: run the whole chain cheap, approve the journey, re-render final legs on Standard (pipeline.md Notes) — suggest it unprompted when the balance reads tight.
-
Stills source (only offer if the Codex CLI is present, Step 0.4): Higgsfield
gpt_image_2(spends credits) vs Codeximage_gen— the same gpt-image-2 model billed to the ChatGPT subscription (zero credits; counts toward Codex usage limits; 1536×1024 output — exactly 3:2, slightly under Higgsfield's 2k). Stills are plain PNGs handed to--start-image, so the video chain is indifferent to their source. Command in Step 2. One source for all N stills of a build — the two render with slightly different character (verified: Codex runs warmer/lighter), and mixing sources across scenes reads as style drift, same reason the video chain uses one model. -
Calibrate costs, don't guess. The CLI exposes no pricing and plans differ. Run ONE still and ONE video first, diff
higgsfield workspace listbefore/ after, extrapolate to the full run, and warn the user whenever the estimate exceeds ~70% of the balance. (Observed on a plus plan, 2026-07: Standard video ≈ 40–55 credits, still ≈ 15.) A realnot_enough_creditsmid-run is recoverable (finished clips survive; resume after top-up) but ugly — the whole point of this step is that the user decides before the spend.
-
If the user names a video model outside the roster, honor it only if it can frame-lock seams (Step 4). This skill only ships seamless output, so a model that can't frame-lock is declined with a one-line why, not substituted in — use a roster model instead.
Keep the scroll mechanic fixed (continuous fly-through) — that's the point of the skill.
See references/prompts.md for the intake checklist and copy structure.
Step 2 — Generate the scene stills
One image per section, all sharing the same style preamble for cohesion. Default
model gpt_image_2 (crisp, great at isometric illustration; returns a solid/white
background which is perfect for floating diorama "islands"). Use nano_banana_2 only if
the brief is character/cartoon-heavy (note: nano_banana_2 is a CLI alias — it resolves
to nano_banana_pro; it won't appear under that name in higgsfield model list).
Prompt shape (full templates in references/prompts.md):
<STYLE PREAMBLE, identical every time>. On a plain solid <bg> background with a soft
contact shadow. <PALETTE hexes>. No text, no letters, no logos, centered, 3:2.
Subject: <what is in THIS diorama>.
-
Run all N concurrently, detached. Command per scene:
higgsfield generate create gpt_image_2 --prompt "$(cat scene_i.txt)" --aspect_ratio 3:2 --resolution 2k --quality high --wait --wait-timeout 15m --json > scene_i.json 2>scene_i.err -
Result URL is
.[]0.result_urlin the--wait --jsonoutput.curlit down. -
Codex stills variant (if chosen at Step 1.6 — subscription-billed, zero credits): same prompt files, same byte-identical preamble, generated by Codex's built-in
image_gen:codex exec -C "$WORK" -s workspace-write --skip-git-repo-check \ 'Use the image generation tool ($imagegen) to generate: '"$(cat "$WORK/still_i.txt")"' Wide 3:2 landscape, high resolution. Save it as ./still_i.png. Do not do anything else.'Single-quote the
$imagegensegment (the shell must not expand it); if editing with reference images, the prompt goes BEFORE any-iflag (it's variadic). ~1–3 min per image; run a few in parallel, not all N at once. Output lands at 1536×1024 (3:2) — fine for--start-imageand posters. Everything downstream (cohesion review, knockout, dives) is unchanged. -
A generation may fail transiently (HTTP 503) — re-roll that one individually; don't restart the batch.
-
Review the stills before continuing. They must read as one cohesive world (same angle, palette, light). If one is off-style, regenerate it, optionally passing an approved scene as
--imageto lock style.
See references/pipeline.md for the exact batch script.
Step 3 — (Optional) Float the scenes
If you want the dioramas to float over an atmospheric background instead of sitting in a
solid box, knock out the flat background to transparency with
references/knockout.py (border-connected flood fill — preserves interior colour that
matches the bg, e.g. cream walls). Then encode to webp. If you'd rather keep it simple,
just make the page background the same colour as the scene background and skip this.
These stills double as video posters and lazy-load fallbacks, so keep them.
Step 4 — Camera architecture (pick one — this makes or breaks the feel)
How the camera moves between scenes is the single biggest quality lever. Two shapes; pick by aesthetic.
Video model — pick ONE for the whole chain
This skill only ships seamless output, so the only usable models are ones that can
frame-lock a seam: every chained clip must accept --start-image, and connectors also
need --end-image. That capability — not preference — is the selection rule. Check any
model with higgsfield model get <job_type> and skip anything whose media inputs are
reference-only (no start/end image): it can only condition a generation, not
continue a shot, so it physically can't hold a seam. Schemas below were confirmed
against the CLI:
| Model | start/end image | Notes |
|---|---|---|
seedance_2_0 (default) | ✓ / ✓ | Full chain (legs + connectors). --mode std --resolution 1080p. Its NSFW filter is the touchy one (see Gotchas). |
kling3_0 | ✓ / ✓ | Full chain — tested: --mode std --sound off --duration 5 with start+end images accepted, seams frame-lock cleanly. No --resolution param (don't pass one; --mode std returns 720p native — encode what ffprobe reports, never upscale). Sound defaults on → --sound off. --duration default 5, try 10 for legs. Different content filter than Seedance — the sanctioned NSFW fallback. |
seedance_2_0_mini | ✓ / ✓ | Cheap draft tier that keeps frame-locking (720p). The previz tier: run the whole chain here first, then re-render final legs on the full model — still seamless, so it translates directly. |
Those three are the roster — all do both architectures. (kling3_0_turbo also frame-locks
via --start-image, but has no --end-image, so it's architecture-A-only and can't make
connectors; it also takes a different flag set — no --mode, has --resolution — so it
doesn't drop into the pipeline as-is. It's not in the default roster; only reach for it, and
wire it by hand, if architecture A's sequential render time is a proven bottleneck and you've
benchmarked it as actually faster.)
Rules:
- One model for all chained clips. Each renderer has its own motion/color/grain character; mixing models mid-chain keeps position continuity (frames still hand off) but the render-character shift reads as a subtle pop. The one sanctioned exception is the NSFW fallback for a single stubborn clip (Gotchas) — a slight character shift on one 5s connector beats a missing connector.
- Default to
seedance_2_0; honor a user's stated preference only if the model qualifies (frame-locking). If it doesn't, say so and use a supported model — never ship a non-seamless build to satisfy a model request. - The pipeline scripts take the model as
$VMODELwith per-model flags already cased out (references/pipeline.md).
A) Continuous forward take — RECOMMENDED for grounded / realistic / walkthrough
One camera that only ever glides forward, first scene through last, as a single take.
Generate the legs sequentially: leg 0 from scene-0's still (glide forward into it);
then each leg's --start-image = the previous leg's ACTUAL last frame (extract with
ffmpeg), prompt "continue gliding smoothly FORWARD into [scene i], never pulling back"
(or an expressive mid-leg move under the motion-handoff contract — see Camera grammar
below), and no --end-image — an end-image of a wide establishing shot forces the
camera to pull back, which is the #1 cause of stutter. Extract each leg's last frame to feed the
next. Result: every seam is frame-identical and the camera never reverses. There are
no connectors (skip Step 5) — the legs ARE the journey. Wire each leg as a section
clip with connectors: [] and a small crossfade (~0.08). Even without an --end-image
the legs still arrive at distinct rooms (the prompt steers the content). Cost: strictly
sequential (can't parallelize) and slower; interiors trip the NSFW filter, so build in
re-rolls (3 attempts/leg).
B) Dive-in + aerial connector — only for diorama / miniature / god's-eye worlds
A "dive into each scene" clip + a connector that pulls up and out and flies over to the next scene (Step 5). The pull-out reverses camera direction at every seam (forward dive → backward pull-out). In a miniature/diorama world that reads as an intentional "zoom out to the map, fly to the next island"; in a grounded first-person walkthrough it reads as a jarring rewind/stutter. Use B only for the map-like aesthetic. When in doubt, use A.
Camera grammar — the move should fit the concept (A is NOT "forward only")
"Forward only" is the seam rule, not the leg rule. The physics of the chain:
- Position continuity at a seam comes from the frame handoff (next leg starts from the previous leg's actual last frame).
- Velocity continuity at a seam means the camera must never reverse across a seam — that's the rewind stutter.
- Inside a single leg the camera is free. One leg is one continuous render — there is no seam to break mid-leg, so orbits, crane-ups, lateral tracking, even a push-in that eases back out are all safe within the clip. Reversals are only fatal across seams.
So give each leg an expressive move chosen from the scene's own logic, under a motion
handoff contract: every leg ends by settling into a slow, steady forward drift toward
the next destination (final ~1 s), and every leg begins by continuing that same drift.
Keep both clauses in the prompts verbatim (templates in references/prompts.md).
Pick the grammar from the concept:
| Concept / tone | Mid-leg move |
|---|---|
| Product / luxury retail | slow half-orbit around the hero object, then continue past it |
| Real estate / hospitality | steadicam glide through doorways; gentle crane-up in atria |
| Industrial / process / logistics | low lateral track alongside the line, foreground parallax |
| Travel / outdoors / campus | drone-style rise-and-reveal, then a descending swoop |
| Food / craft / detail-driven | push in close to the craft moment, ease back, carry on |
| Playful miniature (arch. B) | dives + aerial hops — the connector IS the grammar |
Honest costs: expressive mid-leg moves raise re-roll odds — the model can end a fancy move in a state that isn't a clean forward drift. Mitigations: keep the final-second settle clause verbatim; eyeball each leg's last frame before chaining the next (it should look like a frame from a gentle forward glide — if not, re-roll before wasting the next leg); budget ~1 extra re-roll per expressive leg. A plain forward glide stays the zero-risk default — use it for legs where the scene itself is the show.
Two related pacing knobs live in the engine (Step 7): per-section scroll (more scroll
distance = longer dwell in that scene) and linger (the camera settles mid-scene exactly
while the copy peaks, then picks up speed toward the seam). Prefer expressive motion in the
clip and restraint in the scrub mapping — they compound.
And remember scroll is a scrubber: visitors can scroll up, so every move also plays in reverse. That's free and expected — no extra work — but it's another reason seam velocity must be consistent in both directions (a seam that reads fine forward reads as a stutter backward too if velocity flips).
For B, one camera flight per scene: starts high/outside, descends into the interior,
structure opens. Model: the chain model you picked above (default seedance_2_0),
--start-image = the scene still.
- Use the solid-background still (not the knocked-out transparent one) as the start image, so the video has a full frame.
- Prompt: "Single continuous cinematic camera move, no cuts. Begin high and far looking
at the whole from outside … descend and fly inside toward … the
roof/walls gently open to reveal the interior. , smooth graceful slow motion.
No text." (Template in
references/prompts.md.) - Params (seedance):
--mode std --resolution 1080p --aspect_ratio 16:9 --duration 8. For Kling: drop--resolution(no such param), add--sound off,--duration 10. Do not pass--generate-audio(it errors on seedance; audio is wasted anyway — you'll mute). - Run concurrently, detached, then download each
.result_url. Re-roll individual failures. Keep the raw 1080p sources — you need their frames next.
Step 5 — Connectors (architecture B only)
Skip this whole step for architecture A — the forward take has no connectors; its legs already chain seamlessly. This step applies to B (diorama/miniature), and note the reversal caveat from Step 4.
The connector clips are what make the world feel connected instead of cut. A connector flies from the end of scene i out and into the start of scene i+1. Both of its endpoints must be the ACTUAL RENDERED FRAMES of the neighbouring clips — never the original diorama still.
Why: every Higgsfield generation renders slightly differently. If a connector ends on a fresh render of "the kitchen diorama," but the next dive clip starts on its own different render of that same diorama, the two won't match and you get a pop at the seam. The fix is to hand off the exact pixels:
For each connector between dive_i and dive_{i+1}:
start-image = the LAST frame extracted from dive_i's rendered video
end-image = the FIRST frame extracted from dive_{i+1}'s rendered video
Now every seam is frame-identical on both sides:
dive_i.end == connector.start and connector.end == dive_{i+1}.start.
Extract the boundary frames from the rendered dives (not the stills):
ffmpeg -sseof -0.15 -i dive_i.mp4 -frames:v 1 -q:v 2 dive_i_last.png # interior of i
ffmpeg -ss 0 -i dive_{i+1}.mp4 -frames:v 1 -q:v 2 dive_next_first.png # establishing of i+1
Generate the connector (--duration 5 is plenty). Connectors need --end-image, so the
model must accept it — any roster model does (seedance_2_0, seedance_2_0_mini,
kling3_0):
higgsfield generate create "$VMODEL" \
--prompt "$(cat connector_i.txt)" \
--start-image dive_i_last.png --end-image dive_next_first.png \
$VOPTS --aspect_ratio 16:9 --duration 5 --wait --json
# seedance: VOPTS="--mode std --resolution 1080p"; kling3_0: VOPTS="--mode std --sound off"
Connector prompt: "Single continuous camera move, no cuts. Pull up and back out of , rise into the sky, glide across the connected miniature world, and arrive above <scene i+1>, beginning to descend toward it. Seamless flowing aerial transition.
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 22
- Forks
- 2
- Last commit
- Sep 2026
ahel review
K6low
bundled executables the agent is told to run
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
scroll-world-lev-os- Source
- github.com/lev-os/agents