Elements
Every element sits in a normalized box on the 16:9 canvas. Seven built-in types exist; free HTML or SVG is not allowed, because deck content reaches audience phones.
Common element fields
| Field | Type | Rules |
|---|---|---|
id | string | [A-Za-z0-9_-]{1,40}, unique in the slide. Effects (ripple, focus, zoom) target it. |
type | "text" | "image" | "shape" | "qr" | "icon" | "chart" | "decor" | Discriminator. No other types: free HTML or SVG is not allowed. |
box | { x, y, w, h } | Normalized 0..1 on the 16:9 canvas, origin top-left. x + w <= 1, y + h <= 1. |
fragment | integer 1–20 | Optional. Element appears at that step; absent = always visible. |
text
text: string, max 2000.\nbreaks lines.style(optional, all optional):fontSize8–400 (logical px on 1920x1080)fontWeight400 | 500 | 600 | 700 | 800font"display"|"body"|"mono"italicbooleancolorhexalign"left"|"center"|"right"valign"top"|"middle"|"bottom"lineHeight0.8–3backgroundhex (card fill)radius0–540 (px)padding0–200 (px)cardboolean: draws the preset card (surface color, radius, border, shadow). Do not combine withbackgroundorradius; let the preset decide.uppercasebooleantracking-0.05–0.3 (letter spacing in em; negative tightens big display type, positive opens small caps labels)markboolean: accent highlight underline behind the text. Use on one short phrase per slide.
image
src:https://…orassets/<path>(chars[A-Za-z0-9_\-./], no.., max 500). Local files live indecks/<id>/assets/; the CLI fails if the file is missing.alt: string, required, max 300.fit:"contain"|"cover"(optional).style: only{ radius }.
shape
shape:"rect"|"ellipse"|"line". A horizontal line usesh: 0.style(optional):fillhex,strokehex,strokeWidth0–40,radius0–540.
qr
Renders the session join QR and URL at runtime. No payload.
style(optional): onlycolorandbackground(hex). Use a light background with dark color for scanability.- Put one on slide 1. Keep it at least 0.25 wide and roughly square on screen (
h ≈ w × 16/9).
icon
A curated Lucide icon. The authoritative list is ICON_NAMES in shared/icons.ts (~80 kebab-case names); any other name fails validation. Check the file when unsure.
name: anICON_NAMESentry, e.g."rocket".style(optional):colorhex,backgroundhex (a filled tile behind the icon),strokeWidth1–3,radiuspx (rounds the background tile).- Default color: the preset accent, or the text color when the accent is too faint on its ground (under 3:1, e.g. yellow on light paper in
brutalista). Setcoloronly to force a specific hue. - Keep the box roughly square on screen:
h ≈ w × 16/9(e.g.w: 0.08, h: 0.142).
Representative names (verify against ICON_NAMES):
| Meaning | Names |
|---|---|
| People and talk | users, user, message-circle, heart, smile, thumbs-up, hand |
| Ideas and goals | lightbulb, target, rocket, sparkles, trophy, flag |
| Data and growth | bar-chart-3, trending-up, trending-down, pie-chart, database |
| Safety | shield-check, lock, key, alert-triangle, check-circle |
| Time and place | clock, calendar, map-pin, globe |
| Tech and work | code, cpu, cloud, zap, settings, book-open, graduation-cap |
chart
Simple data chart rendered as SVG. Use it when the content has 2–8 real numbers; never invent data.
kind:"bar"|"donut".data: array of{ "label": string (max 40 chars), "value": number >= 0 }. Bar: 1–8 points, one series. Donut: 2–6 slices.unit(optional): string, max 8 chars, appended to values ("%"," h","k").style(optional): onlycolorhex (bar color; default accent). Donut uses the preset's categorical palette in fixed order.- Bar shows value labels on the bars and no legend. Donut shows a legend with values and the total in the center.
- Give it room: at least
w: 0.4, h: 0.5.
decor
Built-in decorative SVG shape. It carries no content: never put meaning in decor.
shape:"blob"|"wave"|"dots"|"rings"|"arc"|"squiggle"|"star"|"grid".style(optional):colorhex (default accent),opacity0.05–1.- Place it before text in
elementsso it draws behind; keep it off the text, usually hugging a corner or an edge (boxes cannot leave the canvas). One or two per slide at most.