Blocks
Every Block in the core vocabulary, its content model, its parameters and the worked examples the registry carries — generated from the registry itself.
Everything below is read from the Block registry as this page renders. The parameter tables are the same schemas the validator enforces, and the examples are the ones each Block declares beside its own schema — so a document written from this page is one the engine accepts.
Two things to read the tables with:
- Every value is a string, because every parameter is an HTML attribute. The
Type column says what the value actually is — a colour, a length, a number,
an
asset://URI — which is the thing worth knowing. - A
*marks a required parameter. Everything else is optional, and where a default exists the Accepts column names it.
A Block's parameters are its whole surface. There is no escape into CSS, so anything not in one of these tables is not expressible — and asking for it is a rejection by name rather than a silent no-op.
<vf-background>
The canvas backdrop: always full-bleed, always behind everything, at most one per canvas. It takes no placement parameters because it has nowhere else to be. Note some Channels constrain it — Amazon's primary image requires pure white.
Takes no children and no text. Allowed inside <vf-canvas>. At most 1 per parent.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| kind * | enum | solid | gradient | Which family of background this is. "solid" needs color; "gradient" needs either stops, or both from and to. |
| color | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Fill color. Only for kind="solid". |
| from | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Gradient start color. Only for kind="gradient"; pair with "to". |
| to | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Gradient end color. Only for kind="gradient"; pair with "from". |
| angle | number | a bare number, no unit (0 to 360) | Gradient direction in degrees: 0 points up, 180 points down — the CSS convention. |
| stops | string | ^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:@(?:0|1|0?\.\d{1,3}))?\s+\d{1,3}%(?:\s*,\s*#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:@(?:0|1|0?\.\d{1,3}))?\s+\d{1,3}%)+$ | An explicit gradient stop list — a stop list like "#1e1b4b 0%, #4338ca 100%". Any colour may carry an alpha as "@0" to "@1" — "#000000@0" is transparent black, which is how a scrim fades out instead of ending on a visible edge. Use instead of from/to when the gradient needs more than two stops, off-centre positions, or a stop that fades out. |
<vf-background kind="solid" color="#0E1B4D"></vf-background><vf-background kind="gradient" from="#0E1B4D" to="#3B5BDB" angle="160"></vf-background><vf-brief>
Creative intent for this Design: what it is trying to do and what it must avoid. Never rendered — it carries no pixels — but versioned with the Design, diffed like everything else, and read by the agent on every turn. Write down the reasoning a later reader would otherwise have to reverse-engineer from the layout.
Structural — draws nothing. Takes child Blocks, not bare text. Allowed inside <vf-doc>. At most 1 per parent.
No parameters.
<vf-brief>
<vf-field name="intent">Frame 1 carries the conversion; lead with zero-config setup</vf-field>
<vf-field name="constraint">No pricing claims — Apple rejects them in screenshots</vf-field>
</vf-brief><vf-canvas>
One rendered surface, at an exact pixel size. Take the size from a Channel preset rather than width/height wherever one exists — the preset also carries the safe area, which is the region the platform guarantees will not be cropped or covered by its own chrome.
Structural — draws nothing. Takes child Blocks, not bare text. Allowed inside <vf-doc>.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| preset | string | ^[A-Z][A-Z0-9_]*$ | A Channel preset id such as APP_STORE_6_9, supplying both the exact pixel size and the platform's safe area. Prefer this over width/height: the two are mutually exclusive, and a preset is what makes the design correct for where it ships. |
| width | integer | a bare whole number, no unit (1 to 20000) | Canvas width in pixels. Only for sizes no preset covers; must be given with height. |
| height | integer | a bare whole number, no unit (1 to 20000) | Canvas height in pixels. Only for sizes no preset covers; must be given with width. |
| locale | string | ^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$ — defaults to en-US | BCP-47 locale for this canvas. Also sets text direction: Arabic, Hebrew, Persian and Urdu render right-to-left. |
| padding | string | ^(?:safe|-?\d+(?:\.\d+)?(?:px|%)?)$ — defaults to safe | Inset for flowing children. "safe" uses the preset's safe area — the region guaranteed free of platform chrome and cropping — which is almost always what you want; on a canvas sized by hand, where there is no preset and so no safe area, it is a proportional default margin instead. A length overrides either uniformly, and "0" turns it off. |
| align-y | enum | start | center | end | between — defaults to start | How flowing children are distributed down the canvas. Absolutely placed Blocks ignore it. |
| mode | enum | fixed | flowing | paged — defaults to fixed | The shape of the surface. "fixed" is an exact W×H, which is what every store and feed placement wants. "flowing" fixes the width and lets the height follow the content — a commerce detail page. "paged" is not renderable yet. |
<vf-canvas preset="APP_STORE_6_9" locale="en-US" align-y="center"></vf-canvas><vf-doc>
The document root. Every vf-HTML document is exactly one <vf-doc> containing exactly one <vf-canvas>. It draws nothing itself.
Structural — draws nothing. Takes child Blocks, not bare text.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| studio | string | ^[a-z][a-z0-9-]*$ — defaults to core | Which Studio authored this document. "core" means the common Blocks only. |
| spec-version | enum | 1 — defaults to 1 | The vf-HTML format version this document is written against. |
<vf-doc studio="core" spec-version="1">
<vf-canvas preset="APP_STORE_6_9" locale="en-US">
<vf-background kind="solid" color="#0E1B4D"></vf-background>
</vf-canvas>
</vf-doc><vf-field>
One named piece of off-canvas text, holding one field of the design's brief. Its content is the element's text.
Structural — draws nothing. Takes text, not child Blocks. Allowed inside <vf-brief>.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| name * | string | ^[a-z][a-z0-9-]*$ | What this field holds. Conventional names are "intent", "audience", "constraint" and "rationale", but the set is open — a Studio may expect its own. |
<vf-group>
A frame that composes. Children position themselves against the group rather than the canvas, so a device mock or an illustration moves, rotates and scales as one unit instead of one setParam per part — and with clip, children are cropped to the group's shape. Use vf-stack to distribute things along an axis; use vf-group to assemble a thing.
Takes child Blocks, not bare text.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| clip | boolean | true | false | Crop children to the group's box. This is how a highlight is masked to a silhouette instead of being hand-computed to stop at the right pixel. |
| radius | number | a bare number, no unit (0 to 1000) | Corner radius, in px. With clip, children are cropped to the rounded shape. |
| fill | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Optional background behind the group's children. |
| shadow | enum | none | sm | md | lg | xl — defaults to none | Drop shadow, as a named elevation: "sm" through "xl". Lifts a panel or card off the surface behind it — the thing fade cannot do for a rectangle. |
| shadow-color | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Tints the shadow. A neutral shadow on a saturated ground reads as dirt; tinting toward the backdrop keeps a lifted card in the same picture as everything else. |
| gradient | string | ^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:@(?:0|1|0?\.\d{1,3}))?\s+\d{1,3}%(?:\s*,\s*#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:@(?:0|1|0?\.\d{1,3}))?\s+\d{1,3}%)+$ | A gradient fill, as a stop list like "#1e1b4b 0%, #4338ca 100%". Any colour may carry an alpha as "@0" to "@1" — "#000000@0" is transparent black, which is how a scrim fades out instead of ending on a visible edge. Overrides fill when both are set. |
| gradient-kind | enum | linear | radial — defaults to linear | Whether the gradient runs along a line or out from the centre. Radial is how you make a glow or a vignette. |
| gradient-angle | number | a bare number, no unit (0 to 360) | Direction of a linear gradient in degrees: 0 points up, 180 points down. |
| scale | number | a bare number, no unit (0.01 to 10) | Uniform scale about the group's centre. Scales the whole composition, not each child. |
| blur | number | a bare number, no unit (0 to 200) | Blur radius in px, applied to this Block's own content. This is depth of field: a photograph pushed out of focus so type can sit on it, or an element receding behind the subject. Note that the Block's edges soften too — a full-bleed image blurred at the canvas edge will show the page through the softened border, so oversize it past the edge and set bleed. |
| backdrop-blur | number | a bare number, no unit (0 to 200) | Blur radius in px, applied to whatever is painted *behind* this Block while the Block itself stays sharp — the frosted panel. Needs something translucent in front of it to be visible at all: pair it with a fill carrying an alpha, or with opacity, or the panel simply covers what it blurred. |
| opacity | number | a bare number, no unit (0 to 1) | Opacity of the group as a whole, composited once rather than per child. |
| x | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Horizontal position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Coordinates are relative to the nearest enclosing <vf-group>, or to the canvas when there is none — and a percentage resolves against that same frame, not always the canvas. Which point of the Block x/y name is set by "anchor". |
| y | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Vertical position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Relative to the nearest enclosing <vf-group>, or to the canvas when there is none. Which point of the Block x/y name is set by "anchor". |
| w | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Width, in px or as a percentage of the parent. |
| h | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Height, in px or as a percentage of the parent. |
| bleed | boolean | true | false | Declare that this Block is meant to run past the safe area — a full-width band, a glow spilling off a corner. Nothing then remarks on it. Say it deliberately: the safe area is the region the destination keeps clear of its own chrome and its own crop, so an element that reaches the edge by accident is the one a platform cuts through, and this is how you say yours does not. |
| anchor | enum | top-left | top | top-right | left | center | right | bottom-left | bottom | bottom-right — defaults to top-left | Which point of this Block the x/y coordinates refer to. Default "top-left" matches CSS; "center" is usually what you want for a centred element, since it removes the need to subtract half the element's own size. Ignored when the Block is flowing. |
| rotate | number | a bare number, no unit (-360 to 360) | Rotation in degrees, clockwise, about the Block's centre. |
<vf-group x="50%" y="55%" anchor="center" w="600" h="900" rotate="-6">
<vf-shape kind="rect" fill="#1E293B" x="0" y="0" w="600" h="900" radius="64"></vf-shape>
<vf-shape kind="rect" fill="#38BDF8" x="60" y="80" w="480" h="200" radius="16"></vf-shape>
</vf-group><vf-group x="700" y="300" w="420" h="1100" radius="190" clip="true">
<vf-shape kind="rect" fill="#98A4B4" x="0" y="0" w="420" h="1100"></vf-shape>
<vf-shape kind="rect" fill="#FFFFFF" opacity="0.35" x="-40" y="0" w="120" h="1100"></vf-shape>
</vf-group><vf-image>
A picture drawn from a Project asset. The only way real screenshots, photography and logo files enter a Design.
Takes no children and no text.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| src * | asset-uri | asset://path/into/project-assets.png — never http, file or data | An asset:// URI into the owning Project's Assets. Real product imagery is source material and is never synthesized, so there is no path here that can reach the network — upload the file first, then reference it. |
| alt | string | — — defaults to | Alternative text, carried into live HTML exports. |
| fit | enum | cover | contain | fill — defaults to contain | How the image fills its box when the aspect ratios differ. "contain" fits it whole, "cover" crops to fill, "fill" stretches — "fill" distorts and is almost never what a product screenshot wants. |
| radius | number | a bare number, no unit (0 to 1000) | Corner radius in px. |
| opacity | number | a bare number, no unit (0 to 1) | Opacity from 0 to 1. |
| blur | number | a bare number, no unit (0 to 200) | Blur radius in px, applied to this Block's own content. This is depth of field: a photograph pushed out of focus so type can sit on it, or an element receding behind the subject. Note that the Block's edges soften too — a full-bleed image blurred at the canvas edge will show the page through the softened border, so oversize it past the edge and set bleed. |
| blend | enum | normal | multiply | screen — defaults to normal | How this Block composites with what is already painted beneath it. "multiply" drops the light ground out of artwork that arrived baked onto one — ink, a brushed headline, a paper grain — so it reads as marks on the page rather than as a rectangle laid over it. "screen" does the same for light marks on a dark ground. Only meaningful when something is underneath. Note what multiply actually does: it keeps the darker of the two, so it erases the artwork's ground only where that ground is *white*. Artwork on a cream or grey ground darkens the page into a visible rectangle instead — so when you commission or generate the asset, ask for pure white, and reach for "normal" if you cannot get it. |
| x | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Horizontal position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Coordinates are relative to the nearest enclosing <vf-group>, or to the canvas when there is none — and a percentage resolves against that same frame, not always the canvas. Which point of the Block x/y name is set by "anchor". |
| y | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Vertical position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Relative to the nearest enclosing <vf-group>, or to the canvas when there is none. Which point of the Block x/y name is set by "anchor". |
| w | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Width, in px or as a percentage of the parent. |
| h | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Height, in px or as a percentage of the parent. |
| bleed | boolean | true | false | Declare that this Block is meant to run past the safe area — a full-width band, a glow spilling off a corner. Nothing then remarks on it. Say it deliberately: the safe area is the region the destination keeps clear of its own chrome and its own crop, so an element that reaches the edge by accident is the one a platform cuts through, and this is how you say yours does not. |
| anchor | enum | top-left | top | top-right | left | center | right | bottom-left | bottom | bottom-right — defaults to top-left | Which point of this Block the x/y coordinates refer to. Default "top-left" matches CSS; "center" is usually what you want for a centred element, since it removes the need to subtract half the element's own size. Ignored when the Block is flowing. |
| rotate | number | a bare number, no unit (-360 to 360) | Rotation in degrees, clockwise, about the Block's centre. |
<vf-image src="asset://art/headline.png" blend="multiply" fit="contain" x="50%" y="18%" anchor="center" w="80%"></vf-image><vf-image src="asset://screens/home.png" fit="contain" x="50%" y="55%" anchor="top" w="72%" radius="24"></vf-image><vf-shape>
A rectangle or ellipse. Fills flat, with a gradient, or with a soft fade to nothing — reach for fade rather than a low opacity when you want a glow, because a translucent disc still has an edge. No intrinsic size, so w and h are required: without them it would render as a zero-pixel no-op, which is far more confusing than an error.
Takes no children and no text.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| kind | enum | rect | ellipse — defaults to rect | Which primitive to draw. "ellipse" ignores radius and rounds fully. |
| fill | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Fill color. A shape needs a fill, a stroke, or both. |
| gradient | string | ^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:@(?:0|1|0?\.\d{1,3}))?\s+\d{1,3}%(?:\s*,\s*#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})(?:@(?:0|1|0?\.\d{1,3}))?\s+\d{1,3}%)+$ | A gradient fill, as a stop list like "#1e1b4b 0%, #4338ca 100%". Any colour may carry an alpha as "@0" to "@1" — "#000000@0" is transparent black, which is how a scrim fades out instead of ending on a visible edge. Overrides fill when both are set. |
| gradient-kind | enum | linear | radial — defaults to linear | Whether the gradient runs along a line or out from the centre. Radial is how you make a glow or a vignette. |
| gradient-angle | number | a bare number, no unit (0 to 360) | Direction of a linear gradient in degrees: 0 points up, 180 points down. |
| fade | number | a bare number, no unit (0 to 1) | How much of the shape's radius is spent fading out to nothing, from 0 (a hard edge) to 1 (fading from the centre). This is how a glow is made — a translucent disc has an edge, and the edge is what reads as a mistake. |
| stroke | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Border color; pair with stroke-width, which defaults to 0. |
| stroke-width | number | a bare number, no unit (0 to 200) | Border thickness in px. A stroke with width 0 draws nothing. |
| radius | number | a bare number, no unit (0 to 1000) | Corner radius in px, for kind="rect". |
| shadow | enum | none | sm | md | lg | xl — defaults to none | Drop shadow, as a named elevation: "sm" through "xl". Lifts a panel or card off the surface behind it — the thing fade cannot do for a rectangle. |
| shadow-color | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Tints the shadow. A neutral shadow on a saturated ground reads as dirt; tinting toward the backdrop keeps a lifted card in the same picture as everything else. |
| opacity | number | a bare number, no unit (0 to 1) | Opacity from 0 to 1. Useful for scrims behind text over busy imagery. |
| blur | number | a bare number, no unit (0 to 200) | Blur radius in px, applied to this Block's own content. This is depth of field: a photograph pushed out of focus so type can sit on it, or an element receding behind the subject. Note that the Block's edges soften too — a full-bleed image blurred at the canvas edge will show the page through the softened border, so oversize it past the edge and set bleed. |
| backdrop-blur | number | a bare number, no unit (0 to 200) | Blur radius in px, applied to whatever is painted *behind* this Block while the Block itself stays sharp — the frosted panel. Needs something translucent in front of it to be visible at all: pair it with a fill carrying an alpha, or with opacity, or the panel simply covers what it blurred. |
| blend | enum | normal | multiply | screen — defaults to normal | How this Block composites with what is already painted beneath it. "multiply" drops the light ground out of artwork that arrived baked onto one — ink, a brushed headline, a paper grain — so it reads as marks on the page rather than as a rectangle laid over it. "screen" does the same for light marks on a dark ground. Only meaningful when something is underneath. Note what multiply actually does: it keeps the darker of the two, so it erases the artwork's ground only where that ground is *white*. Artwork on a cream or grey ground darkens the page into a visible rectangle instead — so when you commission or generate the asset, ask for pure white, and reach for "normal" if you cannot get it. |
| x | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Horizontal position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Coordinates are relative to the nearest enclosing <vf-group>, or to the canvas when there is none — and a percentage resolves against that same frame, not always the canvas. Which point of the Block x/y name is set by "anchor". |
| y | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Vertical position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Relative to the nearest enclosing <vf-group>, or to the canvas when there is none. Which point of the Block x/y name is set by "anchor". |
| w | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Width, in px or as a percentage of the parent. |
| h | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Height, in px or as a percentage of the parent. |
| bleed | boolean | true | false | Declare that this Block is meant to run past the safe area — a full-width band, a glow spilling off a corner. Nothing then remarks on it. Say it deliberately: the safe area is the region the destination keeps clear of its own chrome and its own crop, so an element that reaches the edge by accident is the one a platform cuts through, and this is how you say yours does not. |
| anchor | enum | top-left | top | top-right | left | center | right | bottom-left | bottom | bottom-right — defaults to top-left | Which point of this Block the x/y coordinates refer to. Default "top-left" matches CSS; "center" is usually what you want for a centred element, since it removes the need to subtract half the element's own size. Ignored when the Block is flowing. |
| rotate | number | a bare number, no unit (-360 to 360) | Rotation in degrees, clockwise, about the Block's centre. |
<vf-shape kind="rect" fill="#000000" opacity="0.45" x="0" y="0" w="100%" h="42%"></vf-shape><vf-shape kind="ellipse" fill="#3B5BDB" x="50%" y="12%" anchor="center" w="120" h="120"></vf-shape><vf-shape kind="ellipse" fill="#7FA6F5" fade="0.85" opacity="0.5" x="70%" y="60%" anchor="center" w="620" h="620"></vf-shape><vf-shape kind="rect" gradient="#1E293B 0%, #0F172A 100%" gradient-angle="150" radius="24" x="112" y="300" w="620" h="360"></vf-shape><vf-shape kind="rect" gradient="#0B1A0F@0 0%, #0B1A0F@0.75 100%" gradient-angle="180" bleed="true" x="0" y="60%" w="100%" h="40%"></vf-shape><vf-stack>
A flexbox row or column. The way to lay several Blocks out relative to each other instead of positioning each one absolutely — which is what keeps a layout intact when a translated string grows. Parameter names are shortened from their CSS equivalents: direction, align, justify.
Takes child Blocks, not bare text.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| direction | enum | column | row — defaults to column | Main axis. Equivalent to CSS flex-direction, but the parameter is named "direction". |
| gap | number | a bare number, no unit (0 to 2000) | Space between children, in px, as a bare number — not a CSS length, so no unit suffix. |
| align | enum | start | center | end | stretch — defaults to stretch | Cross-axis alignment. CSS align-items, with the flex- prefixes dropped: write "start", not "flex-start". |
| justify | enum | start | center | end | between | around — defaults to start | Main-axis distribution. CSS justify-content with shortened names: "between", not "space-between". |
| padding | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" — defaults to 0 | Inner padding, one value applied to all four sides. CSS shorthands are not accepted. |
| wrap | boolean | true | false | Whether children wrap onto further lines. |
| x | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Horizontal position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Coordinates are relative to the nearest enclosing <vf-group>, or to the canvas when there is none — and a percentage resolves against that same frame, not always the canvas. Which point of the Block x/y name is set by "anchor". |
| y | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Vertical position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Relative to the nearest enclosing <vf-group>, or to the canvas when there is none. Which point of the Block x/y name is set by "anchor". |
| w | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Width, in px or as a percentage of the parent. |
| h | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Height, in px or as a percentage of the parent. |
| bleed | boolean | true | false | Declare that this Block is meant to run past the safe area — a full-width band, a glow spilling off a corner. Nothing then remarks on it. Say it deliberately: the safe area is the region the destination keeps clear of its own chrome and its own crop, so an element that reaches the edge by accident is the one a platform cuts through, and this is how you say yours does not. |
| anchor | enum | top-left | top | top-right | left | center | right | bottom-left | bottom | bottom-right — defaults to top-left | Which point of this Block the x/y coordinates refer to. Default "top-left" matches CSS; "center" is usually what you want for a centred element, since it removes the need to subtract half the element's own size. Ignored when the Block is flowing. |
| rotate | number | a bare number, no unit (-360 to 360) | Rotation in degrees, clockwise, about the Block's centre. |
<vf-stack direction="column" gap="24" align="center" padding="48">
<vf-text role="title" align="center">Track every launch</vf-text>
<vf-text role="subtitle" align="center">Every store, one dashboard</vf-text>
</vf-stack><vf-text>
A run of text. Its content is the element's text, not an attribute. Long copy wraps rather than truncating — the layout adapts to the string, never the other way round, which is what keeps a German translation from silently losing words. Prefer setting "role" over setting size and weight by hand.
Takes text, not child Blocks.
| Parameter | Type | Accepts | What it does |
|---|---|---|---|
| role | enum | title | subtitle | body | caption — defaults to body | What this text is in the composition. It supplies the type scale — size, weight and line height — so setting those explicitly is rarely needed and flattens the scale across a set when overused. Choose the role first; override only when the design genuinely departs from it. |
| family | enum | sans | serif | display | modern | condensed | mono — defaults to sans | Which bundled typeface to set this text in. The list is closed and the files are bundled: a family with no face behind it would be resolved against whatever fonts the rendering machine has, which is the silent fallback the whole face set exists to close. "sans" — The workhorse — a neutral grotesque, metric-compatible with Arial. In Chinese it is 黑体. "serif" — The literary or editorial register, metric-compatible with Times. In Chinese it is 宋体, which is the difference between a 黑体 and a 宋体 poster. "display" — A high-contrast display serif for one large line — a headline that is the whole composition. Thin strokes disappear at caption size, so it is the wrong choice for body copy. Chinese runs set in 宋体 beside it. "modern" — A contemporary screen grotesque: larger x-height, tighter spacing, numerals that line up in a column. The one to reach for when a design should read as software rather than as print — a metric, a price, a dashboard. "condensed" — Tall, narrow, all-caps — the voice of a sports poster or a promotion. It has one weight and no italic, and lower-case letters draw as capitals. Latin only in practice: its Chinese runs fall to 黑体, which is not condensed. "mono" — Fixed width, for anything that has to line up down the page — a code sample, a ticket number, a serial. Rarely what marketing copy wants. Every family sets Chinese, Korean and Japanese as well as Latin. |
| size | number | a bare number, no unit (1 to 2000) | Font size in px. Overrides the size the role would supply. |
| weight | enum | 400 | 700 | Font weight. Only 400 and 700 exist: the renderer bundles exactly two faces, and any other value would be a synthesized weight that renders differently across Chromium builds. |
| italic | boolean | true | false | Set the run in the bundled italic face. Latin only — no italic Chinese face exists to bundle, so a Chinese run asked to slant would be slanted by the browser rather than drawn, and the synthesized-style check warns about that by name. Use a different weight or family for emphasis in Chinese. |
| line-height | number | a bare number, no unit (0.5 to 4) | Line height as a multiple of the font size. Overrides the role's value. |
| color | color | #rgb or #rrggbb — no alpha, no rgb(), no color names — defaults to #000000 | Text color. |
| align | enum | left | center | right — defaults to left | Horizontal text alignment. |
| letter-spacing | number | a bare number, no unit (-20 to 100) | Letter spacing in px. Negative values tighten. |
| max-width | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Maximum line length before wrapping, in px or as a percentage. The usual way to control where a headline breaks. Named for the horizontal case but defined as *line length*, so in a vertical run it caps how far down a column reaches. |
| vertical | boolean | true | false | Set the run as a vertical column: characters read top to bottom, and successive columns run right to left, as Chinese and Japanese typesetting do. Not a rotation — the glyphs stay upright, punctuation takes its vertical forms, and a Latin word inside the column lies on its side, which is the convention. Everything else keeps its meaning: max-width still caps line length, and align still runs from the start of the column. |
| wrap | enum | auto | balance | pretty | none — defaults to auto | How lines are broken. "balance" evens out the line lengths of a short heading — usually what hand-tuning max-width is trying to achieve. "pretty" only avoids leaving one word alone on the last line. "none" refuses to wrap at all. For a specific break use , to keep two words together use , and to permit one inside a long word use ­. |
| transform | enum | none | uppercase — defaults to none | Case transformation applied at render time; the text content itself is unchanged. |
| bg | color | #rgb or #rrggbb — no alpha, no rgb(), no color names | Background colour behind the text. Use this rather than a shape plus a separately placed label: a chip built from two Blocks falls out of flow layout, and flow is what survives a long translation. |
| bg-opacity | number | a bare number, no unit (0 to 1) | Opacity of the background alone, leaving the text fully opaque. |
| pad | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" — defaults to 0 | Inner padding around the text, one value on all four sides. Only meaningful with bg. |
| radius | number | a bare number, no unit (0 to 1000) | Corner radius of the background in px. |
| x | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Horizontal position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Coordinates are relative to the nearest enclosing <vf-group>, or to the canvas when there is none — and a percentage resolves against that same frame, not always the canvas. Which point of the Block x/y name is set by "anchor". |
| y | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Vertical position, in px or as a percentage. Supplying x or y switches this Block from flowing inside its parent to absolute positioning within the canvas. Omit both to let it flow. Relative to the nearest enclosing <vf-group>, or to the canvas when there is none. Which point of the Block x/y name is set by "anchor". |
| w | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Width, in px or as a percentage of the parent. |
| h | length | 120, 120px or 38% — a single value, never a CSS shorthand like "10px 20px" | Height, in px or as a percentage of the parent. |
| bleed | boolean | true | false | Declare that this Block is meant to run past the safe area — a full-width band, a glow spilling off a corner. Nothing then remarks on it. Say it deliberately: the safe area is the region the destination keeps clear of its own chrome and its own crop, so an element that reaches the edge by accident is the one a platform cuts through, and this is how you say yours does not. |
| anchor | enum | top-left | top | top-right | left | center | right | bottom-left | bottom | bottom-right — defaults to top-left | Which point of this Block the x/y coordinates refer to. Default "top-left" matches CSS; "center" is usually what you want for a centred element, since it removes the need to subtract half the element's own size. Ignored when the Block is flowing. |
| rotate | number | a bare number, no unit (-360 to 360) | Rotation in degrees, clockwise, about the Block's centre. |
<vf-text role="title" align="center" color="#FFFFFF" max-width="80%">Track every launch</vf-text><vf-text role="caption" bg="#1E3A8A" pad="16" radius="8" color="#DBEAFE">New</vf-text><vf-text role="caption" x="50%" y="88%" anchor="center" color="#94A3B8">No account needed</vf-text><vf-text role="title" italic="true" weight="700" letter-spacing="-1" x="112" y="1334">10.02</vf-text><vf-text role="subtitle" family="serif" vertical="true" x="120" y="900" color="#1A1A1A">三伏未尽</vf-text>What gets refused
Every rejection code, the reserved attributes no Block declares, the budgets a document lives inside, and why refusals are structured.
Commands
Every command that can change a document, with its input schema — generated from the command registry the editor, the assistant and the MCP endpoint all share.