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.
<e9-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 <e9-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. |
<e9-background kind="solid" color="#0E1B4D"></e9-background><e9-background kind="gradient" from="#0E1B4D" to="#3B5BDB" angle="160"></e9-background><e9-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 <e9-doc>. At most 1 per parent.
No parameters.
<e9-brief>
<e9-field name="intent">Frame 1 carries the conversion; lead with zero-config setup</e9-field>
<e9-field name="constraint">No pricing claims — Apple rejects them in screenshots</e9-field>
</e9-brief><e9-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 <e9-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. |
<e9-canvas preset="APP_STORE_6_9" locale="en-US" align-y="center"></e9-canvas><e9-doc>
The document root. Every e9-HTML document is exactly one <e9-doc> containing exactly one <e9-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 | 3 — defaults to 3 | The e9-HTML format version this document is written against. |
<e9-doc studio="core" spec-version="3">
<e9-canvas preset="APP_STORE_6_9" locale="en-US">
<e9-background kind="solid" color="#0E1B4D"></e9-background>
</e9-canvas>
</e9-doc><e9-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 <e9-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. |
<e9-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 e9-stack to distribute things along an axis; use e9-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 <e9-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 <e9-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. |
<e9-group x="50%" y="55%" anchor="center" w="600" h="900" rotate="-6">
<e9-shape kind="rect" fill="#1E293B" x="0" y="0" w="600" h="900" radius="64"></e9-shape>
<e9-shape kind="rect" fill="#38BDF8" x="60" y="80" w="480" h="200" radius="16"></e9-shape>
</e9-group><e9-group x="700" y="300" w="420" h="1100" radius="190" clip="true">
<e9-shape kind="rect" fill="#98A4B4" x="0" y="0" w="420" h="1100"></e9-shape>
<e9-shape kind="rect" fill="#FFFFFF" opacity="0.35" x="-40" y="0" w="120" h="1100"></e9-shape>
</e9-group><e9-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 <e9-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 <e9-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. |
<e9-image src="asset://art/headline.png" blend="multiply" fit="contain" x="50%" y="18%" anchor="center" w="80%"></e9-image><e9-image src="asset://screens/home.png" fit="contain" x="50%" y="55%" anchor="top" w="72%" radius="24"></e9-image><e9-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 <e9-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 <e9-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. |
<e9-shape kind="rect" fill="#000000" opacity="0.45" x="0" y="0" w="100%" h="42%"></e9-shape><e9-shape kind="ellipse" fill="#3B5BDB" x="50%" y="12%" anchor="center" w="120" h="120"></e9-shape><e9-shape kind="ellipse" fill="#7FA6F5" fade="0.85" opacity="0.5" x="70%" y="60%" anchor="center" w="620" h="620"></e9-shape><e9-shape kind="rect" gradient="#1E293B 0%, #0F172A 100%" gradient-angle="150" radius="24" x="112" y="300" w="620" h="360"></e9-shape><e9-shape kind="rect" gradient="#0B1A0F@0 0%, #[email protected] 100%" gradient-angle="180" bleed="true" x="0" y="60%" w="100%" h="40%"></e9-shape><e9-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 <e9-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 <e9-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. |
<e9-stack direction="column" gap="24" align="center" padding="48">
<e9-text role="title" align="center">Track every launch</e9-text>
<e9-text role="subtitle" align="center">Every store, one dashboard</e9-text>
</e9-stack><e9-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. |
| font | string[] | — — defaults to Liberation Sans | Which bundled faces to set this run in, in order — a list, the way a CSS font-family is, resolved per glyph with the first match winning. Name one face for a single-script run and two when a run mixes scripts: font="Montserrat, 马善政毛笔楷书" sets the Latin in Montserrat and the Chinese in a brush. Any script no named face serves is completed with the shared 黑体 or 宋体, so a Latin-only list still renders Chinese. The list is closed and the files are bundled: a name with no file behind it would be resolved against whatever fonts the rendering machine has, which is the silent fallback the whole face set exists to close. The note beside each one says what it is for, which is the decision actually in front of you — a name you have read a lot about is not the same as the right face for this line. "Liberation Sans" — The workhorse — a neutral grotesque, metric-compatible with Arial, which is what font="Arial" resolves to. In Chinese it is 黑体. "Liberation Serif" — The literary or editorial register, metric-compatible with Times, which is what font="Times New Roman" resolves to. In Chinese it is 宋体, which is the difference between a 黑体 and a 宋体 poster. "Liberation Mono" — The typewriter monospace, metric-compatible with Courier New — a slab-serifed fixed width, where JetBrains Mono is the screen one. Reach for it when the design should read as a document, a manuscript or a form rather than as code. Latin only: name 思源等宽, 본고딕 등폭 or 源ノ角ゴシック等幅 beside it for a CJK column that lines up too. "Playfair 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. "Inter" — 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. "Bebas Neue" — 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. "JetBrains 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. Latin only: name 思源等宽, 본고딕 등폭 or 源ノ角ゴシック等幅 beside it for a CJK column that lines up too. "Montserrat" — A geometric sans built on the circle — even, wide, friendly at a large size and the default voice of a modern brand deck. Set beside 黑体 in Chinese. "Nunito" — A soft-cornered sans: warmth without a script's informality, the register a food, family or wellness brand reaches for. Latin only — name M PLUS Rounded 1c beside it to keep the softness in Japanese. "Roboto Slab" — A slab serif — the sturdy, mechanical register of a ticket, a badge or a headline that wants weight without elegance. It has no italic. "Libre Baskerville" — A transitional serif drawn for reading at length: sturdier than a display serif, and the right choice when a paragraph rather than a headline is the point. 宋体 in Chinese. "Cormorant Garamond" — A high-contrast garamond — the fashion, editorial and invitation register, and the most delicate face here. Small sizes lose its thin strokes. 宋体 in Chinese, 명조 in Korean, 明朝 in Japanese. "Barlow Condensed" — A condensed grotesque that has a bold and an italic — the narrow face for a headline that has to fit, and the one to reach for where Bebas Neue's single weight is not enough. Chinese, Japanese and Korean fall to 黑体, which is not condensed. "Oswald" — The condensed gothic of a hundred thousand posters and page headers: tighter and more compact than Barlow Condensed, and heavier in colour on the page. No italic. CJK falls to 黑体, which is not condensed. "Poppins" — A geometric sans drawn on a true circle, with a tall x-height and even strokes — the most-set geometric on the web, and rounder and friendlier than Montserrat. 黑体 in Chinese. "DM Sans" — A low-contrast geometric sans made for interfaces and short copy: smaller apertures than Poppins, plainer than Montserrat. Optical size pinned at 9. 黑体 in Chinese. "Work Sans" — A grotesque optimised for the middle sizes a page is actually set in — plainer than Space Grotesk, warmer than Inter. 黑体 in Chinese. "Space Grotesk" — A grotesque with drawn quirks — a squared g, a flat-topped a — for a brand that wants a voice without reaching for a display face. No italic. 黑体 in Chinese. "Quicksand" — A rounded geometric sans with terminals cut square: gentler than Nunito and more geometric than either. No italic, and its Chinese, Japanese and Korean fall to 黑体 — the softness is Latin only. "Comfortaa" — A rounded display sans, wider and more decorative than Quicksand — a logotype face rather than a paragraph one. No italic. CJK falls to 黑体. "Chakra Petch" — A squared techno sans with clipped corners — motorsport, gaming, science fiction. Wider and far more readable than Orbitron, and it has an italic. CJK falls to 黑体. "Lora" — A contemporary serif with brushed curves — the workhorse for a paragraph that should read as considered rather than institutional. 宋体 in Chinese. "Merriweather" — A serif drawn for screens: large x-height, sturdy serifs, readable small. The choice when a long paragraph has to survive a phone. Optical size pinned at 18. 宋体 in Chinese. "EB Garamond" — A revival of Claude Garamont's sixteenth-century types — the old-style serif, lighter on the page than Libre Baskerville and more literary than either Liberation. 宋体 in Chinese. "Bodoni Moda" — A Didone with the full range: vertical stress and abrupt hairlines, the serif that reads as editorial and expensive. Optical size pinned at 11. 宋体 in Chinese. "Space Mono" — A fixed-width face with display quirks — a monospace chosen because it looks like one, for a label or a byline rather than a code block. CJK falls to 黑体, which is not fixed width. "IBM Plex Mono" — IBM's corporate monospace: warmer and more humanist than JetBrains Mono, with a drawn italic. Its CJK falls to 黑体 and does not line up — JetBrains Mono is the monospace whose Chinese, Japanese and Korean are fixed width too. "站酷小薇" — A light Chinese display serif (细宋) that sets Latin from the same design — narrow, high-waisted, the register of a poster with one vertical line of poetry. One weight, no italic, and Latin runs in it are the face's own rather than a Western serif beside it. Korean falls to 명조; like Ma Shan Zheng it cannot set Japanese kana, it draws no accented Latin, and it has no middle dot — so "café" and 玛丽·居里 are refusals rather than fallbacks. "Anton" — A poster gothic: narrow, very heavy, drawn for one line at the top of a page. One weight, because it was drawn once. Latin only — name 站酷庆科黄油体, 검은고딕 or Dela Gothic One beside it to keep a headline a headline in CJK. "Dancing Script" — A joined script with a light, informal bounce — a greeting, a signature, a seasonal line. One weight, and never for body copy: joined letterforms stop reading below a headline size. Latin only; 志莽行书, 나눔손글씨 펜 and Yomogi are the hands for CJK. "Caveat" — A casual unjoined hand, as if written with a pen rather than drawn — a note, a caption, a personal aside. Latin only: its CJK runs fall to 黑体, and "script" is the family that has a hand for them. "马善政毛笔楷书" — 毛笔楷书 — brush calligraphy with a regular script's structure, and it sets Latin from the same hand. The register a festival, a tea or a poster with a poem asks for. It draws no accented Latin, so "café" is a refusal rather than a fallback; 나눔손글씨 붓 and 佑字肅 are the brushes for Korean and Japanese. "Permanent Marker" — A felt-tip marker hand — flat, urgent, hand-lettered. It draws Latin only, so Chinese, Japanese and Korean runs in it fall to 黑体. "Orbitron" — A wide squared-off techno face for a game, a launch or a sci-fi headline. Latin, digits and very little else — a Chinese run in it is set in 黑体. "Fredoka" — A rounded display sans with a friendly, almost drawn warmth — children's, food, anything cheerful. One weight. Latin only; 站酷快乐体, 주아 and M PLUS Rounded 1c carry the same register in CJK. "Press Start 2P" — A bitmap pixel face at one size. It is a picture of a font as much as a font: 8-bit games, retro badges, anything meant to look rasterized. Draws Latin and digits only. "Archivo Black" — A very heavy grotesque at one weight — a headline that has to shout without a display face's mannerism. Where Anton is narrow, this is wide. CJK falls to 黑体. "Staatliches" — Condensed sans capitals at one weight, drawn after painted signage: posters, tickets, gig flyers. Capitals are the design; it has no lowercase to speak of. CJK falls to 黑体. "Bungee" — A signage face drawn to be stacked vertically as readily as set across — urban, dense, unmistakably a sign. One weight. CJK falls to 黑体. "Alfa Slab One" — A fat slab serif at one weight — circus poster, craft label, anything that wants weight and warmth at the same time. CJK falls to 宋体. "Abril Fatface" — A fat-face Didone: the fashion-magazine masthead, hairlines against very heavy stems. One line at size — the hairlines disappear below a headline. CJK falls to 宋体. "DM Serif Display" — A high-contrast display serif with an italic and no bold — a headline or a pull quote, never a paragraph. 宋体 in Chinese. "Lobster" — A bold connected script with the swashes of a shop sign — the heaviest script here and the one that survives at small size. CJK falls to 黑体. "Pacifico" — A brush script out of surf lettering: loose, joined, warm. One weight, and illegible in capitals. CJK falls to 黑体. "Great Vibes" — A formal joined script — wedding invitation, certificate, perfume label. Finer and more upright than Dancing Script. CJK falls to 黑体. "Amatic SC" — A hand-drawn face in tall narrow capitals — a chalkboard, a market stall, a handwritten price. Very condensed, and a whole paragraph of it is unreadable. CJK falls to 黑体. "VT323" — A terminal bitmap face at one weight, drawn after a DEC video terminal — a scanline, a command prompt, a countdown. Latin and digits; CJK falls to 黑体. "UnifrakturMaguntia" — Blackletter — the register of a brewery, a metal band or a diploma. Latin only, and unreadable at caption size; a whole line of it in capitals is unreadable at any size. "Roboto" — The most-set sans on the web, and Android's own: neutral, a little narrow, mixing straight-sided and circular letters. Where Inter is drawn for small sizes on a screen, this is the one a picture is most often already set in. 黑体 in Chinese. "Open Sans" — A humanist sans with open apertures and a tall x-height, drawn for a passage rather than a headline — the choice when body copy should be neutral and nothing else. 黑体 in Chinese. "Raleway" — An elegant geometric sans with a single-storey w and drawn numerals — a boutique, a lookbook, an invitation. Airy even at 400, so it wants letter-spacing and room. 黑体 in Chinese. "Rubik" — A geometric sans with slightly rounded corners: friendlier than Poppins, firmer than Nunito, and the face a product page or an app store screenshot is set in. 黑体 in Chinese. "Lato" — A humanist sans that is warm at text size and almost classical in the bold — the corporate-deck workhorse. It carries Greek and Cyrillic, which nothing else in this set outside the Liberation pair does. 黑体 in Chinese. "Black Ops One" — A stencil: heavy military lettering with bridges cut through the strokes. Army surplus, industrial, an esports poster. One weight, capitals do the work, and CJK falls to 黑体 — which is not stencilled. "Saira Stencil One" — A condensed stencil with narrow counters and fine bridges — the technical end of the register, where Black Ops One is the military one. One weight. CJK falls to 黑体. "Big Shoulders Stencil Display" — A tall, very condensed stencil for a headline that has to fit, and the only one of the three with a bold. CJK falls to 黑体. "Bungee Outline" — Bungee drawn as outlines only: each letter is a hollow line, so whatever sits behind it shows through. Over a photograph, or stacked on Bungee itself as a second layer. One weight, invisible at caption size, and CJK falls to 黑体. "Bungee Shade" — Bungee with the drop shadow drawn into the face — dimensional signage lettering in a single colour, with no effect to apply. Same skeleton as Bungee and Bungee Outline, so the three line up character for character. One weight, CJK falls to 黑体. "思源黑体" — 黑体 — the Chinese workhorse. The neutral sans a screen, a sign or a paragraph of body copy is set in, and the face any Latin sans sits beside without argument. "본고딕" — 본고딕 — the Korean workhorse sans, and what Korean body copy is set in unless a design says otherwise. "源ノ角ゴシック" — ゴシック体 — the Japanese workhorse sans, for body copy and for anything that has to stay neutral. "思源宋体" — 宋体 — the literary and editorial register, and the difference between a 黑体 poster and a 宋体 one. A book, a poem, a formal notice. "본명조" — 본명조 — the Korean serif, for reading at length and for a formal register. "源ノ明朝" — 明朝体 — the Japanese serif: a book, an editorial, a formal line. "思源等宽" — Fixed-width 黑体: 全角 characters on the same grid as the Latin beside them, so a column of numbers or a code sample lines up. The only Chinese face here that does. "본고딕 등폭" — Fixed-width 본고딕: Korean syllables on the same grid as the Latin beside them, so a column lines up. "源ノ角ゴシック等幅" — Fixed-width ゴシック体: kana and kanji on the same grid as the Latin beside them, so a column lines up. "M PLUS Rounded 1c" — 丸ゴシック — a rounded Japanese gothic, the softer register a food or family brand reaches for. "站酷庆科黄油体" — A heavy rounded poster face — a sale banner, a variety-show caption, anything that has to shout and stay warm. One weight, and no use below a headline. "검은고딕" — A very heavy Korean display sans — a poster headline, a title card. One weight. "Dela Gothic One" — A very heavy Japanese display gothic — a poster, a title card. One weight. "志莽行书" — 行书 — a running hand, joined and quick. A signature, a greeting, a seasonal card. One weight. "나눔손글씨 펜" — A ballpoint hand — a note, a caption, anything that should read as written rather than set. One weight. "Yomogi" — A soft handwritten Japanese face — a note rather than a headline. One weight. "나눔손글씨 붓" — 붓글씨 — a Korean brush hand, for a festival line or a shop sign. One weight. "佑字肅" — 筆文字 — a Japanese brush hand, for a festival, a seasonal card or a shop sign. One weight. "站酷快乐体" — A playful display face with a brush's rhythm — children's, food, anything cheerful. One weight. "주아" — A rounded, friendly Korean display face. One weight. "霞鹜文楷" — 楷书 — the regular script, drawn for reading rather than for a headline. Warmer and more hand-made than 宋体 and far steadier than the brush: a long paragraph, a poem, a label that should read as written by a person. One weight, Chinese and Latin from the same hand. "도현" — A Korean signage gothic — squarer and tighter than 본고딕, lighter than 검은고딕. The register between a workhorse and a shout: a subheading, a banner line, a price. One weight. "고운바탕" — A Korean serif drawn for a headline rather than for a paragraph: higher contrast and more drawn than 본명조, which is the one to reach for when a line has to be read at length. Invitations, editorial titles, anything formal. One weight. "しっぽり明朝" — A display 明朝体 — sharper serifs and more contrast than 源ノ明朝, drawn for one large line. The Japanese counterpart to reaching for Playfair Display rather than for a book serif. One weight. "ドットゴシック16" — A bitmap pixel face on a 16px grid — kana and kanji drawn as dots, the Japanese counterpart to Press Start 2P. Name them together (font="Press Start 2P, ドットゴシック16") or a Latin pixel headline sets its Japanese in 黑体. One weight, and illegible small. "得意黑" — A condensed 黑体 that is slanted by design and has no upright — sport, a promotion, anything with momentum, and the Chinese way to set a headline that a Latin design would put in a condensed italic. The slant is the drawing, not a style: `italic` is false because there is no second face to switch to. One weight. "朱雀仿宋" — 仿宋 — the fourth Chinese text register after 黑体, 宋体 and 楷书: even strokes, a slight slant off the horizontal, and the voice of a notice, a document or a tea-house label. Released as a technical preview, so it is younger than everything else here. One weight. "Pretendard" — The Korean interface sans, drawn on the metrics of the system faces a Korean reader already sees all day — tighter and more contemporary than 본고딕, which is the one for a printed page. Two weights. "나눔고딕" — The Korean screen gothic of the last fifteen years: squarer and plainer than 본고딕, and the name a Korean reading reaches for when it means simply "a body face". Two weights. "Zen Kaku Gothic New" — A contemporary Japanese gothic drawn for setting rather than for display — wider counters and a squarer kana than 源ノ角ゴシック, which is the neutral one. Two weights. "Zen Maru Gothic" — 丸ゴシック with a lighter hand than M PLUS Rounded 1c: rounded without reading as a children's face. One weight — name M PLUS Rounded 1c instead where a bold is needed. "Zen Old Mincho" — An old-style 明朝体 — the pre-war book face: warmer and less even than 源ノ明朝, and without しっぽり明朝's display contrast. Literature, tea, craft. One weight. "Klee One" — 楷書体 — the Japanese schoolbook hand, drawn with a pen's rhythm and none of a brush face's speed. What 霞鹜文楷 is in Chinese. One weight. "Rampart One" — Outlined lettering with the shadow drawn into the face — a festival banner, a title card, the one face here that reads as three-dimensional in Japanese as well as in Latin, which Bungee Shade cannot. One weight, and useless at caption size. |
| 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 <e9-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 <e9-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. |
<e9-text role="title" align="center" color="#FFFFFF" max-width="80%">Track every launch</e9-text><e9-text role="caption" bg="#1E3A8A" pad="16" radius="8" color="#DBEAFE">New</e9-text><e9-text role="caption" x="50%" y="88%" anchor="center" color="#94A3B8">No account needed</e9-text><e9-text role="title" italic="true" weight="700" letter-spacing="-1" x="112" y="1334">10.02</e9-text><e9-text role="subtitle" font="思源宋体" vertical="true" x="120" y="900" color="#1A1A1A">三伏未尽</e9-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.