Compose design
compose_designCreate a new social media design (a single image or a multi-slide carousel) from a layout you describe in the JSON format below, and save it to the workspace, where it can be opened in the Blaze editor. Inputs: workspace_key, dsl; optional title. Call get_brand_kit first for the brand colors and fonts; search_fonts finds other fonts and search_media or generate_image provide photos.
Layout: content in "stack", "row", and "grid" containers and "overlay" anchors is placed automatically and cannot overflow the frame, so no coordinates are needed. Decorative elements in "free" can be placed at exact x/y positions, including partly off the canvas.
Pass dsl as: { "frames": [ Frame, ... ] } (one frame = one slide; carousels have several)
Frame {
"w": 1080, "h": 1350, // 4:5 social default (1080x1920 for a story)
"pad": 96, // safe-area inset
"justify": "center"|"start"|"end"|"between", // vertical placement of the stack
"align": "start"|"center", // default horizontal alignment
"bg": { "color": } | { "gradient": [,...], "angle": } | { "image": },
"stack": [ Block, ... ], // main content, flows vertically
"overlay": [ { "anchor": , "block": Block } ], // pinned to a corner/edge/center
"free": [ { "at": { "x": , "y": } | { "region": , "dx": , "dy": },
"block": Block } ] // exact placement for decoration (off-canvas ok)
}
= top-left|top-right|bottom-left|bottom-right|top-center|bottom-center|center
Block (one of): TEXT: { "type": "text", "role": "display"|"title"|"body"|"eyebrow"|"credit", "color": , "text": "..." OR "runs": [ { "t": "...", "color": <color?>, "weight": <num?>, "italic": <bool?>, "underline": <bool?>, "strikethrough": <bool?>, "caps": <bool?> } ], "font": <family?>, // override the role font with any family (e.g. from search_fonts) "weight": <num?>, "tracking": <int?>, // thousandths of an em (160 = 0.16em) "autoWidth": <bool?>, // size the box to ONE line of content — the text (and any // panel) hugs its glyphs instead of filling the column; single-line "panel": { "color": , "opacity": <0..1>, "shape": "box"|"silhouetteRounded"|"callToAction" }? } SHAPE: { "type": "shape", "geo": "rectangle"|"roundedRectangle"|"circle"|"triangle"|"diamond"| "hexagon"|"pill"|"fivePointStar"|... , "w": , "h": , "fill": , "stroke": { "color": , "width": }?, "radius": <num?>, "shadow": { "x","y","blur","color","opacity" }? } IMAGE: { "type": "image", "url": , "w": , "h": , "fit": "cover"|"contain", "radius": <num?>, // a placed photo card / band (not full-bleed) "stroke": { "color": , "width": }?, "logo": <bool?> } // logo: true = brand mark GROUP: { "type": "group", "w": , "h": , "layout": "stack"|"row"|"grid", "children": [ Block, ... ] } // moves/rotates as one unit (e.g. a pill = shape + text) ROW: { "type": "row", "gap": <num?>, "justify": "start"|"center"|"end", "align": "top"|"middle"|"bottom", "children": [ Block, ... ] } GRID: { "type": "grid", "cols": , "gap": <num?>, "children": [ Block, ... ] } SPACE: { "type": "space", "h": } // vertical spacer in a stack
Any block also accepts UNIVERSAL props: "rotate": , "opacity": <0..1>, "z": (higher z paints later / on top; use negative z for background decoration).
= | { "gradient": [,...], "angle": } = a brand color token from get_brand_kit ("primary", "accent", …, plus "paper" and "ink", which always exist) or any hex such as "#FF006E". Tokens keep the design in the brand palette.
RULES:
"role" picks the font automatically (display/title = title font; body/eyebrow/credit = body font). Only set "font" when you deliberately want a different family.
Use "runs" to color one or two key words with an accent color; highlighting more reduces the contrast.
"display" = short headline (about 9 words or fewer). "title" = medium. "body" = supporting copy.
"eyebrow" is ALL-CAPS small (brand mark / kicker / slide number) — usually an overlay (top-left = brand, top-right = "01 / 05").
Shapes, gradients, rotation and free placement are for art direction — accents, dividers, badges, framing. Keep the composition clean; don't clutter.
Per carousel slide, vary the bg for rhythm and ensure text contrasts its background. For legibility over a busy area, give text a "panel" (e.g. a dark box at ~0.55 opacity).
For a photo: use bg.image for a full-bleed background (get a URL from search_media or generate_image), or a placed "image" block for a card/band inside the layout. Over a photo, keep text in the safe area with high-contrast colors and a panel.
Keep on-image text short. The post caption is set separately.
Returns the design id, an editor URL, the element structure (with the aliases the design edit tools use, such as set_design_text and move_design_element), and a rendered preview of every slide. It always creates a new design.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"workspace_key": "<workspace_key>",
"dsl": "<dsl>"
},
"name": "compose_design"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| dsl | Yes | The design layout: { "frames": [ Frame, ... ] }. See the frame and block format in the tool description. | |
| title | No | Optional design title. Defaults to the first line of copy. | |
| workspace_key | Yes | Key of the workspace to act in. Call list_workspaces to see the workspaces you have access to and their keys. |