The site is the story
A launch film built from the live product. GroundSlate records the real pages scrolling, on desktop and on a phone, with cookie banners refused during capture, and your agent cuts them into a narrated film. No mockups, no recreations, and nobody has to sit and screen record.
Use /groundslate-site-film on <<YOUR PRODUCT URL>>. The story is <<WHAT LAUNCHED OR CHANGED>>. It is for <<WHO WATCHES IT>>, and it should run about <<LENGTH>>. Bring me a cut.
Works with
- Your agent's own skills
- Research, analysis and writing. GroundSlate renders web pages itself now, capture_page for stills and record_page for footage, so the pictures come from the app; the reading, the judgement and any account that needs a sign-in still arrive through your agent.
- Claude Design, or any design tool that outputs HTML
- Designs the page and holds the brand. GroundSlate renders the page to video and can keep it as a named kit. What it ships is tooling: a ruler for placing marks against text, a browser library of transition moves, puppet engines for 2D and 3D characters, and a console kit that holds a video to what a classic games console could draw. It stores no brand and designs nothing itself.
- ElevenLabs, or any voice or music model
- Generates the audio, outside GroundSlate. Your agent generates it through its own connection to the provider, an MCP server or an API key, and hands the file back. It stores the voice id against a character and mixes, ducks and lays whatever your agent brings back. Most work needs no provider at all: GroundSlate speaks scripts locally in a designed or stock voice, and writes instrumental beds and sound effects locally too. A provider is for a specific voice you own, or a catalogue track you want by name.
Most product films never show the product. They show a mockup floating at an angle over a gradient, because real footage of a website meant booking someone to screen record it and then cutting around their cursor.
GroundSlate records pages itself: WebKit on the Mac, desktop or a true phone viewport, the whole page scrolling as video, with the cookie banner refused before the first frame. So the film shows the real thing: your type, your photography, your interface, moving. This skill has your agent produce that film.
The site needs to be reachable without a login. If the good part is behind a sign in, say so in the ask, and the skill will open a window for you to log in once.
Install it
Copy or download SKILL.md above.
For Claude Code, save it as ~/.claude/skills/groundslate-site-film/SKILL.md.
For claude.ai and the Claude desktop app, put it in a folder named groundslate-site-film, zip the folder, and upload it under Settings, Capabilities, Skills.
The skill
---
name: groundslate-site-film
description: Build a launch or product film out of the live site itself. GroundSlate records the real pages with capture_page and record_page, in desktop and phone viewports, with consent banners refused at capture, and the agent cuts them into a narrated film with ducked music. Use when somebody wants a product launch video, a feature reveal, a site tour or a release film and the product is on the web.
---
# The site is the footage
The product is the footage. Everything else supports it. Your job is to
capture the real thing well, then cut it with an argument.
## Permission comes first, and you cannot grant it
Web capture is off until the human turns it on, and then answers to their site
policy. Do this before you promise a film.
- `browser_policy` reads the current state: enabled or not, the mode, and the
lists.
- `request_browser_site` ASKS for a host, with your reason, and the human
decides in GroundSlate. Asking twice increments a counter rather than
creating a second request, so ask once and say what you need.
- If the policy is a LIST, third party frames on the page are refused too, and
most of a commercial page's furniture is third party. The result says so.
RELAY THAT. A capture shown as "the page" when a third of it did not load is
a misrepresentation, and only the human can widen the policy.
- A capture that redirects somewhere the policy does not permit is discarded
rather than returned.
## Capture the site properly
- `capture_page` for stills. `device` is desktop (1440x900) or mobile
(390x844 with a phone user agent, so the site serves its real mobile layout
rather than a squeezed desktop one). `full_page` for the whole scroll,
`scale` for retina.
- `record_page` is video. `scroll=True` walks the page top to bottom across
the recording, and that is what turns a static site into footage.
- Record at 24fps. A scrolling page repaints continuously and holds about 7
percent of its frames at 24 against 16 to 26 percent at 30, measured. More
frames is not more motion here, it is more duplicates.
- `consent="reject"` refuses the cookie banner at capture time so it is never
in your plate. There is no accept option and you should not want one.
- For a 9:16 cut use `device="mobile", width=360, height=640, scale=3`. That
is a true phone viewport upscaled, not a desktop page squeezed.
- Behind a login: `open_browser_window` with a `reason` written for the human,
they sign in, and then `session="shared"` on the capture sees it. Nothing
here solves a challenge for you and nothing should try. `close_browser_window`
when you are done, or it closes itself after thirty minutes.
Capture more than you need, in both form factors, and capture the flows rather
than only the landing page. Pricing, the app itself, the docs, the empty
state, the thing the release actually changed.
## Shoot list before capture list
A page scrolling is not automatically interesting. Decide what each capture is
FOR before you take it.
- The hero: the page as the subject, full frame, sharp, moving.
- The detail: a crop magnified out of the page with the rest ghosted, so a
small piece of interface becomes readable at a distance.
- The comparison: before and after, or two states side by side, where the
difference is the point.
- The scale shot: many captures at once, a grid, where the repetition is the
argument.
- The device: a capture held in a frame, angled, moving, when the fact that it
is a phone matters.
- The cutout: `remove_background` lifts a subject off a still on device and
writes a transparent PNG at source resolution with the subject in place, so
it drops back over the original as a layer. Check `foreground_fraction`,
because near 1.0 means nothing came off.
A blurred page behind a headline is the weakest use of a capture and it is the
one everybody defaults to. Spend the vocabulary.
## Cut it as an argument, not a tour
- Open on the change, not on the logo. What is different, in one line.
- One statement per scene, set large. The narration carries everything else.
- Show, then say. The capture lands, then the line about it, not the reverse.
- The demo is a sequence of decisions, not a scroll. If a capture runs longer
than the point it is making, cut it.
- Close on what to do next, and make it specific.
## The scene rules
- Small type is only ever verbatim evidence, a URL, a label, a line of code.
A sentence set small is the narration leaking onto the picture.
- Motion is how a thing arrives and leaves, not a state it lives in.
- The layout is fixed from t=0. Nothing on screen moves because something new
arrived.
- Composition varies between scenes, never inside one.
- The captured page is the layer that moves. The type over it holds still.
## Everything happens inside GroundSlate
- `write_composition` writes an authored page where the renderers can open it.
Never reach outside the framework for a filesystem bridge.
- `render_html` bakes a page. `render_sequence` assembles N clips with N-1
seams in one call, encoding every frame once. `author_film` expresses
scenes and seams as one composition.
- `mix_audio` IS the ducking: voice plus music in, `ffmpeg_argv` out, bake it
with `render_ffmpeg`. Its `threshold` is a linear amplitude, not decibels.
- `list_transitions` and `transition_motion` for the moves. Choose on the
measured `seam_seconds`.
- `reframe_vertical` or `make_reframe` when the same film has to ship 9:16,
but prefer recapturing in a phone viewport, which is a real mobile layout
rather than a crop of a desktop one.
## Timing is frames
- A transition overlaps its two shots and never adds time:
`sum(clip frames) - sum(seam frames)`.
- Declare durations that land on whole frames at your fps.
- Freeze scene durations before you place a single audio cue, or you will
re-derive every cue downstream by hand.
- Verify frame counts with ffprobe on the delivered file, not from the job
record.
- A recorded page is not always constant frame rate. Normalise it explicitly
before it enters the cut, or a later step drops frames without saying so.
- One pixel format and one colour range across the whole film. A single full
range clip among limited range ones is a visible black level jump.
## Motion has a floor
- A drift under about 0.3 px per frame emits identical frames. Clear 8 px per
second on a ground you can actually see.
- A scrolling capture under a still headline is the trap this format invites.
If you paused the capture, would the scene still be moving? Measure the type
and graphic layers separately from the footage.
## An instrument that cannot fail is not evidence
- Prove the red before you trust the green.
- Look at every capture before you cut it. A page can render with a missing
font, a blank third party frame, an interstitial or a consent wall, and the
file will still be a valid mp4 of exactly the right length.
- Never present a capture as the page when part of it did not load. Say what
was refused.
## The project is the source of truth
A DIFFERENT agent, tomorrow, with only the profile and the project id, must be
able to continue this. If they cannot, it failed.
- `create_project` early, hold the `prj_` id, bind everything.
- Captures are media: bind them, and record which page and which viewport each
one came from. A folder of screenshots nobody can attribute is not an asset
library.
- `write_project_file` for the shoot list, the script, the cue tables and the
note map from each review round.
- `add_project_note` for a decision and its reason.
- `commit_to_library` the finals with the project.
- The site will change. Record the capture date beside every asset, because a
re-cut in three months is against a different site.
## Show them, every round
- End every round with `request_review(source, ask, agent=, profile=)`.
ALWAYS pass an `ask`, or it is a show: it accepts notes and offers no way to
submit them. ALWAYS pass `agent=`.
- Read `placed` back and say what it says: `opened`, `waiting` (running, not
frontmost, Dock bouncing), `saved` (app shut).
- `review_status` for the notes and their anchors. Work from the anchor.
- `withdraw_review` for a superseded question of your own.
- Report per note: DONE, NOT DONE or PARTIAL, with evidence.
## Report like a producer
- Keep working while captures and renders run.
- Say which hosts were allowed, which were refused, and what that cost the
picture.
- End with where the film is, what it is called, and the date the site was
captured.