Spotlight, Neo-brutalist 1.0.0
| Template | Spotlight, tpl_dbadb7ef4a70 |
|---|---|
| Variant | Neo-brutalist |
| Version | 1.0.0, the newest: what a channel following this variant draws |
| Shapes | 9x16, 4x5, 1x1, 16x9, 2x3 |
| Length | 12 seconds |
Example video
The 1x1 cut of this version, drawn from its own worked example. Open the video on its own.
What it accepts
One subject in the spotlight: a picture or a logo settling in, a title, a line about it and up to eight facts that count up, four at a time, each with an optional change or a bar. metaData is the post's title, descriptions and hashtags and is never drawn.
| Field | Type | Required | Limit | What it is |
|---|---|---|---|---|
clipData | group | yes | Clip data: Everything drawn: a kicker, the title, a line about the subject, its picture and how it is fitted, up to eight facts, the credit and the look. | |
clipData.kicker | text | up to 20 characters | Kicker: A word above the title, such as STOCK SPOTLIGHT or IMAGE OF THE DAY. | |
clipData.title | text | yes | up to 80 characters | Title: What the subject is and why it is in the spotlight. Shown from the first frame. |
clipData.text | text | up to 160 characters | Line: One or two sentences about the subject. | |
clipData.picture | image | yes | media:// file from the media library, alt text up to 120 characters | Picture or logo: The subject: a photograph, a product shot or a logo. |
clipData.pictureFit | enum | fill, whole | Picture fit: Fill the frame for a photograph; show it whole for a logo or a cut-out product. | |
clipData.facts | list | up to 8 | Facts: Up to eight figures about the subject, counting up, four at a time: past four they turn a page. A fact with an Out of value is drawn as a bar. Each adds a second. | |
clipData.facts[] | group | Fact | ||
clipData.facts[].label | text | yes | up to 24 characters | What it is |
clipData.facts[].value | number | yes | 4 decimals | Figure |
clipData.facts[].prefix | text | up to 3 characters | Prefix: Written before the figure, such as a currency sign. | |
clipData.facts[].unit | text | up to 12 characters | Unit: Written after the figure: a percent sign, million, days. | |
clipData.facts[].change | number | 2 decimals | Change in percent: Drawn under the figure with an arrow, green for up, red for down. | |
clipData.facts[].max | number | from 0, 4 decimals | Out of: Draws the fact as a bar filling to its share of this figure. | |
clipData.credit | text | up to 60 characters | Credit: Whose picture and figures these are. | |
clipData.look | group | Look: How the clip looks and moves within its style. The same four switches in every format of the collections. Leave a switch out, or set it to the style's own, and the style decides. | ||
clipData.look.theme | enum | auto, brand, light, dark, bold | Theme: The style's own choice; your brand's own colours and background; a light or dark page tinted with your brand colour; or your brand colour as the page. | |
clipData.look.pace | enum | auto, calm, standard, punchy | Pace: How things arrive: the style's own rhythm, calm fades, a standard rhythm, or punchy slams and cuts. | |
clipData.look.corners | enum | auto, square, soft, round | Corners: The shape of cards, panels and marks. | |
clipData.look.align | enum | auto, start, centre | Text alignment: Where the text lines up. | |
metaData | group | Meta data: Everything about the post that is never drawn in the clip: its title, its description in four lengths, one per kind of platform, and its hashtags. Reelwire adds the brand's description, link and hashtags after it. Left out, the post text is generated from the clip data. | ||
metaData.title | text | up to 100 characters | Title: Used where the platform has a title of its own: Facebook Feed, LinkedIn, Pinterest and YouTube. Up to 100 characters, which every one of them takes. | |
metaData.captionTiny | text | up to 200 characters | Tiny description (Pinterest, Threads, X): Up to 200 characters. The brand's description, link and hashtags follow it within the platform's limit. | |
metaData.captionShort | text | up to 500 characters | Short description (Telegram, Threema, WeChat, WhatsApp): Up to 500 characters. The brand's description, link and hashtags follow it within the platform's limit. | |
metaData.captionMedium | text | up to 1500 characters | Medium description (Discord, Facebook Reels, Instagram, LinkedIn, Signal, Slack, TikTok): Up to 1500 characters. The brand's description, link and hashtags follow it within the platform's limit. | |
metaData.captionLong | text | up to 4000 characters | Long description (Facebook Feed, YouTube): Up to 4000 characters. The brand's description, link and hashtags follow it within the platform's limit. | |
metaData.hashtags | list | up to 15 | Hashtags: Written without the #. Up to 15, which every platform takes. | |
metaData.hashtags[] | text | up to 60 characters | Hashtag |
locales carries other languages: under each language code, the parts of clipData and metaData that differ, laid over the default, so a language with no copy still renders.
A picture is always a file from your media library: media:// followed by its id or its name.
Anything the table does not list is refused, and so is anything over its limit, with a 422 that
names the field.
The JSON Schema
{
"type": "object",
"properties": {
"clipData": {
"type": "object",
"properties": {
"kicker": {
"type": "string",
"maxLength": 20,
"title": "Kicker",
"description": "A word above the title, such as STOCK SPOTLIGHT or IMAGE OF THE DAY."
},
"title": {
"type": "string",
"maxLength": 80,
"title": "Title",
"description": "What the subject is and why it is in the spotlight. Shown from the first frame."
},
"text": {
"type": "string",
"maxLength": 160,
"title": "Line",
"description": "One or two sentences about the subject."
},
"picture": {
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 2048,
"pattern": "^media:\\/\\/[^\\s/\\\\\\u0000-\\u001f][^/\\\\\\u0000-\\u001f]{0,254}$",
"title": "Picture",
"description": "A file from the workspace's media library, written media:// and the file's id or name. A web address is refused."
},
"alt": {
"type": "string",
"maxLength": 120,
"title": "Alt text",
"description": "What the picture shows, for anyone who cannot see it."
}
},
"required": [
"url"
],
"additionalProperties": false,
"title": "Picture or logo",
"description": "The subject: a photograph, a product shot or a logo."
},
"pictureFit": {
"type": "string",
"enum": [
"fill",
"whole"
],
"title": "Picture fit",
"description": "Fill the frame for a photograph; show it whole for a logo or a cut-out product."
},
"facts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"maxLength": 24,
"title": "What it is"
},
"value": {
"type": "number",
"title": "Figure"
},
"prefix": {
"type": "string",
"maxLength": 3,
"title": "Prefix",
"description": "Written before the figure, such as a currency sign."
},
"unit": {
"type": "string",
"maxLength": 12,
"title": "Unit",
"description": "Written after the figure: a percent sign, million, days."
},
"change": {
"type": "number",
"title": "Change in percent",
"description": "Drawn under the figure with an arrow, green for up, red for down."
},
"max": {
"type": "number",
"minimum": 0,
"title": "Out of",
"description": "Draws the fact as a bar filling to its share of this figure."
}
},
"required": [
"label",
"value"
],
"additionalProperties": false,
"title": "Fact"
},
"maxItems": 8,
"title": "Facts",
"description": "Up to eight figures about the subject, counting up, four at a time: past four they turn a page. A fact with an Out of value is drawn as a bar. Each adds a second."
},
"credit": {
"type": "string",
"maxLength": 60,
"title": "Credit",
"description": "Whose picture and figures these are."
},
"look": {
"type": "object",
"properties": {
"theme": {
"type": "string",
"enum": [
"auto",
"brand",
"light",
"dark",
"bold"
],
"title": "Theme",
"description": "The style's own choice; your brand's own colours and background; a light or dark page tinted with your brand colour; or your brand colour as the page."
},
"pace": {
"type": "string",
"enum": [
"auto",
"calm",
"standard",
"punchy"
],
"title": "Pace",
"description": "How things arrive: the style's own rhythm, calm fades, a standard rhythm, or punchy slams and cuts."
},
"corners": {
"type": "string",
"enum": [
"auto",
"square",
"soft",
"round"
],
"title": "Corners",
"description": "The shape of cards, panels and marks."
},
"align": {
"type": "string",
"enum": [
"auto",
"start",
"centre"
],
"title": "Text alignment",
"description": "Where the text lines up."
}
},
"additionalProperties": false,
"title": "Look",
"description": "How the clip looks and moves within its style. The same four switches in every format of the collections. Leave a switch out, or set it to the style's own, and the style decides."
}
},
"required": [
"title",
"picture"
],
"additionalProperties": false,
"title": "Clip data",
"description": "Everything drawn: a kicker, the title, a line about the subject, its picture and how it is fitted, up to eight facts, the credit and the look."
},
"metaData": {
"type": "object",
"properties": {
"title": {
"type": "string",
"maxLength": 100,
"title": "Title",
"description": "Used where the platform has a title of its own: Facebook Feed, LinkedIn, Pinterest and YouTube. Up to 100 characters, which every one of them takes."
},
"captionTiny": {
"type": "string",
"maxLength": 200,
"title": "Tiny description (Pinterest, Threads, X)",
"description": "Up to 200 characters. The brand's description, link and hashtags follow it within the platform's limit."
},
"captionShort": {
"type": "string",
"maxLength": 500,
"title": "Short description (Telegram, Threema, WeChat, WhatsApp)",
"description": "Up to 500 characters. The brand's description, link and hashtags follow it within the platform's limit."
},
"captionMedium": {
"type": "string",
"maxLength": 1500,
"title": "Medium description (Discord, Facebook Reels, Instagram, LinkedIn, Signal, Slack, TikTok)",
"description": "Up to 1500 characters. The brand's description, link and hashtags follow it within the platform's limit."
},
"captionLong": {
"type": "string",
"maxLength": 4000,
"title": "Long description (Facebook Feed, YouTube)",
"description": "Up to 4000 characters. The brand's description, link and hashtags follow it within the platform's limit."
},
"hashtags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 60,
"title": "Hashtag"
},
"maxItems": 15,
"title": "Hashtags",
"description": "Written without the #. Up to 15, which every platform takes."
}
},
"additionalProperties": false,
"title": "Meta data",
"description": "Everything about the post that is never drawn in the clip: its title, its description in four lengths, one per kind of platform, and its hashtags. Reelwire adds the brand's description, link and hashtags after it. Left out, the post text is generated from the clip data."
},
"locales": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"clipData": {
"type": "object",
"properties": {
"kicker": {
"type": "string",
"maxLength": 20,
"title": "Kicker",
"description": "A word above the title, such as STOCK SPOTLIGHT or IMAGE OF THE DAY."
},
"title": {
"type": "string",
"maxLength": 80,
"title": "Title",
"description": "What the subject is and why it is in the spotlight. Shown from the first frame."
},
"text": {
"type": "string",
"maxLength": 160,
"title": "Line",
"description": "One or two sentences about the subject."
},
"picture": {
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 2048,
"pattern": "^media:\\/\\/[^\\s/\\\\\\u0000-\\u001f][^/\\\\\\u0000-\\u001f]{0,254}$",
"title": "Picture",
"description": "A file from the workspace's media library, written media:// and the file's id or name. A web address is refused."
},
"alt": {
"type": "string",
"maxLength": 120,
"title": "Alt text",
"description": "What the picture shows, for anyone who cannot see it."
}
},
"required": [
"url"
],
"additionalProperties": false,
"title": "Picture or logo",
"description": "The subject: a photograph, a product shot or a logo."
},
"pictureFit": {
"type": "string",
"enum": [
"fill",
"whole"
],
"title": "Picture fit",
"description": "Fill the frame for a photograph; show it whole for a logo or a cut-out product."
},
"facts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"maxLength": 24,
"title": "What it is"
},
"value": {
"type": "number",
"title": "Figure"
},
"prefix": {
"type": "string",
"maxLength": 3,
"title": "Prefix",
"description": "Written before the figure, such as a currency sign."
},
"unit": {
"type": "string",
"maxLength": 12,
"title": "Unit",
"description": "Written after the figure: a percent sign, million, days."
},
"change": {
"type": "number",
"title": "Change in percent",
"description": "Drawn under the figure with an arrow, green for up, red for down."
},
"max": {
"type": "number",
"minimum": 0,
"title": "Out of",
"description": "Draws the fact as a bar filling to its share of this figure."
}
},
"required": [
"label",
"value"
],
"additionalProperties": false,
"title": "Fact"
},
"maxItems": 8,
"title": "Facts",
"description": "Up to eight figures about the subject, counting up, four at a time: past four they turn a page. A fact with an Out of value is drawn as a bar. Each adds a second."
},
"credit": {
"type": "string",
"maxLength": 60,
"title": "Credit",
"description": "Whose picture and figures these are."
},
"look": {
"type": "object",
"properties": {
"theme": {
"type": "string",
"enum": [
"auto",
"brand",
"light",
"dark",
"bold"
],
"title": "Theme",
"description": "The style's own choice; your brand's own colours and background; a light or dark page tinted with your brand colour; or your brand colour as the page."
},
"pace": {
"type": "string",
"enum": [
"auto",
"calm",
"standard",
"punchy"
],
"title": "Pace",
"description": "How things arrive: the style's own rhythm, calm fades, a standard rhythm, or punchy slams and cuts."
},
"corners": {
"type": "string",
"enum": [
"auto",
"square",
"soft",
"round"
],
"title": "Corners",
"description": "The shape of cards, panels and marks."
},
"align": {
"type": "string",
"enum": [
"auto",
"start",
"centre"
],
"title": "Text alignment",
"description": "Where the text lines up."
}
},
"additionalProperties": false,
"title": "Look",
"description": "How the clip looks and moves within its style. The same four switches in every format of the collections. Leave a switch out, or set it to the style's own, and the style decides."
}
},
"additionalProperties": false,
"title": "Clip data",
"description": "Everything drawn: a kicker, the title, a line about the subject, its picture and how it is fitted, up to eight facts, the credit and the look."
},
"metaData": {
"type": "object",
"properties": {
"title": {
"type": "string",
"maxLength": 100,
"title": "Title",
"description": "Used where the platform has a title of its own: Facebook Feed, LinkedIn, Pinterest and YouTube. Up to 100 characters, which every one of them takes."
},
"captionTiny": {
"type": "string",
"maxLength": 200,
"title": "Tiny description (Pinterest, Threads, X)",
"description": "Up to 200 characters. The brand's description, link and hashtags follow it within the platform's limit."
},
"captionShort": {
"type": "string",
"maxLength": 500,
"title": "Short description (Telegram, Threema, WeChat, WhatsApp)",
"description": "Up to 500 characters. The brand's description, link and hashtags follow it within the platform's limit."
},
"captionMedium": {
"type": "string",
"maxLength": 1500,
"title": "Medium description (Discord, Facebook Reels, Instagram, LinkedIn, Signal, Slack, TikTok)",
"description": "Up to 1500 characters. The brand's description, link and hashtags follow it within the platform's limit."
},
"captionLong": {
"type": "string",
"maxLength": 4000,
"title": "Long description (Facebook Feed, YouTube)",
"description": "Up to 4000 characters. The brand's description, link and hashtags follow it within the platform's limit."
},
"hashtags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 60,
"title": "Hashtag"
},
"maxItems": 15,
"title": "Hashtags",
"description": "Written without the #. Up to 15, which every platform takes."
}
},
"additionalProperties": false,
"title": "Meta data",
"description": "Everything about the post that is never drawn in the clip: its title, its description in four lengths, one per kind of platform, and its hashtags. Reelwire adds the brand's description, link and hashtags after it. Left out, the post text is generated from the clip data."
}
},
"additionalProperties": false
},
"propertyNames": {
"enum": [
"aa",
"ab",
"ae",
"af",
"ak",
"am",
"an",
"ar",
"as",
"av",
"ay",
"az",
"ba",
"be",
"bg",
"bi",
"bm",
"bn",
"bo",
"br",
"bs",
"ca",
"ce",
"ch",
"co",
"cr",
"cs",
"cu",
"cv",
"cy",
"da",
"de",
"dv",
"dz",
"ee",
"el",
"en",
"eo",
"es",
"et",
"eu",
"fa",
"ff",
"fi",
"fj",
"fo",
"fr",
"fy",
"ga",
"gd",
"gl",
"gn",
"gu",
"gv",
"ha",
"he",
"hi",
"ho",
"hr",
"ht",
"hu",
"hy",
"hz",
"ia",
"id",
"ie",
"ig",
"ii",
"ik",
"io",
"is",
"it",
"iu",
"ja",
"jv",
"ka",
"kg",
"ki",
"kj",
"kk",
"kl",
"km",
"kn",
"ko",
"kr",
"ks",
"ku",
"kv",
"kw",
"ky",
"la",
"lb",
"lg",
"li",
"ln",
"lo",
"lt",
"lu",
"lv",
"mg",
"mh",
"mi",
"mk",
"ml",
"mn",
"mr",
"ms",
"mt",
"my",
"na",
"nb",
"nd",
"ne",
"ng",
"nl",
"nn",
"no",
"nr",
"nv",
"ny",
"oc",
"oj",
"om",
"or",
"os",
"pa",
"pi",
"pl",
"ps",
"pt",
"qu",
"rm",
"rn",
"ro",
"ru",
"rw",
"sa",
"sc",
"sd",
"se",
"sg",
"si",
"sk",
"sl",
"sm",
"sn",
"so",
"sq",
"sr",
"ss",
"st",
"su",
"sv",
"sw",
"ta",
"te",
"tg",
"th",
"ti",
"tk",
"tl",
"tn",
"to",
"tr",
"ts",
"tt",
"tw",
"ty",
"ug",
"uk",
"ur",
"uz",
"ve",
"vi",
"vo",
"wa",
"wo",
"xh",
"yi",
"yo",
"za",
"zh",
"zu",
"zh-CN",
"zh-TW",
"pt-BR"
]
}
}
},
"required": [
"clipData"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}
Ask Reelwire for the same document yourself, without signing in:
curl "http://localhost:4000/v1/formats/template/tpl_dbadb7ef4a70?variant=Neo-brutalist&version=1.0.0"
Delivery JSON
Your own system sends this to one of your streams, POST /v1/stream, and every channel listening to
that stream draws it with its template. data is the document described above; a stream with an
empty field map passes it to the template unchanged. Try it first on POST /v1/stream/validate,
which answers the same without publishing anything. Streams and feeds
explains the rest, including how to map a document of your own shape instead.
{
"streamId": "st_your_stream_id",
"eventId": "01M2SQMKK3G1NVFXV31DCBVB95",
"occurredAt": "2026-09-23T07:00:00Z",
"locale": "en",
"data": {
"clipData": {
"kicker": "Stock spotlight",
"title": "Kestrel Wind raises its outlook after a record summer at its offshore parks",
"text": "The North Sea operator now expects a third more profit this year, after its parks ran at full output for 61 days between June and August.",
"picture": {
"alt": "A landscape under a pale sky",
"url": "media://example-image.svg"
},
"pictureFit": "fill",
"facts": [
{
"label": "Share price",
"value": 48.25,
"change": 6.4,
"prefix": "€"
},
{
"unit": "million",
"label": "Profit forecast",
"value": 410,
"change": 33,
"prefix": "€"
},
{
"unit": "billion",
"label": "Market value",
"value": 12.4,
"prefix": "€"
},
{
"max": 92,
"unit": "days",
"label": "Days at full output",
"value": 61
},
{
"unit": "parks",
"label": "Parks at sea",
"value": 7
},
{
"unit": "million",
"label": "Homes supplied",
"value": 2.1,
"change": 12
}
],
"credit": "Picture: Kestrel Wind. Share data at Friday's close",
"look": {
"theme": "auto",
"pace": "auto",
"corners": "auto",
"align": "auto"
}
},
"metaData": {
"title": "Kestrel Wind raises its outlook after a record summer at its North Sea parks",
"captionTiny": "Stock spotlight: Kestrel Wind raises its profit outlook by a third after its offshore parks ran at full output for 61 days this summer. Shares up 6.4 percent.",
"captionShort": "Stock spotlight: Kestrel Wind. The North Sea operator raised its profit forecast to 410 million euros, a third more than it expected in spring, after its offshore parks ran at full output for 61 of the 92 days between June and August. The shares closed 6.4 percent higher at 48.25 euros on Friday, valuing the company at 12.4 billion euros. Figures are illustrative.",
"captionMedium": "Stock spotlight: Kestrel Wind. The North Sea operator raised its profit forecast for the year to 410 million euros on Friday, a third more than it expected in spring. The reason is the weather: its offshore parks ran at full output for 61 of the 92 days between June and August, its best summer since the first turbines turned. The shares closed 6.4 percent higher at 48.25 euros, valuing the company at 12.4 billion euros, the highest since its listing. Analysts point out that a windy summer is not a plan, and that the company still has to finish two new parks on time and within budget next year. The management said both are on schedule and that it will say more at its results in November. The figures in this clip are illustrative.",
"captionLong": "Stock spotlight: Kestrel Wind. The North Sea operator raised its profit forecast for the year to 410 million euros on Friday, a third more than it expected in spring. The reason is the weather: its offshore parks ran at full output for 61 of the 92 days between June and August, its best summer since the first turbines turned. Summer is usually the quiet season for wind, so a good one lifts a whole year. The shares closed 6.4 percent higher at 48.25 euros, valuing the company at 12.4 billion euros, the highest since its listing. Trading volume was three times the daily average, and the shares have now risen for six weeks in a row. Analysts point out that a windy summer is not a plan, and that the company still has to finish two new parks on time and within budget next year, at a time when cables, ships and steel are all in short supply. Several also noted that the price the company receives for its power is fixed for most of its output until 2029, which makes its income steadier than that of its rivals, but also means it gains less when power prices rise. The management said both new parks are on schedule, that the first turbines will be installed in spring, and that it will say more at its results in November, including whether the higher profit will mean a higher dividend. The figures in this clip are illustrative and the company is fictional.",
"hashtags": [
"stocks",
"windpower",
"energy",
"renewables",
"markets"
]
}
}
}
The delivery names no version: which build draws it is the channel's choice, the newest of its
variant or the one it is pinned to. eventId is a ULID you make once per event: sending the same
one again changes nothing. occurredAt is when the thing happened, not when you sent it. locale
is the language of the text in data, and data.locales carries other languages beside it.