Carousel DSL
The carousel DSL is the contract between the planner and the renderer. The planner emits a CarouselSpec; the renderer turns it into PNGs. The DSL is freeform-only by design: every slide is a positioned grid of elements (text, library components, stat cards) rather than a templated kind. This gives the planner room to produce non-formulaic compositions without exploding the renderer surface.
Overview
- Schema source
cf-workers/marketing-swarm/src/carousel/types.ts- Validator
cf-workers/marketing-swarm/src/carousel/validate.ts- Slide kind
freeform(the only allowed value)- Element kinds
text,library,stat_card- Canvas sizes
- 1080x1080 (square), 1080x1350 (portrait)
- Slide count range
- 3 to 12 per deck
Freeform-only
Every slide is the same kind. There is no cover slide kind, no body slide kind, no list slide kind.
Earlier versions of the DSL had templated slide kinds (cover, body, stat, quote, spotlight, list, logoStrip, compare, cta). The validator now rejects anything that is not freeform. The reasoning is that templated slides forced the planner into a small set of compositions; freeform lets the planner reach for the layout that the brief actually wants. The renderer dispatches to the right component per element, not per slide.
Slide shape
Three required fields: kind, bg, elements.
Element kinds
Three building blocks. Combine them to compose any slide.
| Type | Purpose | Required fields |
|---|---|---|
text | Plain or styled typography on the slide | value, pos |
library | A registered visual component from the library (patterns, shaders, marquees, ripple effects, etc.) | id, pos |
stat_card | Number + label callout | value, label, pos |
pos: "fullbleed" and a negative z so it sits behind everything) plus one to three foreground elements. More than that and the slide reads as cluttered.Positioning
Every element declares its position in percentage of the canvas.
Percentages are passed through verbatim to the renderer's CSS layer. { x: "5%", y: "20%", w: "90%" } means anchor the element at 5 percent from the left, 20 percent from the top, and span 90 percent of the canvas width. fullbleed is a shorthand for the typical backdrop position. The planner picks values that align cleanly to a 12-column grid most of the time but is not forced to.
Per-slide budgets
The validator caps character counts per element kind so a slide cannot overflow.
End-to-end example
One slide. One backdrop, one headline, one stat.
File map
Glossary
- DSL
- The Carousel DSL. The JSON shape that connects the planner and the renderer.
- Freeform
- The only allowed slide kind. Each slide is a positioned grid of elements.
- Element
- One thing on a slide. text, library, or stat_card.
- Position
- Where an element lives on the canvas. Either fullbleed or percentage-based x/y/w/h.
- Backdrop
- A library element set fullbleed with a negative z so it sits behind the foreground.
- Budget
- A character cap on an element kind enforced by the validator.