When you ask Claude Code to "make a 60-second horror reel", it will happily start writing components. Twenty minutes later you have a video that renders, moves and looks fine, and nobody watches past second three.
The problem is not the code. The problem is that the story decisions were never written down, so nothing could check them. The fix that worked for us is boring and very effective: the agent writes a timed spec first, then builds shots from it, then runs checks before anything is posted. This post walks through that structure so you can use it in your own short-form video projects, horror or not.
1. Why the spec comes before any code
Short vertical video is judged in the first few seconds. If the viewer doesn't know who, where and what is at stake almost immediately, they scroll. Those are story decisions, and they are easy to get wrong when they only live inside a component tree.
So the first thing Claude produces is a single JSON file that describes the whole episode. Code is generated from it later. Because the decisions are data, they can be linted.
A trimmed example (a new story, written for this post):
{
"title": "Floor 13",
"fps": 30,
"logline": "A night-shift guard sees the lift stop at a floor the building does not have, and it is calling him.",
"hook": { "line": "The lift just stopped at thirteen. We only have twelve floors.", "pattern": "impossible situation" },
"newcomer": { "who": "night guard", "where": "empty office tower, 3 AM", "stakes": "he is alone and the doors are opening", "lineAt": 3.2 },
"want": { "text": "keep the doors shut until the morning shift", "at": 6.5 },
"cliffhanger": { "type": "reveal", "line": "The panel shows a fourteen now. And it's lit." }
}
A few rules we lint on every spec:
- The hook lands in the first seconds. Frame 0 is already an event (doors opening, a light failing), never a slow establishing shot. The hook line has a named shape: impossible situation, status reversal, ticking clock, shocking reveal or payoff first.
- Who, where and stakes by about 5 seconds; the want by about 8. If the line that completes them starts later, the spec fails.
-
A question ladder. Every open question has an
opensandclosestime. A new question every 10 to 15 seconds, and never more than three open at once, otherwise the viewer gets lost instead of curious. - One cliffhanger type per episode, rotated. Threat, reveal, revelation, decision, clock. Repeating the same type two episodes in a row is flagged.
None of this needs AI to check. It is a small Node script that reads the JSON and prints PASS or FAIL per rule. Claude fixes the spec until it passes, then moves on.
2. Shots: every shot carries what the viewer sees and what they should understand
Next, the spec gets a shot list. Shots are continuous (each start equals the previous end) and each one has a beat: frame0, hook, want, escalation, scare, turn, reveal, cliffhanger, endcard.
The two fields that helped us most are sees and understands:
{
"id": "s05", "beat": "scare", "start": 14.0, "end": 18.0, "framing": "wide",
"sees": "The corridor lights go out one by one towards the camera; the last one stays on over the lift",
"understands": "Something is coming down the corridor, and the lift is the only lit thing left",
"camera": { "zoom": [1.0, 1.12], "drift": 0.4, "ease": "slowIn" },
"light": { "level": 0.8, "flicker": 0.25 },
"scare": { "kind": "approaching darkness", "at": 15.5 }
}
Writing understands forces you (and the agent) to say what the shot is for. If you can't fill it in, the shot is decoration and should go. Camera, light and events are plain numbers, so the render code stays dumb: it reads the shot and draws it. Changing the story never means hunting through components.
Two craft rules that live in the shot data:
-
Silence before a scare. Set an
endon the narration line before the scare so there is a real gap. The quiet does more than any sound effect. -
Rotate scare mechanisms. Each scare has a
kind. Two scares in one episode must use different mechanisms, and a mechanism used too often across a series gets flagged.
3. QA before anything is posted
Rendering a long vertical video takes a while, so we check cheaply first and expensively last.
- Spec lint (seconds): the timing and story rules above.
-
Blind read (a minute): render one still per shot. Someone (or a separate model session) who has not read the spec writes one line per still describing what is happening. Compare that with the
understandsfield. Any shot where the two don't match gets redrawn before the full render. Two rounds max; after that the shot is rethought, not polished. - Technical QA (after the render): 1080x1920, expected duration, audio present, captions in sync, no frame held static for more than about two seconds.
- Uniqueness check: the posted spec is copied into a history folder, and new episodes are compared against it, so the same hook pattern or cliffhanger type doesn't sneak back three episodes later.
- A separate reviewer scores hook and overall. The reviewer is never the session that wrote the script.
The point of the order is that the expensive mistakes (a story nobody follows) are caught when they cost seconds, not after a render.
4. How Claude Code fits in
We keep the method in a Claude Code skill: a SKILL.md that tells Claude the order (story, spec, lint, palette, staging, stills and blind read, voice-over, render, technical QA, uniqueness, review), plus reference files for the story rules, the spec format, camera and lighting, and QA. Claude reads the reference only when the step needs it, so the context stays small. You direct the story; Claude writes the code and runs the checks.
If you want to try the pattern without anything from us: start with one JSON spec, write five lint rules you care about, add sees/understands to every shot, and refuse to render until the spec passes. You'll feel the difference on the first episode.
Our version
We packaged the full method as the Animated Horror Reels Skill for Claude Code: SKILL.md and reference guides (story method, timed episode spec, camera, light and colour grade with a palette builder, QA and uniqueness checks) plus a render-ready TypeScript/React 1080x1920 starter project with caption timing and the check scripts. Skill Rs 1,499, one-time; the Complete Kit (Rs 4,599) adds video lessons, written guides, cheat sheets, an example project and a full demo episode project with its finished render. It needs Claude Code, Node.js and ffmpeg (Claude plan not included). Details: https://learn.homingo.co.in/skill
Disclosure: I'm with Homingo, this is our product.
Top comments (0)