4,100 launch videos measured shot by shot. Search references, pull blueprints, plan your film.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Bearer refs_… key from https://refs.video/account (the MCP comes with Pro)
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
After rendering a video from a reference, check it against that film's measured timeline and get concrete fixes: cut timing to the frame, pace, brightness curve, motion per shot, loudness for the platform, and format. First measure your render: run `node scripts/measure.mjs <file>` from the Refs starter kit (curl -sL https://refs.video/starter.zip -o refs-starter.zip && unzip refs-starter.zip; it unpacks to refs-starter/) and pass the JSON it prints as `render`. Returns a score out of 100, a table of checks and a numbered fix list (frames at your render's frame rate), then the same as JSON. Costs 2 credits, so fix, re-measure and check again.
The reference you built from: REF-0005, a refs.video/v/… link, a YouTube/X link, or an id from search_videos
The JSON printed by `node scripts/measure.mjs <your video>`, as an object (or that JSON as text)
Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution."
The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess.
Where it will be posted; sets the loudness target: x and youtube −14 LUFS, tiktok −14 to −10, web −16, true peak ≤ −1 dBTP. Default: the reference's platform
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
After rendering a video from a reference, check it against that film's measured timeline and get concrete fixes: cut timing to the frame, pace, brightness curve, motion per shot, loudness for the platform, and format. First measure your render: run `node scripts/measure.mjs <file>` from the Refs starter kit (curl -sL https://refs.video/starter.zip -o refs-starter.zip && unzip refs-starter.zip; it unpacks to refs-starter/) and pass the JSON it prints as `render`. Returns a score out of 100, a table of checks and a numbered fix list (frames at your render's frame rate), then the same as JSON. Costs 2 credits, so fix, re-measure and check again.
| Argument | Type | Description |
|---|---|---|
| id* | string | The reference you built from: REF-0005, a refs.video/v/… link, a YouTube/X link, or an id from search_videos |
| render* | any | The JSON printed by `node scripts/measure.mjs <your video>`, as an object (or that JSON as text) |
| target | string | Where it will be posted; sets the loudness target: x and youtube −14 LUFS, tiktok −14 to −10, web −16, true peak ≤ −1 dBTP. Default: the reference's platform |
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"render",
"context",
"llm_model"
],
"properties": {
"id": {
"type": "string",
"description": "The reference you built from: REF-0005, a refs.video/v/… link, a YouTube/X link, or an id from search_videos"
},
"render": {
"anyOf": [
{
"type": "object",
"required": [
"kind",
"version",
"duration_s",
"fps",
"width",
"height",
"cuts",
"luma",
"motion",
"audio"
],
"properties": {
"fps": {
"type": "number",
"maximum": 1000,
"exclusiveMinimum": 0
},
"cuts": {
"type": "array",
"items": {
"type": "object",
"required": [
"t",
"frame",
"score"
],
"properties": {
"t": {
"type": "number",
"minimum": 0
},
"frame": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
"score": {
"type": "number"
}
}
}
},
"file": {
"type": "string"
},
"kind": {
"type": "string",
"const": "refs-render-measure"
},
"luma": {
"type": "object",
"required": [
"step_s",
"mean",
"p95"
],
"properties": {
"p95": {
"type": "array",
"items": {
"type": "number"
}
},
"mean": {
"type": "array",
"items": {
"type": "number"
}
},
"step_s": {
"type": "number",
"exclusiveMinimum": 0
}
}
},
"audio": {
"type": "object",
"required": [
"has_audio",
"integrated_lufs",
"true_peak_dbtp",
"range_lu"
],
"properties": {
"range_lu": {
"type": [
"number",
"null"
]
},
"has_audio": {
"type": "boolean"
},
"true_peak_dbtp": {
"type": [
"number",
"null"
]
},
"integrated_lufs": {
"type": [
"number",
"null"
]
}
}
},
"width": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"height": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"motion": {
"type": "object",
"required": [
"step_s",
"diff"
],
"properties": {
"diff": {
"type": "array",
"items": {
"type": "number"
}
},
"step_s": {
"type": "number",
"exclusiveMinimum": 0
}
}
},
"version": {
"type": "number"
},
"duration_s": {
"type": "number",
"exclusiveMinimum": 0
}
}
},
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
{
"type": "string"
}
],
"description": "The JSON printed by `node scripts/measure.mjs <your video>`, as an object (or that JSON as text)"
},
"target": {
"enum": [
"x",
"youtube",
"tiktok",
"web"
],
"type": "string",
"description": "Where it will be posted; sets the loudness target: x and youtube −14 LUFS, tiktok −14 to −10, web −16, true peak ≤ −1 dBTP. Default: the reference's platform"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
}
}
}The full reverse-engineered blueprint of one video: hook frame by frame, beat sheet with timestamps, shot list, style guide, voice and sound, script template, production plan, edit recipe, QA checklist, plus a runnable recipe prompt. Markdown by default; format "json" returns the plates, toolkit, recipe and measured timeline as one object. To see the film's frames, call get_frames. Accepts a REF id (REF-0005), a refs.video link, the source YouTube/X link, or the id from search_videos.
| Argument | Type | Description |
|---|---|---|
| id* | string | REF-0005, a refs.video/v/… link, a YouTube/X link, an id from search_videos, or one of your brand films (brand:<import>:<film>, from get_brand) |
| format | string | Default markdown. "json": plates as an array, the toolkit, the measured timeline (shots, camera, type, audio grid) and the frame sheets on hand |
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
One of your brand imports: the brand kit (the brand's house style across all its films: palette, type, logo and end card, motion and easing, pacing and cut rhythm, camera, transitions, sound and voice, recurring formats, written as rules to follow) plus each film's blueprint summary with its id (brand:<import>:<film>) for get_blueprint and get_frames. Private to you. To make a new film in this style, call plan_video(brief, brand: id).
| Argument | Type | Description |
|---|---|---|
| id* | string | An import id from list_brands, a refs.video/b/… link, or the X handle you imported (e.g. @yourbrand) |
| limit | integer | Films to include; default 20 |
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
Every film in a Refs collection as search cards (REF id, link, length, aspect, measured metrics, why it works). Takes a collection id or refs.video/c/… link: anyone's shared collection, or your own private one; "favourites" gives the films you hearted. Then use them as references: plan_video(brief, reference_ids) with up to 5 that fit the brief, get_blueprint for one film in full.
| Argument | Type | Description |
|---|---|---|
| id* | string | A collection id like k3j9x2mq, a refs.video/c/… link, or "favourites" |
| limit | integer | Default 50 |
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"context",
"llm_model"
],
"properties": {
"id": {
"type": "string",
"description": "A collection id like k3j9x2mq, a refs.video/c/… link, or \"favourites\""
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Default 50"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
}
}
}The full cross-video formula for one format, as markdown: structure, timing ranges, what top performers share, mistakes to avoid, and a template prompt.
| Argument | Type | Description |
|---|---|---|
| id* | string | |
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"context",
"llm_model"
],
"properties": {
"id": {
"type": "string"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
}
}
}One video's labelled frame sheets as images, so you can see the reference instead of guessing from text: the hook (first 3 s at 0.25 s steps), one frame per shot, and the whole film at fixed steps where measured. sheet "transitions" adds every frame around each cut and in-shot change, for timing transitions to the frame. Each image follows a caption saying how its labels read. Accepts the same ids as get_blueprint.
| Argument | Type | Description |
|---|---|---|
| id* | string | REF-0005, a refs.video/v/… link, a YouTube/X link, an id from search_videos, or one of your brand films (brand:<import>:<film>) |
| sheet | string | Default all (hook, shots and timeline; ask for "transitions" separately) |
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
Your brand imports on refs.video (refs.video/saved → Brandprint): each X account you imported, with its progress and film count. Private to you. Pass an id or handle to get_brand for the brand kit and every film.
| Argument | Type | Description |
|---|---|---|
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"context",
"llm_model"
],
"properties": {
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
}
}
}Your collections on refs.video (named sets of films you saved) and your favourites, with ids and film counts. Pass an id to get_collection to read the films and use them as references.
| Argument | Type | Description |
|---|---|---|
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"context",
"llm_model"
],
"properties": {
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
}
}
}Formulas distilled across many videos of one format (e.g. 'the silent UI workflow', 'the delayed hardware reveal'). Returns ids, titles, summaries and their source films; fetch one with get_formula.
| Argument | Type | Description |
|---|---|---|
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| category | string | |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"context",
"llm_model"
],
"properties": {
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"category": {
"enum": [
"launch",
"demo",
"explainers",
"motion",
"interactive",
"films",
"teaser"
],
"type": "string"
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
}
}
}Give a brief (product, audience, length, platform) and 1-5 references (REF ids, links or ids, or your brand films' brand:<import>:<film> ids), and optionally one of your imported brands (brand) to plan in its house style. Returns, per reference, the plates that carry its timing and look (format, hook, beat sheet, style, sound, edit recipe) plus its recipe prompt, and the one formula that best matches, with instructions to write a shot list and a build prompt for the user's own video. With several references it also says how to mix them: one spine for structure and timing, and one named job for each of the others. Name the spine first if you already know it. Then, like an editor, it storyboards before anything is built: you draft the storyboard (1 direction for a fixed brief, 2–4 for an open one), check it with the storyboard tool and lay it out as a Claude Design canvas, the user picks a direction, and only then do you write the build prompt. For every plate of one film, use get_blueprint.
| Argument | Type | Description |
|---|---|---|
| brand | string | One of your brand imports (id or @handle, from list_brands): its brand kit becomes the house-style constraint |
| brief* | string | What the user wants to make |
| context* | string | Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
Search 4,000+ dissected top-performing videos (launch films, product demos, explainers, motion design, interactive/3D, film + music, teasers). Returns compact cards: REF id, link, a small still (thumb), length, aspect, views, measured metrics (shots, cuts per minute, voice, music) and why each works. Use it to find references before making a video; pass a ref to get_blueprint or plan_video.
| Argument | Type | Description |
|---|---|---|
| sort | string | recommended = only the films a digital product (SaaS, app, AI or dev tool) would copy for its launch film, best first; none = every film, with those recommended ones still first |
| brand | string | A tracked brand, e.g. linear, higgsfield, runway, vercel, openai |
| limit | integer | Default 8 |
| query | string | Keywords, e.g. 'developer tool launch dark UI', 'founder to camera', 'kinetic type', 'terminal UI launch'. Films matching every word come first; if none does, films matching some of the words (the result then has a note). A REF id or a YouTube/X link finds that film. |
| aspect | string | Frame shape, as cards name it: 16:9 (landscape), 9:16 (vertical/reels), 1:1 (square), 4:5 (portrait feed) |
| offset | integer | |
| ai_made | boolean | true = made with AI/code (Claude, Remotion, three.js); false = human-made |
Before anything is built, storyboard the film the way an editor does. Send the storyboard you drafted from plan_video: 1 direction for a fixed brief, 2–4 when it's open. Each direction: logline, references (REF id + the one job each does), palette, type, sound, 2–3 style frames at full look, and 3–30 numbered panels in order, each with in/out seconds, shot size, camera move, action, VO, on-screen text, sound, the transition into the next panel, and its frame as layers (text, REF stills or the user's own captures by https URL, and shapes; positions in % of the frame). Mark a layer real only when it's a real capture of the user's product or a real result. This checks the timing and the REF ids and returns each REF's real still. While it returns ok: false it lists what to fix (fix it and call again); with ok: true it tells you how to lay the storyboard out as a Claude Design canvas (or as a text board where you can't make one). Free with Pro. Let the user pick a direction before you write any build prompt.
| Argument | Type | Description |
|---|---|---|
| bpm | number | |
| fps | integer | |
| brand | string | Brandprint import used for the look, if any |
| brief* | string | |
| title* | string | |
| aspect* | string | |
| context* |
| include_recipe | boolean | Default true |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"context",
"llm_model"
],
"properties": {
"id": {
"type": "string",
"description": "REF-0005, a refs.video/v/… link, a YouTube/X link, an id from search_videos, or one of your brand films (brand:<import>:<film>, from get_brand)"
},
"format": {
"enum": [
"markdown",
"json"
],
"type": "string",
"description": "Default markdown. \"json\": plates as an array, the toolkit, the measured timeline (shots, camera, type, audio grid) and the frame sheets on hand"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"include_recipe": {
"type": "boolean",
"description": "Default true"
}
}
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"context",
"llm_model"
],
"properties": {
"id": {
"type": "string",
"description": "An import id from list_brands, a refs.video/b/… link, or the X handle you imported (e.g. @yourbrand)"
},
"limit": {
"type": "integer",
"maximum": 20,
"minimum": 1,
"description": "Films to include; default 20"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
}
}
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"context",
"llm_model"
],
"properties": {
"id": {
"type": "string",
"description": "REF-0005, a refs.video/v/… link, a YouTube/X link, an id from search_videos, or one of your brand films (brand:<import>:<film>)"
},
"sheet": {
"enum": [
"hook",
"shots",
"timeline",
"transitions",
"all"
],
"type": "string",
"description": "Default all (hook, shots and timeline; ask for \"transitions\" separately)"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
}
}
}| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
| reference_ids | array | REF-0005, refs.video/v/… or YouTube/X links, ids (get_collection lists a collection's films), or brand:<import>:<film> ids. Optional with brand: then the brand's own top films are the references |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"brief",
"context",
"llm_model"
],
"properties": {
"brand": {
"type": "string",
"description": "One of your brand imports (id or @handle, from list_brands): its brand kit becomes the house-style constraint"
},
"brief": {
"type": "string",
"description": "What the user wants to make"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"reference_ids": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 5,
"minItems": 1,
"description": "REF-0005, refs.video/v/… or YouTube/X links, ids (get_collection lists a collection's films), or brand:<import>:<film> ids. Optional with brand: then the brand's own top films are the references"
}
}
}| context* |
| string |
| Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| category | string |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
| made_with | string | Tool, e.g. claude, remotion, three.js, manim, after effects |
| max_seconds | number | e.g. 30 for short films |
| min_seconds | number |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"context",
"llm_model"
],
"properties": {
"sort": {
"enum": [
"recommended",
"none",
"added",
"views",
"shortest",
"longest",
"catalogue"
],
"type": "string",
"description": "recommended = only the films a digital product (SaaS, app, AI or dev tool) would copy for its launch film, best first; none = every film, with those recommended ones still first"
},
"brand": {
"type": "string",
"description": "A tracked brand, e.g. linear, higgsfield, runway, vercel, openai"
},
"limit": {
"type": "integer",
"maximum": 20,
"minimum": 1,
"description": "Default 8"
},
"query": {
"type": "string",
"description": "Keywords, e.g. 'developer tool launch dark UI', 'founder to camera', 'kinetic type', 'terminal UI launch'. Films matching every word come first; if none does, films matching some of the words (the result then has a note). A REF id or a YouTube/X link finds that film."
},
"aspect": {
"enum": [
"16:9",
"9:16",
"1:1",
"4:5"
],
"type": "string",
"description": "Frame shape, as cards name it: 16:9 (landscape), 9:16 (vertical/reels), 1:1 (square), 4:5 (portrait feed)"
},
"offset": {
"type": "integer",
"maximum": 2000,
"minimum": 0
},
"ai_made": {
"type": "boolean",
"description": "true = made with AI/code (Claude, Remotion, three.js); false = human-made"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"category": {
"enum": [
"launch",
"demo",
"explainers",
"motion",
"interactive",
"films",
"teaser"
],
"type": "string"
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"made_with": {
"type": "string",
"description": "Tool, e.g. claude, remotion, three.js, manim, after effects"
},
"max_seconds": {
"type": "number",
"minimum": 0,
"description": "e.g. 30 for short films"
},
"min_seconds": {
"type": "number",
"minimum": 0
}
}
}| string |
| Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as "a user", "the customer", or "an account". Example: "Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution." |
| length_s* | number |
| llm_model* | string | The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. "claude-opus-4-8", "gpt-5.2"). Used for analytics only. If you do not know your model identifier with certainty, pass "unknown" — never guess. |
| directions* | array |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"title",
"brief",
"aspect",
"length_s",
"directions",
"context",
"llm_model"
],
"properties": {
"bpm": {
"type": "number",
"maximum": 220,
"minimum": 40
},
"fps": {
"type": "integer",
"maximum": 120,
"minimum": 12
},
"brand": {
"type": "string",
"maxLength": 80,
"description": "Brandprint import used for the look, if any"
},
"brief": {
"type": "string",
"maxLength": 1200,
"minLength": 1
},
"title": {
"type": "string",
"maxLength": 100,
"minLength": 1
},
"aspect": {
"enum": [
"16:9",
"9:16",
"1:1",
"4:5"
],
"type": "string"
},
"context": {
"type": "string",
"description": "Explain in 15-25 words, in third person, why this tool is called and how it supports the user's goal. For analytics only. You MUST describe only the abstract purpose of the tool call. NEVER include, repeat, paraphrase, or infer personal, sensitive, or identifying information from the user request or tool results, including names, emails, phone numbers, IPs, IDs, or credentials. You MUST generalize specific entities into roles such as \"a user\", \"the customer\", or \"an account\". Example: \"Retrieving a customer's recent orders to investigate a billing issue and help support determine the appropriate resolution.\""
},
"length_s": {
"type": "number",
"maximum": 900,
"minimum": 3
},
"llm_model": {
"type": "string",
"description": "The exact model identifier you (the assistant) are running as, taken from your system prompt or environment (e.g. \"claude-opus-4-8\", \"gpt-5.2\"). Used for analytics only. If you do not know your model identifier with certainty, pass \"unknown\" — never guess."
},
"directions": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"logline",
"references",
"palette",
"type",
"sound",
"style_frames",
"panels"
],
"properties": {
"name": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"type": {
"type": "object",
"required": [
"display",
"body"
],
"properties": {
"body": {
"type": "string",
"maxLength": 60
},
"mono": {
"type": "string",
"maxLength": 60
},
"note": {
"type": "string",
"maxLength": 200
},
"display": {
"type": "string",
"maxLength": 60
}
}
},
"sound": {
"type": "string",
"maxLength": 400,
"description": "music and sound design in a line or two"
},
"motion": {
"type": "string",
"maxLength": 400,
"description": "how frames hand off to each other overall"
},
"panels": {
"type": "array",
"items": {
"type": "object",
"required": [
"start",
"end",
"action",
"frame"
],
"properties": {
"vo": {
"type": "string",
"maxLength": 400,
"description": "the spoken line over this panel"
},
"end": {
"type": "number",
"maximum": 900,
"minimum": 0,
"description": "out, seconds"
},
"shot": {
"type": "string",
"maxLength": 12,
"description": "shot number; numbered 1, 2, 3… when left out"
},
"frame": {
"type": "object",
"required": [
"layers"
],
"properties": {
"layers": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"required": [
"type",
"text",
"x",
"y",
"size"
],
"properties": {
"w": {
"type": "number",
"maximum": 150,
"minimum": -50,
"description": "box width, % of frame width (text wraps inside it)"
},
"x": {
"type": "number",
"maximum": 150,
"minimum": -50,
"description": "left edge, % of frame width"
},
"y": {
"type": "number",
"maximum": 150,
"minimum": -50,
"description": "top edge, % of frame height"
},
"font": {
"enum": [
"display",
"body",
"mono",
"serif"
],
"type": "string",
"description": "display = the direction's headline face, body = UI/sans, mono = data, serif = editorial"
},
"real": {
"type": "boolean",
"description": "true only when this is a real capture of the user's product or a real result; anything else is illustrative and is labelled so"
},
"size": {
"type": "number",
"maximum": 80,
"minimum": 0.5,
"description": "font size as % of frame height"
},
"text": {
"type": "string",
"maxLength": 400,
"minLength": 1
},
"type": {
"type": "string",
"const": "text"
},
"align": {
"enum": [
"left",
"center",
"right"
],
"type": "string"
},
"color": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "integer",
"maximum": 900,
"minimum": 100
},
"opacity": {
"type": "number",
"maximum": 1,
"minimum": 0
},
"tracking": {
"type": "number",
"maximum": 0.6,
"minimum": -0.2,
"description": "letter spacing in em"
}
}
},
{
"type": "object",
"required": [
"type",
"src",
"x",
"y",
"w",
"h"
],
"properties": {
"h": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"w": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"x": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"y": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"fit": {
"enum": [
"cover",
"contain"
],
"type": "string"
},
"src": {
"type": "string",
"maxLength": 600,
"minLength": 1,
"description": "\"REF-1234\" for that archive film's still, or an https URL of the user's own capture"
},
"real": {
"type": "boolean",
"description": "true only when this is a real capture of the user's product or a real result; anything else is illustrative and is labelled so"
},
"type": {
"type": "string",
"const": "image"
},
"radius": {
"type": "number",
"maximum": 50,
"minimum": 0,
"description": "corner radius, % of frame height"
},
"opacity": {
"type": "number",
"maximum": 1,
"minimum": 0
},
"grayscale": {
"type": "boolean"
}
}
},
{
"type": "object",
"required": [
"type",
"shape",
"x",
"y",
"w",
"h"
],
"properties": {
"h": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"w": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"x": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"y": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"fill": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
"type": {
"type": "string",
"const": "shape"
},
"shape": {
"enum": [
"rect",
"circle",
"line"
],
"type": "string"
},
"radius": {
"type": "number",
"maximum": 50,
"minimum": 0
},
"stroke": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
"opacity": {
"type": "number",
"maximum": 1,
"minimum": 0
},
"stroke_width": {
"type": "number",
"maximum": 5,
"minimum": 0,
"description": "% of frame height"
}
}
}
]
},
"maxItems": 40
},
"gradient": {
"type": "array",
"items": false,
"maxItems": 2,
"minItems": 2,
"description": "top to bottom; replaces background",
"prefixItems": [
{
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
{
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
}
]
},
"background": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
}
}
},
"sound": {
"type": "string",
"maxLength": 200,
"description": "music cue or SFX"
},
"start": {
"type": "number",
"maximum": 900,
"minimum": 0,
"description": "in, seconds"
},
"action": {
"type": "string",
"maxLength": 400,
"minLength": 1,
"description": "what happens and what moves, in one or two sentences"
},
"camera": {
"enum": [
"static",
"push in",
"pull out",
"pan left",
"pan right",
"tilt up",
"tilt down",
"truck left",
"truck right",
"orbit",
"zoom in",
"zoom out",
"whip",
"handheld"
],
"type": "string",
"description": "the camera move, drawn as arrows on the panel"
},
"look_ref": {
"type": "string",
"maxLength": 20,
"description": "REF id whose look this panel borrows"
},
"on_screen": {
"type": "string",
"maxLength": 200,
"description": "text that appears on screen"
},
"shot_size": {
"enum": [
"extreme wide",
"wide",
"medium",
"close",
"extreme close",
"macro",
"insert",
"ui",
"full-frame type"
],
"type": "string"
},
"transition": {
"type": "object",
"required": [
"kind"
],
"properties": {
"kind": {
"enum": [
"cut",
"match cut",
"dissolve",
"morph",
"wipe",
"push",
"whip",
"fade to black",
"hold"
],
"type": "string"
},
"note": {
"type": "string",
"maxLength": 200,
"description": "how this frame becomes the next, e.g. 'the caret stretches into the search bar'"
},
"frames": {
"type": "integer",
"maximum": 240,
"minimum": 0
}
},
"description": "how this panel becomes the next one"
}
}
},
"maxItems": 30,
"minItems": 3
},
"logline": {
"type": "string",
"maxLength": 280,
"minLength": 1,
"description": "the idea in one line"
},
"palette": {
"type": "array",
"items": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
"maxItems": 8
},
"references": {
"type": "array",
"items": {
"type": "object",
"required": [
"ref",
"contributes"
],
"properties": {
"ref": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "REF id"
},
"contributes": {
"type": "string",
"maxLength": 140,
"minLength": 1,
"description": "the one job it does, e.g. 'structure and timing', 'the hook', 'type treatment'"
}
}
},
"maxItems": 6
},
"style_frames": {
"type": "array",
"items": {
"type": "object",
"required": [
"title",
"frame"
],
"properties": {
"note": {
"type": "string",
"maxLength": 300
},
"frame": {
"type": "object",
"required": [
"layers"
],
"properties": {
"layers": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"required": [
"type",
"text",
"x",
"y",
"size"
],
"properties": {
"w": {
"type": "number",
"maximum": 150,
"minimum": -50,
"description": "box width, % of frame width (text wraps inside it)"
},
"x": {
"type": "number",
"maximum": 150,
"minimum": -50,
"description": "left edge, % of frame width"
},
"y": {
"type": "number",
"maximum": 150,
"minimum": -50,
"description": "top edge, % of frame height"
},
"font": {
"enum": [
"display",
"body",
"mono",
"serif"
],
"type": "string",
"description": "display = the direction's headline face, body = UI/sans, mono = data, serif = editorial"
},
"real": {
"type": "boolean",
"description": "true only when this is a real capture of the user's product or a real result; anything else is illustrative and is labelled so"
},
"size": {
"type": "number",
"maximum": 80,
"minimum": 0.5,
"description": "font size as % of frame height"
},
"text": {
"type": "string",
"maxLength": 400,
"minLength": 1
},
"type": {
"type": "string",
"const": "text"
},
"align": {
"enum": [
"left",
"center",
"right"
],
"type": "string"
},
"color": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
"italic": {
"type": "boolean"
},
"weight": {
"type": "integer",
"maximum": 900,
"minimum": 100
},
"opacity": {
"type": "number",
"maximum": 1,
"minimum": 0
},
"tracking": {
"type": "number",
"maximum": 0.6,
"minimum": -0.2,
"description": "letter spacing in em"
}
}
},
{
"type": "object",
"required": [
"type",
"src",
"x",
"y",
"w",
"h"
],
"properties": {
"h": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"w": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"x": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"y": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"fit": {
"enum": [
"cover",
"contain"
],
"type": "string"
},
"src": {
"type": "string",
"maxLength": 600,
"minLength": 1,
"description": "\"REF-1234\" for that archive film's still, or an https URL of the user's own capture"
},
"real": {
"type": "boolean",
"description": "true only when this is a real capture of the user's product or a real result; anything else is illustrative and is labelled so"
},
"type": {
"type": "string",
"const": "image"
},
"radius": {
"type": "number",
"maximum": 50,
"minimum": 0,
"description": "corner radius, % of frame height"
},
"opacity": {
"type": "number",
"maximum": 1,
"minimum": 0
},
"grayscale": {
"type": "boolean"
}
}
},
{
"type": "object",
"required": [
"type",
"shape",
"x",
"y",
"w",
"h"
],
"properties": {
"h": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"w": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"x": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"y": {
"type": "number",
"maximum": 150,
"minimum": -50
},
"fill": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
"type": {
"type": "string",
"const": "shape"
},
"shape": {
"enum": [
"rect",
"circle",
"line"
],
"type": "string"
},
"radius": {
"type": "number",
"maximum": 50,
"minimum": 0
},
"stroke": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
"opacity": {
"type": "number",
"maximum": 1,
"minimum": 0
},
"stroke_width": {
"type": "number",
"maximum": 5,
"minimum": 0,
"description": "% of frame height"
}
}
}
]
},
"maxItems": 40
},
"gradient": {
"type": "array",
"items": false,
"maxItems": 2,
"minItems": 2,
"description": "top to bottom; replaces background",
"prefixItems": [
{
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
},
{
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
}
]
},
"background": {
"type": "string",
"pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
}
}
},
"title": {
"type": "string",
"maxLength": 80,
"minLength": 1
}
}
},
"maxItems": 3,
"description": "2–3 key frames at full look"
}
}
},
"maxItems": 4,
"minItems": 1
}
}
}