Page components

A fenced code block whose language starts with @ is a call to a component. Everything below is generated from the components themselves, so it cannot go stale.

@audio renders: server

An audio player over a file uploaded to this site. Controls on, nothing autoplays.

Server rendered.

Example

```@audio src:/f/k3Fq9ZrX2mB7vT1wLp8sYa/episodio.mp3 title:"Episódio 1"
```

Arguments

src path Required
Path of the file on this site, usually an upload of the page. Starts with a single / — "//host/x" is another site, not a path.
title string
A short title shown under the player.
preload enum Default: metadata
How much the browser fetches before play: none, metadata or auto. Allowed: none, metadata, auto
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@button renders: server

A link drawn as a button: what the reader should do next. Works in pages and in e-mails.

Server rendered.

Example

```@button to:/pricing
See the plans
```

Arguments

to string Required
Where it goes: a path of this site (/@ana/menu) or a web address starting with https://.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

Free text. The label on the button.

@components renders: server

The reference for every fence a page may call, generated from the components' own declarations.

Server rendered.

Example

```@components
```

Arguments

only enum Default: all
Which half to list: `server`, `client`, or `all` (the default). Allowed: all, server, client
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@contact renders: server

A person or a place to reach: call, WhatsApp with a written message, e-mail, map — and a button that saves the contact to the phone.

Server rendered.

Example

```@contact name:"Vitória Imóveis" role:"Corretora" whatsapp:"+55 11 95550-0134" message:"Olá! Vi sua página." email:[email protected]
```

What it draws

Vitória Imóveis

Corretora

Arguments

name string Required
Who this is.
role string
What they do, under the name.
org string
The company or the place.
phone string
A telephone number, with the country code: "+55 11 5550-0134".
whatsapp string
The WhatsApp number, with the country code. It opens a conversation.
message string
What the WhatsApp conversation starts with, already written for the person.
email string
An e-mail address.
site string
A web address, starting with https://.
address string
Where it is. It opens the map.
save boolean Default: true
Whether the "Save contact" button is shown.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@copy renders: server

A value to take away — a Pix key, a coupon, a wifi password, a command — printed, with a button that copies it.

Server rendered.

Example

```@copy label:"Chave Pix" value:[email protected] note:"Any amount helps"
```

What it draws

Chave Pix

Any amount helps

Arguments

value string
What is copied, up to 2,000 characters. Write it here when it is short, or in the body when it is long or has spaces and quotes.
label string
What the value is, printed above it.
note string
One line under the value: until when it is valid, where to paste it.
kind enum Default: text
text for a key or a code a person reads; code for something pasted into a terminal, kept on its own lines. Allowed: text, code
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

Free text. The value, when it does not fit on the fence line: up to 2,000 characters. The body wins over `value`.

@countdown renders: server

Counts down to a date and time, and says something else once it has come. A launch, a drop, doors opening, enrolment closing.

Server rendered.

Example

```@countdown to:2026-11-20T19:00-03:00 label:"Doors open" done:"We are open"
```

What it draws

Doors open

Arguments

to string Required
The moment, as 2026-11-20 or 2026-11-20T19:00-03:00. With no offset it is read as UTC; a date alone is its first minute.
label string
What is being waited for, printed above the clock.
done string
What the block says once the moment has passed. Without it the block says the moment has come.
show enum Default: full
full counts days, hours, minutes and seconds; days counts only days, for something weeks away. Allowed: full, days
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@data renders: server

Reads a collection of this space and renders it as a table, with filters, columns, metrics and pagination; filter_by and search give the reader tabs, menus and a search box that narrow it. view:board group:<select field> shows the same rows as a board, one column per option, and lets the space's writers move a card to another column. view:calendar date:<date or datetime field> places the rows on a month or a week, and lets the writers move an item to another day. view:checklist done:<boolean field> gives each row a checkbox the writers tick. view:timeline lays the rows out as the steps of a :::timeline, state:<field> giving each its marker and item:<component> drawing each with a component of the theme. view:field field:<field> (or fields:a,b,c) shows that field of the rows the @filter lines select — meant for one row, like a post's own page — as a control the writers change in place: a select, a checkbox, a date, a number, a text box. A filter may name the page the table is shown on — in a template, the page wearing it: `@filter pr eq page.slug` (the last step of its address), `page.name`, `page.parent` (the last step of the page above). A date filter may count from today, in the reader's time zone: `@filter due lte today`, `@filter updated_at lt -14d` (today, today+3d, -2w; on a datetime, the whole of that day: `lte today` runs to midnight tonight). `@count by:<select field>` counts the rows per option; `@sum field by:<select field>` and `@avg field by:` sum or average per option, the rows counted beside each, in one query. `label:"…"` on a metric line names it. view:metric draws only the metric lines, each a stat (the number large, its label under it) — a dashboard tile, and the stat of a `:::grid items:stat` item. `@column created_at format:age` prints how long ago ("3d", "2w"). `@column title link:pr,ticket` links the text to the first of those url fields that holds an address, and `label:` on a link column is the link's text. A public collection is public inside a space its reader may see; in a private space, a page published on its own (public, cut from the space's settings) shows a table of it to whoever opens that page, when everyone who may edit the page already writes the collection — the export and every other page stay private.

Server rendered.

Example

```@data collection:inscricoes sort:-created_at limit:10
@filter status eq aberto
@count
@column nome label:"Quem"
@column status format:badge
```

Arguments

collection string Required
The name of the collection inside this space, without the @space prefix: lowercase letters, digits and hyphens, 2 to 40 characters (coord-agents, never coord_agents — field names take underscores, collection names do not).
limit integer Default: 25
How many rows per page (1–100). Defaults to 25. A board, a checklist and a calendar's period are one page: they show at most this many rows in all, and say how many more there are. Allowed: 1 to 100
offset integer Default: 0
How many rows to skip before the first page. Allowed: 0 to 100000
sort string
A field to sort by; a leading minus reverses it (`-created_at`).
distinct string
One row per value of this field: the first in the sort order, so `distinct:pr sort:-created_at` shows each pull request's latest review. The limit, the counts and the pages are over the rows kept; rows with no value are one value.
include list
Reference fields to resolve, comma separated. Shown references are resolved anyway.
fields list
Which fields to show, comma separated. Defaults to every stored field plus created_at. With view:field, the fields shown as controls (`fields:status,due,done`), in that order.
scope enum
viewer: each person sees only the rows they created. Allowed: viewer
empty string
What to say when there is no row to show.
export boolean Default: false
Adds CSV and JSON links for the whole filtered collection — the fence's filters, sort, scope and columns, but not its limit or offset.
updated boolean Default: false
Prints, under the table, when a row of the collection was last added, changed or deleted, in the reader's clock and language.
page_param string Default: page
The query parameter this table pages on. Only for two tables on one page that both page (more rows than limit:): give them different ones. A table that never pages needs none.
filter_by list
Fields the reader may filter by, comma separated: select or multi_select fields this table shows. Five options or fewer render as tabs, more as a menu. It only narrows what the fence's own @filter lets through.
search list
Text fields the reader may search, comma separated, from the ones this table shows: one box searches them all. A search is not cached.
title string
A line above the rows, {count} replaced by how many rows the reader's filters leave: title:"{count} imóveis disponíveis".
sorts string
Orders the reader may choose, label:field pairs, comma separated, `-` before a field for descending (sorts:"Padrão:ordem,Valor maior:-valor,Valor menor:valor"): a menu above the rows; the fence's own sort: stays the order until the reader picks one.
aside string
A short line under the reader's filters, in their column when controls:side (aside:"Não encontrou o imóvel desejado?"), with an optional button: aside_button: its words, aside_href: where it goes (an http(s) address or a /path).
aside_button string
With aside:, the button's words.
aside_href string
With aside:, where the button goes: an http(s) address or a /path of this site.
filter_min list
Number fields this table shows that the reader may ask a minimum of, comma separated (filter_min:quartos,vagas): each is a row of buttons 1+ to 5+, and the chosen one leaves the rows with at least that many; choosing it again clears it.
filter_include list
Exactly the select fields readers may filter by, shown on the table or not, comma separated (filter_include:tipo,cidade,bairro). Without filter_include or filter_except, filter_by takes only the fields the table shows.
filter_except list
Readers may filter by every select field of the collection, shown or not, except these, comma separated (filter_except:nota,salario). Not together with filter_include.
controls enum Default: top
Where the reader's filters and search stand: top (a row above the rows), side (a column beside them, every filter a menu, the button the column's width; above them on a phone), or only (the menus and the button and no rows: a search bar whose button opens to:, where a table with the same id: lists them). Allowed: top, side, only
apply string
The label of the button that applies the reader's menus and search (default: Apply).
labels enum Default: above
Where each menu's name stands: above it, or inside (its first option says it, "Tipo de imóvel" for all of them, as a home's search bar draws them; the name above stays for a screen reader). Allowed: above, inside
id string
The table's own name, lowercase letters, digits and dashes, starting with a letter (id:imoveis): its reader's choices travel under it in the address (?data-imoveis_filter_tipo=Casa), so a link, or a search bar on another page with the same id:, opens it filtered. One per page.
to string
With controls:only, where the search bar's button goes (an http(s) address or a /path): the page whose table has the same id:.
paging enum Default: simple
How the pages are offered when the rows run past limit:: simple (previous, page 2 of 9, next), or numbers (the pages near this one as numbered boxes, and arrows). Allowed: simple, numbers
view enum Default: table
table: rows and columns (the default). board: one column per option of the `group` field, in the order the schema lists them, each row a card; the first @column is the card's title and the others are small lines under it. The space's writers can drag a card, or use its "Move to" menu, to set the field to another option; everybody else sees the board read-only. calendar: the rows on the days of a month (or a week, `period:week`) by their `date` field, in the viewer's time zone; writers drag an item to another day or use its "Move to date" form. checklist: each row a checkbox bound to the `done` field, labelled by the first @column, with a count; writers tick and untick, everybody else sees the boxes disabled. field: one field (`field:status`) or a few (`fields:status,due,done`) of each row the filters select, as controls the space's writers change in place — a select, checkboxes, tag chips, a checkbox, a date, a number, a text box, each saved at once; everybody else sees the values. Meant for a filter that selects one row (`@filter slug eq x-launch`); several rows are one line each, up to `limit`, titled by the first @column or the row's own name. cards: a grid of cards — the first `format:image` @column is each card's picture, run to the card's edges (a further `format:image` column sits on it, above the tags); the title is the @column with `link:` (else the first other one), on one line; @columns written before it are small lines above it (a code), the ones after it lines under it, cut at three; @columns with `icon:` share one line with their icons (`@column quartos icon:bed`); `format:badge` columns are small tags stacked on the picture, a `format:ribbon` column a band across its corner (sold); `over:` names the column written across its bottom (a price); `button:` adds a small button to the title's link; `layout:carousel` lays them in one row that scrolls sideways, with Previous/Next, holding the first `limit:` rows of the sort with no pages; the reader's filters, search, `sorts:` and pages are the table's. item: each row the filters select drawn whole by a component of the theme the page wears (`item:imovel`), its fields in the slots of the same names — the page of one row; in a template, `@filter codigo eq page.slug` makes one template the page of every row. metric: the @count, @sum, @avg, @min and @max lines and nothing else — no rows, no table — each a stat, the number large and its `label:` (or what it computes) under it; a line with `by:` is a stat per option under its label. Allowed: table, board, calendar, checklist, timeline, field, cards, item, metric
group string
With view:board, the select field whose options become the columns (`group:status`). Required for a board and refused without one. Rows with no value go to a last "No value" column, shown only when some row has none. The space's writers can drag a card (or use its "Move to" menu) to another column; a card dropped on another board of the same collection — on this page, in a side-by-side view, or in another window — takes the group field of the board it lands on. Everybody else sees the board read-only. With view:checklist, a select field whose options become sections (`group:room`), each with its own count; only sections with rows are shown. With view:timeline, a select field whose value heads each run of steps with the same one (`group:kind`), in the order the rows come.
order string
With view:board, a number field that keeps the order of the cards inside each column (`order:rank`): writers can drag a card above or below another, or use Move up and Move down, and one move writes one row. A card dropped into another column takes a number halfway between its new neighbours there (a fraction; when there is no room the column is numbered again); Move to puts it last among that column's numbered cards. The numbers are compared only inside a column, so the same number in two columns means nothing. Cards with no number yet come last, in the fence's sort. Without order the columns keep the fence's sort and cannot be reordered. With view:checklist, a number field that keeps the order of the rows (inside each section): writers drag a row by its grip, or use Move up and Move down.
date string
With view:calendar, the date or datetime field each row is placed by (`date:due`). Required for a calendar. A datetime is placed on the day it falls on in the viewer's time zone (the one in their Settings, else the space owner's, else UTC), and shows its time. The space's writers can drag an item to another day, or use its "Move to date" form; a datetime keeps its time of day, unless dropped on an hour of a week (`period:week`), which sets that hour. Everybody else sees the calendar read-only. With view:timeline, a date or datetime field printed under each step's title (`date:at`). The order is the fence's sort.
end string
With view:calendar, the field each row ends at, of the same kind as `date` (`end:until`). A row with an end lasts: on a datetime it shows its time range, over several days it is drawn on each of them, and one that began before the period shown is shown from its first day. Moving items is not offered while an end is bound.
rows string
With view:calendar, lays the period out as a rota: one row per value of this field (a select's options in their order, or a text field's values), the days as columns, and a last row for the rows that have none. Moving items is not offered on a rota.
mark string
With view:calendar rows:, a row this field is set on (true, or any option) is drawn as a label on its cell's ground — OFF, Sick — instead of as an item.
done string
With view:checklist, the boolean field each row's checkbox shows and sets (`done:packed`). Required for a checklist. The space's writers tick and untick the boxes, which saves the field at once; everybody else sees them disabled. Not the @checklist block, which keeps ticks in the reader's browser.
tags string
With view:checklist, an open tags field: writers search existing tags or create one while working, with automatic colors. Several tags can describe each row without marking it done.
state string
With view:timeline, the field each step's marker shows: a select whose options are done, current, upcoming, error and skipped, or one mapped to them with states:; or a boolean, done when true.
height enum
With view:board or view:calendar, how tall a column (or a week's day) may grow before its cards scroll inside it: short, medium (the default, about two thirds of the screen), tall, screen, or auto (no bound: the column grows the page). A theme or a page changes the default with --nt-board-height. Allowed: auto, short, medium, tall, screen
columns list
With view:board, which options of the `group` field become columns, in this order, comma separated (`columns:"todo,doing,review"`). Rows holding any other option, or none, are not on the board and take none of its `limit`. Without it, every option is a column, in the schema's order.
wip string
With view:board, work-in-progress limits per column, as option=limit pairs separated by commas (`wip:"doing=3,review=2"`). The column's count shows as "n/limit", counted over every row the board's filters let through (not only the cards shown), and its header is marked when the count is over the limit. Moves are not refused.
period enum
With view:calendar, month (the default: whole weeks) or week (seven days), each week from the day `week_start` names (Monday by default). Readers move to the previous or next period, or back to today, with links beside the title; only the rows of the period shown are read, up to `limit`. Allowed: month, week
hours enum
With view:calendar period:week on a datetime, the hours drawn: auto (the default) from 8 to 18, reaching earlier or later when an item does; work, 8 to 18; full, the whole day. Each item sits at its time, as long as it lasts, beside the ones it overlaps; a narrow page lists them instead. Allowed: auto, work, full
week_start enum
With view:calendar, the day each week starts on: monday (the default, ISO 8601), sunday or saturday — the same for every reader of the page. Allowed: monday, sunday, saturday
start string
With view:calendar, the day whose period the page opens on instead of today's: a date (`start:2026-10-13`) or a day counted from the reader's today as @filter counts it (`start:today+2d`, `start:-1w`), within ten years of today. Readers still move to the previous or next period, and "Today" takes them to today's.
states string
With view:timeline state:, how the field's values map to a step's states, as value=state pairs separated by commas: `states:"Entregue=done, Em trânsito=current, Falhou=error"`. A value it does not name, and one that is a state's own name, keep their own.
item string
With view:timeline, a component of the theme the page wears that draws each step (`item:passo`): the row's fields fill the component's slots of the same names, as text, and a list of the component (`list fotos: url`) one entry per value of the field of its name — each option of a multi_select or tags, each line of a text, its fields separated by `|`. The step's marker is still the row's state:. With view:item (where it is required), the component that draws each row the filters select, whole.
direction enum
With view:timeline, vertical (the default) runs down the page; horizontal runs across as a stepper and turns vertical when the page is narrow. Allowed: vertical, horizontal
field string
With view:field, the field shown as a control the space's writers change in place (`field:status`): a select for a select, checkboxes for a multi_select, chips for tags, a checkbox for a boolean, a date (or date and time) input, a number input, a text box for text, long_text, email and url. A reference, a file, a computed field and created_at show their value. Everybody else sees the value. For several fields use `fields:status,due,done` instead (one or the other).
over string
With view:cards, the @column written across the bottom of each card's picture, in white on a darkened band (a price, a date): `over:preco`.
ratio enum
With view:cards, the shape each card's picture is cropped to (4/3 when left out). Allowed: 4/3, 5/4, 9/7, 3/2, 1/1, 16/9, 3/4
per_row enum
With view:cards, at most this many cards per row on a wide screen (as many as fit when left out); a phone gets one. Allowed: 2, 3, 4
gap enum
With view:cards, the room between the cards, a step of the theme's scale like a :::grid's space: (3 when left out; 2 is a listing's tight 16px). Allowed: 1, 2, 3, 4, 5
column_gap enum
With view:cards, the room between cards side by side, in px (column_gap:24); beside gap:, it wins for the columns. Allowed: 8, 12, 16, 24, 32, 40
row_gap enum
With view:cards, the room between rows of cards, in px (row_gap:12); beside gap:, it wins for the rows. Allowed: 8, 12, 16, 24, 32, 40
photo_height enum
With view:cards, each picture this tall in px whatever the card's width (photo_height:254), cropped to fill; instead of ratio:. Allowed: 200, 220, 240, 254, 280, 300
inset enum
With view:cards, room inside the grid's left and right edges, in px (inset:12), as a grid whose cards carry half a gutter each is drawn. Allowed: 8, 12, 16, 24
layout enum
With view:cards, `carousel` puts the cards in one row that scrolls sideways, each stop a card at the row's start: touch, trackpad, the arrow keys with the row focused, and Previous/Next buttons once a script runs; nothing moves by itself. `per_row:` is the most that show at once (cards keep a listing card's width, so a narrow screen shows fewer); `limit:` is how many it holds, the first ones in the sort, with no pages. grid (the default) wraps them in rows. Allowed: grid, carousel
button string
With view:cards, a small button under each card's lines, to the title's link: `button:"Details"`, or with an icon of the set first, `button:"icon:plus Details"`.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

One instruction per line. Optional children: `@filter field op value` (op: eq, ne, gt, gte, lt, lte, contains, contains_any, in, nin; `in` and `nin` take a,b; every line must hold; a field takes each op once, but `ne` may repeat, each line leaving out one more value: `@filter state ne done` + `@filter state ne dropped`), `@column field label:"…" format:… icon:…` (one field of this collection; `icon:` an icon of the set drawn before the value; a reference like `@column prova` prints the row it points at, and there are no dotted paths; `format:image` on a url or text field shows the picture as a thumbnail kept on this site, and a click opens it; a file of this site — a /f/<token>/<name> path, what an upload gives — shows itself, and on a url or text field `format:video` plays it in a small inline player and `format:file` links it for download under its name), and the metrics `@count`, `@sum field`, `@avg field`, `@min field`, `@max field`, each with an optional `label:"…"`; `by:<select field>` on `@count`, `@sum` and `@avg` gives one line per option, in the schema's order (`@sum valor by:categoria`).

Accepted children

@filter, @column, @count, @sum, @avg, @min, @max

@diff renders: server

A patch as a review reads it — what `git diff` prints — one section per file, coloured by language, stacked or side by side. Select a line to annotate it.

Server rendered.

Example

~~~@diff title:"Greeting takes a mark"
--- a/greeting.rb
+++ b/greeting.rb
@@ -1,3 +1,3 @@
 def hello(name)
-  "Hello, #{name}"
+  "Hello, #{name}!"
 end
~~~

Arguments

title string
A line above the files: what the change is.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

Free text. The patch: the output of `git diff` (or any unified diff). Fence it with ~~~ so the backticks inside a patch stay text.

@event renders: server

A moment to put in a calendar: the date and time, how long, where — printed, with a Google Calendar link and an .ics file for Apple and Outlook.

Server rendered.

Example

```@event to:2026-10-17T14:00-03:00 duration:60 title:"First meeting" where:https://meet.example/abc zone:America/Sao_Paulo
```

Arguments

to string Required
When it starts, as 2026-10-17T14:00-03:00. With no offset it is read as UTC; a date alone is its first minute.
title string Required
What the calendar entry is called.
duration integer Default: 60
How long it lasts, in minutes (5 to 1440). Defaults to 60. Allowed: 5 to 1440
where string
Where it happens: a place, or the address of the call (https://…).
details string
A line for the calendar entry's notes: what to read, what to bring.
zone string
The time zone the moment is printed in, as the tz database names it (America/Sao_Paulo). Without it the moment is printed in UTC.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@flashcards renders: server

A deck of cards to drill: a term and its meaning, a question and its answer, a word and its translation — or a self-test, with questions the reader answers and a score. One card per line, front | back; a line of three parts or more is a multiple-choice question. Turned by a click or the keyboard; printed in full, answers included, without a script.

Server rendered.

Example

```@flashcards label:"DNS do envio"
SPF | Diz quais servidores podem enviar em nome do domínio.
DKIM | Assina cada mensagem; o destinatário confere no DNS.
```

```@flashcards label:"Self-test"
Which port does a mail client submit on? | 587 :: The submission port, with STARTTLS. | 25 :: Port 25 is for servers talking to servers. | 80 | 443
Which record signs each message? | DKIM | SPF :: SPF names the servers; it signs nothing. | MX
```

Arguments

label string
A line above the deck saying what it drills.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

One instruction per line. One card per line. `front | back` is a card that turns. `question | right answer | wrong | wrong …` is a multiple-choice question: the FIRST answer after the question is the right one, and the options are shown shuffled (the same order on every render, so it works printed and without a script). An option may say why after ` :: ` (a space, two colons, a space): `25 :: Port 25 is server to server.` — shown once the reader picks. The reader's picks and score stay in their browser; to keep each learner's answers on the server, use a @form with scope:viewer.

@form renders: server

A form that writes a row into a collection of this space. Only renders for somebody the collection accepts.

Server rendered.

Example

```@form collection:inscricoes submit:"Quero entrar"
nome
email required
```

```@form collection:lista layout:inline submit:"Assinar"
email required
```

```@form collection:inscricoes mode:edit own:true
nome
email required
```

```@form collection:inscricoes preview:true
nome
email required
```

```@form collection:anuncios labels:inside button:full submit:"Enviar cadastro"
## 1. Owner
nome
telefone width:1/2
email width:1/2
## 2. The property
rua width:3/4
numero width:1/4
```

In the template a ```route draws each obituary with (`:slug to: obituario collection: obituarios`), its condolence wall:

```@form collection:condolencias submit:"Leave a condolence"
obituario from:params.slug
nome required
mensagem long_text
```

```@data collection:condolencias
@filter obituario eq params.slug
@column nome
@column mensagem
```

Arguments

collection string Required
The name of the collection inside this space, without the @space prefix: lowercase letters, digits and hyphens, 2 to 40 characters (coord-agents, never coord_agents — field names take underscores, collection names do not).
success string
What to say after a row goes in. Defaults to a thank-you.
submit string
The label of the button. Defaults to "Send".
scope enum
viewer: require sign-in and attribute the row to the sender. Use scope:viewer on reads to show only that person's rows; collection visibility still controls other reads. Allowed: viewer
mode enum Default: create
create: a form that adds a row. edit: a form that changes one of the viewer's own rows; it needs own:true. To change any row's fields, a writer uses `@data view:field fields:…` (edits them inline) or the Collections screen. Allowed: create, edit
layout enum Default: stacked
stacked: one field under the other, each with its label. inline: the fields and the button in one row — for a signup of one or two fields; the labels become the hints inside the fields and stay readable to a screen reader. Allowed: stacked, inline
labels enum Default: above
above: each field's name over it. inside: the name is the hint written in the empty field, and a select opens on it — how a site's contact or listing form is drawn; a screen reader still reads the label. A checkbox keeps its label beside it. Allowed: above, inside
button enum Default: auto
full: the send button takes the form's whole width, as a long site form ends. Allowed: auto, full
shape enum Default: default
pill: fully rounded fields and button, the fields on the ground of the band they stand on (a dark footer keeps them dark). With `submit:"icon:arrow-right"` the button is a round icon alone, its name still read to a screen reader. Allowed: default, pill
text enum Default: inherit
The size of the fields' and the button's words in px (text:14), whatever the text around the form; inherit keeps it. Allowed: inherit, 12, 13, 14, 15, 16
own boolean Default: false
true: list the rows this viewer created, each with a link that opens it in the form. Signed-in people only.
preview boolean Default: false
true: the form as it would look — fields, labels, layout, the button's words — with the button disabled and a note that it sends nothing, shown to whoever may read the collection or send through it, even when the collection accepts nobody; anyone else gets the closed notice. No form element and no address to send to, so nothing is ever written. For the docs, a theme's or a template's preview, a mockup.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

One instruction per line. One field per line, a subset of the collection's schema: `email required`, `nome`, `mensagem long_text`. Options must match the collection schema; change @schema first to override them. `width:1/2` on a line (1/4 1/3 1/2 2/3 3/4 full) puts fields side by side, on a phone one under the other. A line that starts with `#` is a section title inside the form (`## 2. The property`). A `file` field takes a picture (JPEG, PNG, WebP, GIF or HEIC, up to 10 MB), kept as the row's own file: only readers of the collection see it, and it counts against the space owner's storage. Empty body: every writable field, in schema order. `from:` on a line makes it a field THE PAGE FILLS, drawn as no input: `obituario from:params.slug` in the template a ```route draws each obituary with writes that row's slug into every condolence sent from its page (also `page.slug`, `page.name`, `page.parent`, as a @data filter reads them). The server sets the value from the page the form was drawn on, asked for again at the submit (the row still there and readable by the sender); whatever the browser sends for it is ignored, so nobody posts onto another row by editing the request. On a page that gives no value (the template opened on its own) the field is left out.

@hours renders: server

When a place is open: the week, printed, and "open now" by the clock of the place. For a venue, a shop, a clinic, a contact page.

Server rendered.

Example

```@hours zone:America/Sao_Paulo notice:"Closed on the 12th"
mon-fri 11:30-15:00, 18:00-23:00
sat 12:00-00:00
sun closed
```

What it draws

Mon – Fri
11:30 – 15:00
18:00 – 23:00
Sat
12:00 – 00:00
Sun
Closed

Closed on the 12th

Arguments

zone string Required
The time zone of the place, as the tz database names it: America/Sao_Paulo, Europe/Lisbon. "Open now" is read on that clock, not the reader's.
title string
A heading over the week.
notice string
One line under the week: a holiday, new hours, "kitchen closes 30 minutes earlier".
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

One instruction per line. One line per day or run of days, then the hours: `mon-fri 09:00-18:00`, `sat 10:00-14:00, 16:00-20:00`, `sun closed`. Days in English or Portuguese. An end before the start runs past midnight.

@members renders: server

The people in a group: name, a line about them, who runs it. Shown only to those the group lets see its list (its managers; its members when the group says so). Nothing for anybody else.

Server rendered.

Example

```@members group:"Turma 3" label:"Quem está na turma"
```

Arguments

group string Required
The group, by name or id. A name must be one you stand in, or a group with a door (by_request, open).
label string
A line above the list.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@pages renders: server

Also written ```pages

A gallery of pages, each one a picture of itself: the pages inside a folder (`from:`), or the pages listed in the body. Only pages the reader may open are shown.

Server rendered.

Example

```@pages from:/@docs/showcase columns:2
```

Arguments

columns integer Default: 3
How many cards per row (1–4). Defaults to 3. Allowed: 1 to 4
from string
A folder: its path (/@you/work), or ~/work for a folder of the space this page is in. Its pages with something written are the gallery, in the order they were made, and a new page joins it by itself — the way to keep a section's hub. Without it, the pages listed in the body.
limit integer Default: 12
How many cards at most (1–48). Defaults to 12. A list in the body longer than this shows its first ones, and validate warns. Allowed: 1 to 48
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

One instruction per line. Without `from:`, one page path per line. `/a/section | /a/section/one` links to the first and pictures the second.

@patterns renders: server

The section pattern library: every pattern, grouped, with a link to it rendered and its markdown to copy.

Server rendered.

Example

```@patterns
```

Arguments

members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@pdf renders: server

A page of a PDF uploaded to this site, drawn in the page (or a few, pages:18-19). Only that page's bytes are fetched; a click opens the PDF in the site's viewer at that page. Without a script, or printed, it is a link to the viewer at that page.

Server rendered.

Example

```@pdf src:/f/k3Fq9ZrX2mB7vT1wLp8sYa/curso.pdf page:18 title:"Figure 3: the request cycle"
```

Arguments

src path Required
The PDF's address on this site, /f/<token>/<name>.pdf, as `files` lists it. Starts with a single / — "//host/x" is another site, not a path. No #page= here: the page is page:.
page integer Default: 1
The page drawn. 1 by default. Allowed: 1 to 100000
pages string
A range of pages drawn one under the other, first-last: pages:18-19. At most 4. Instead of page:.
title string
A short line shown under the page.
height integer
The most pixels tall a page is drawn. By default a page fits the width of the column. Allowed: 120 to 2000
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@posts renders: server

The pages inside a folder as a list of posts, newest first: title, date and a line each. The date is the page's ```meta date:, else the day it was made. Only pages the reader may open are listed; a public folder also offers its RSS and Atom feeds.

Server rendered.

Example

```@posts limit:5
```

Arguments

from path
The folder whose pages are listed. Without it, the page the block is on.
limit integer Default: 10
How many posts, the newest first (1–50). Defaults to 10. Allowed: 1 to 50
feed boolean Default: true
false: leave out the links to the folder's RSS and Atom feeds.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@qr renders: server

A QR code of this page, or of another address: for a table, a slide, a poster, a card. Dark on white whatever the theme, so a camera reads it.

Server rendered.

Example

```@qr label:"Abra esta página no celular"
```

What it draws

to must be a path of this site, like /@ana/menu, or a web address starting with https://, and is neither.

See the components reference

```@qr label:"Abra esta página no celular"
```

Arguments

to string
What the code opens: a path of this site (/@ana/menu) or a web address starting with https://. Without it, the page the block is on.
label string
A line under the code, saying what it opens.
size enum Default: medium
How large it is drawn on the screen. It prints sharp at any size. Allowed: small, medium, large
color string
The colour of the code itself, as #rrggbb. Dark enough to read against the background, or the block says so.
background string
The colour behind the code, as #rrggbb. White by default, which is what a camera likes best.
eye string
The colour of the three corner squares, as #rrggbb. The colour of the code by default.
shape enum Default: square
The shape of the small modules: square, dots or rounded. The corner squares stay square whatever this says. Allowed: square, dots, rounded
logo string
A mark in the middle: `brand` (the mark of this site), `none`, or the path of an image on this site (/demo/mark.png).
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@schema renders: server

Declares the fields of a collection of this space. Whoever edits the page sees the declaration (a reader gets nothing in its place); only somebody with settings on the space can apply it.

Server rendered.

Example

```@schema collection:inscricoes accepts:anyone
nome text required
email email required label:"E-mail"
prova reference:provas
```

Arguments

collection string Required
The name of the collection inside this space, without the @space prefix: lowercase letters, digits and hyphens, 2 to 40 characters (coord-agents, never coord_agents — field names take underscores, collection names do not).
visibility enum Default: private
Who may READ the rows: private (the space's people) or public (anyone). Private by default. Allowed: private, public
accepts enum Default: nobody
Who may send a row through an @form: nobody, members (people a role on the space root reaches) or anyone (in a private space: anyone who reads a published page holding the form; a page anyone may edit opens nothing). Nobody by default. Allowed: nobody, members, anyone
calendar string
A date or datetime field that puts every row on the calendar of the space's own people who may read the collection: their calendar feed (Settings → Preferences) shows each row on its date, with their @remind lines as alarms. The field is indexed as if it said `indexed`. Only the space's owner applies it.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

One instruction per line. One field per line: `name type [required] [indexed] [label:"…"]`. The types: text, long_text, number, boolean, date, datetime, email, url, select, multi_select, tags, file, reference, computed. A type may carry its argument: `select:a,b` (an option with spaces in quotes: `select:"in progress",passed`), `reference:outra`, `computed:sum(outra.valor)` (count, sum, avg, min or max; sum and avg take a number, min and max a number, a date or a datetime and answer in its type: `computed:min(tasks.due)` is a project's earliest due date). Indexed date/datetime fields do not accelerate temporal comparisons. `default:<value>` is what a new row takes when it arrives without the field or with it empty, at every door (a form, the screen, upsert_records): a value the type can hold, one of a select's options (`status select:open,closed default:open`; not on computed, file, reference, multi_select or tags). `doors:` names the only doors that may set or change the field (form, board, calendar, checklist, field, screen, mcp, import, group, feedback, system): `state select:todo,done doors:board,field,screen` refuses an upsert_records (mcp) that sets or changes state, naming the field, and lets one that leaves it alone through. A `@hook` line POSTs the changes of the rows to a URL after they are saved, signed with the collection's secret: `@hook on:updated field:status to:Ready url:https://…`. `on:` created, updated, deleted, restored (all four when left out, created and updated when the line has a `field:`); `field:` only when that field changed; `from:`/`to:` what it changed from/to, a value the field's type can hold; `source:` only through these doors (form, board, calendar, checklist, field, screen, mcp, import, group, feedback, system); `url:` https, a public host, port 443, 80 or 1024 and up. Only the space's owner applies hooks and sees their secret and deliveries (Collections screen); whoever edits the page reads the @hook lines in its source, a reader never gets them. A `@remind` line reminds people of a date field of the rows: `@remind field:due before:1d,1h to:field:assignee`. `field:` a date or datetime field; `before:` 15m, 1h, 1d, 1w (comma-separated, days and weeks only on a date field); `at:HH:MM` a time on the recipient's clock (a date field without it fires at 09:00); `to:` owner (the default), field:<an e-mail or text field naming an account> or group:<a group with a role on the space>; `via:` email (the default, Pro), hook (the `reminder` event a `@hook on:reminder` line forwards) or calendar (only an alarm on the row in the calendar feed of each person `to:` names, on every plan; the collection needs `calendar:` on that field). Only the space's own people (its owner, a role on it they opened, a member of a group with a role on it) who may read the collection are reminded, at most 50 reminder e-mails a day each; a reader never gets the @remind lines. Reserved field names: the row's own (`id`, `extra`, `record`, `included`, `data`, `resolved`, `created_at`, `updated_at`, `created_by`, `initialize`) and the methods every row answers to (`abort`, `as_json`, `assign_attributes`, `at_exit`, `attribute`, `attribute_aliases`, `attribute_method_patterns`, `attribute_missing`, `attribute_names`, `attribute_writer_missing`, `attributes`, `autoload`, `binding`, `caller`, `caller_locations`, `catch`, `class`, `class_eval`, `clone`, `concern`, `context_for_validation`, `deep_dup`, `define_singleton_method`, `display`, `display_label`, `dup`, `enable_warnings`, `enum_for`, `errors`, `eval`, `exec`, `exit`, `extend`, `fail`, `fork`, `format`, `freeze`, `gem`, `gem_original_require`, `gets`, `global_variables`, `halted_callback_hook`, `hash`, `historical_scalar_value`, `init_internals`, `initialize_clone`, `initialize_copy`, `initialize_dup`, `inspect`, `instance_eval`, `instance_exec`, `instance_values`, `instance_variable_get`, `instance_variable_names`, `instance_variable_set`, `instance_variables`, `instance_variables_to_inspect`, `itself`, `j`, `jj`, `lambda`, `load`, `local_variables`, `loop`, `matched_attribute_method`, `method`, `method_missing`, `methods`, `missing_attribute`, `model_name`, `no_warning_require`, `object_id`, `open`, `p`, `pp`, `presence`, `presence_in`, `pretty_inspect`, `pretty_print`, `pretty_print_cycle`, `pretty_print_inspect`, `pretty_print_instance_variables`, `print`, `printf`, `private_methods`, `proc`, `protected_methods`, `public_method`, `public_methods`, `public_send`, `putc`, `puts`, `raise`, `raise_validation_error`, `rand`, `raw_field_value`, `read_attribute_for_validation`, `readline`, `readlines`, `remove_instance_variable`, `require`, `require_dependency`, `require_relative`, `require_without_bootsnap`, `run_callbacks`, `sanitize_for_mass_assignment`, `sanitize_forbidden_attributes`, `select`, `send`, `set_trace_func`, `silence_warnings`, `singleton_class`, `singleton_method`, `singleton_method_added`, `singleton_method_removed`, `singleton_method_undefined`, `singleton_methods`, `sleep`, `slice`, `spawn`, `sprintf`, `srand`, `suppress`, `syscall`, `system`, `tap`, `test`, `then`, `throw`, `to_enum`, `to_json`, `to_key`, `to_model`, `to_param`, `to_partial_path`, `to_query`, `to_s`, `to_yaml`, `trace_var`, `trap`, `try`, `untrace_var`, `validate`, `validates_absence_of`, `validates_acceptance_of`, `validates_comparison_of`, `validates_confirmation_of`, `validates_exclusion_of`, `validates_format_of`, `validates_inclusion_of`, `validates_length_of`, `validates_numericality_of`, `validates_presence_of`, `validates_size_of`, `validates_with`, `validation_context`, `values_at`, `warn`, `with`, `with_options`, `with_warnings`, `yield_self`, `zeitwerk_original_require`). A hyphen reads as an underscore, so `created-at` is reserved too.

Accepted children

@hook, @remind

@themes renders: server

The starting themes: every whole look an author can begin from, drawn in its own colours, with its theme fence to copy.

Server rendered.

Example

```@themes
```

Arguments

members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@tokens renders: server

A theme's tokens, drawn: its colours as swatches with their codes, and its typefaces as a sample — the preview of a design system kept in a page.

Server rendered.

Example

```@tokens from:/@ana/design
```

Arguments

from path
The page whose theme is drawn: a path of this site (/@ana/design). Without it, the page the block is on.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@use renders: server

A component of the theme this page wears (the theme's screen lists them, with when to use each and its slots), filled with this page's words.

Server rendered.

Example

```@use cartao-de-curso
titulo: Torno para iniciantes
data: Sáb · 14 jun
```

Arguments

name string Required
The component's name, as its theme lists it: `cartao-de-curso`. Written alone after @use.
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

Free text. One slot per line, `slot: words`; a list, one line per entry, its fields in the component's order: `etapas: Pedido criado | done | 10 mar`. A link or a picture slot takes an address (/…, https://…).

@video renders: server

A video player over a file uploaded to this site. Controls on, nothing autoplays.

Server rendered.

Example

```@video src:/f/k3Fq9ZrX2mB7vT1wLp8sYa/demo.mp4 title:"Como aplicar o esquema"
```

Arguments

src path Required
Path of the file on this site, usually an upload of the page. Starts with a single / — "//host/x" is another site, not a path.
title string
A short title shown under the player.
preload enum Default: metadata
How much the browser fetches before play: none, metadata or auto. Allowed: none, metadata, auto
poster path
Path of an image shown before play. Starts with a single / — "//host/x" is another site, not a path.
mode enum Default: player
player shows controls and never autoplays; background plays muted, looped and without controls, for the ground of a :::hero (paused when the reader asks for reduced motion). Allowed: player, background
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@whatsapp renders: server

The round WhatsApp button in a site's corner: one tap opens the conversation with the message already written.

Server rendered.

Example

```@whatsapp number:"+55 21 95550-0134" message:"Olá! Vi o site e quero mais informações."
```

Arguments

number string Required
The WhatsApp number, with the country code: "+55 21 98519-2305".
message string
What the conversation starts with, already written for the person.
label string
What a screen reader says, and the hint on hover. Defaults to "Talk on WhatsApp" in the page's language.
position enum Default: corner
corner: on a site, fixed in the bottom corner while the page scrolls. inline: where it is written. Allowed: corner, inline
members_of string
A group, by name or id: only its members (and whoever edits the page) see this block; everybody else sees a line saying so, with the group's door. Nothing of the block reaches them — not on the page, not in its Markdown, not through the MCP, the search or their calendar feed (an @event is on its members' and editors' feeds only).
consent string
A flag the reader must have allowed before this block shows (`consent:videos`; several, separated by spaces). It has to be one a `@consent` on this site offers.

Body

This component takes no body.

@chart renders: client

Also written ```chart

A chart or a table, drawn from CSV: bars, stacked bars, a line, an area, a pie, a donut, a scatter or bubble plot, a heatmap, a waterfall. A reader can point at a value and hide a series.

Rendered in the browser.

Example

```@chart type:line
title: Pages published
markers: Feb=Launch
---
month,pages
Jan,3
Feb,7
```

What it draws

title: Pages published
markers: Feb=Launch
---
month,pages
Jan,3
Feb,7

Arguments

type enum Default: bar
Which drawing. `stacked` piles the series of a bar chart; `pie` and `donut` read the first series, one slice per row. `scatter` reads x and y from the first two number columns and sizes a bubble by an optional third; `heatmap` fills a cell per row and column by its value and prints it; `waterfall` reads one column: the first row is the start total, the last the end total (blank to compute it), the rows between are signed contributions. Allowed: bar, stacked, line, area, pie, donut, scatter, heatmap, waterfall, table
title titulo string
Printed above the chart.
markers marcos string
Moments on the category axis, as category=label pairs separated by semicolons: `markers: Jun=Launch; Aug=New price`. Each is a dashed line with its label, outside the series and the legend, and said in words under the chart. A pair naming no category of the data is left out.
look enum
`editorial`: the chart on diagram-design's fixed 1000 px sheet, its reference geometry for the type (axes, bar widths, label positions), in the page's colours; the sheet scales down on a phone. `page` (the default): the chart laid out at the page's width. Allowed: page, editorial
focal foco string
The one item drawn in the page's accent, the rest in the series palette, the way diagram-design marks one element: a row (`focal: S5`), a series (`focal: plates`), or in a heatmap a `row,column` cell (`focal: payments,S4`). Exactly one; a second name after a comma is refused, and so is a name the data has not. The legend and the table mark it with ★, so the hue is never the only sign.

Body

CSV, or the whole block as JSON. CSV: the first row names the columns, the first column labels the category axis. The whole body may be JSON instead.

@chat renders: client

Also written ```chat

A conversation: one message per line, `who: text` with an optional ` @ time`. `me` (or `eu`) sits on the right.

Rendered in the browser.

Example

```@chat title:Suporte
ana: Oi, chegou?
me: Chegou sim @ 10:42
```

What it draws

ana: Oi, chegou?
me: Chegou sim @ 10:42

Arguments

title titulo string
The line above the thread.

Body

One message per line. One `who: text @ time` per line.

@checklist renders: client

Also written ```checklist

A working checklist: it counts, it groups under ## headings, and it remembers — in the reader's own browser, never on the page. For ticks every reader shares and an agent can tick, use @data view:checklist over a collection (manual views).

Rendered in the browser.

Example

```@checklist title:"Antes do deploy"
## Testes
- [ ] Rodar a suite
- [x] Console limpo
```

What it draws

## Testes
- [ ] Rodar a suite
- [x] Console limpo

Arguments

title titulo string
The line above the list.

Body

Items, separated by a --- line. One `- [ ] something` per line, with optional `## Section` headings.

@profile renders: client

Also written ```profile

The head of a link page: avatar, name, bio and a row of social icons.

Rendered in the browser.

Example

```@profile
name: Nara
bio: A taste of everything
avatar: /demo/nara.svg
instagram: https://instagram.com
```

What it draws

name: Nara
bio: A taste of everything
avatar: /demo/nara.svg
instagram: https://instagram.com

Arguments

name string Required
The name printed under the avatar.
bio string
One paragraph under the name.
avatar string
An image URL, absolute or root-relative.
shape enum Default: circle
The avatar's shape. Allowed: circle, rounded

Body

One link per line. More `platform: url` lines.

@reviews renders: client

Also written ```reviews

A row of review cards, each with its stars.

Rendered in the browser.

Example

```@reviews title:"O que dizem"
★★★★★ Ana
Best bagels in town.
```

What it draws

★★★★★ Ana
Best bagels in town.

Arguments

title titulo string
The line above the row.

Body

Items, separated by a --- line. One review per block, separated by a --- line: `★★★★☆ Name` or `4/5 Name`, then the text.

@faq renders: client

Also written ```faq

Questions that open, one <details> each.

Rendered in the browser.

Example

```@faq
Do you ship?
Yes, worldwide.
---
Returns?
Within 30 days.
```

What it draws

Do you ship?
Yes, worldwide.
---
Returns?
Within 30 days.

Arguments

title titulo string
The line above the questions.

Body

Items, separated by a --- line. One question per block, separated by a --- line: the question line, then the answer.

@embed renders: client

Also written ```embed

A card that names a provider and links out. Never a frame the reader did not ask for: the page loads no third party inside itself, and with play:here a YouTube or Vimeo video is a poster and a button until the reader presses play (ADR 013).

Rendered in the browser.

Example

```@embed youtube:https://youtu.be/abc
title: Sunrise set
```

What it draws

title: Sunrise set

Arguments

youtube string
A YouTube URL.
spotify string
A Spotify URL.
podcast string
A podcast URL.
video string
A video URL.
calendar agenda string
Where somebody books a time with you: a Cal.com, Calendly or Google Calendar appointment URL.
music musica string
A track, an album or a playlist, wherever it lives.
applemusic string
An Apple Music URL.
soundcloud string
A SoundCloud URL.
bandcamp string
A Bandcamp URL.
deezer string
A Deezer URL.
tiktok string
A TikTok video or profile URL.
instagram string
An Instagram post or profile URL.
twitch string
A Twitch channel URL.
vimeo string
A Vimeo URL.
map string
An address or a Google Maps URL.
maps string
The same as map.
title titulo string
The card's first line.
note string
The card's second line.
play enum
here: a YouTube or Vimeo video plays in the page, in a 16:9 frame — after the reader presses play, and not before: until then the page holds nothing of the provider, only the poster and a button. The player comes from the provider's no-cookie address (youtube-nocookie.com, Vimeo with dnt). Any other provider stays a card. Allowed: here
poster string
With play:here, the picture shown until the reader presses play: a file of this site (/f/…), never the provider's own thumbnail, which would load the provider before the reader asked.

Body

This component takes no body. This block takes no body.

@diagram renders: client

Also written ```diagram

A figure drawn from a list, in the editorial manner of diagram-design (cathrynlavery/diagram-design, MIT), each type on its reference geometry, in the page's colours and fonts, with one focal item in the accent: a layer stack, a pyramid or funnel, a loop, a timeline, nested rings, a process or data flow (lanes × steps), a story map, a security matrix, a service blueprint, an exploded view (isometric parts pulled apart), a high-level data stack, a medallion of tiers, a data-platform integration, an architecture delta (before and after, with a ledger of changes), an axonometric plan (a floor or a site seen from above), a tree (a hierarchy by indentation), an org chart (ownership, with callout strips), a dependency graph (ranks, fan-in, one cycle), a polar chart (one series on a dial), a gantt (tasks on weeks, in phases), a sankey (a quantity through three stages), a sequence (lifelines, activations, fragments), a swimlane (steps across team lanes), a flowchart (shapes carry type, labelled branches), a state machine (states, dots, curved returns), a quadrant (a 2×2 of dots) or a scenario matrix, a radar (series over axes), an ER model (entities, cardinality), a UML class diagram (compartments, typed arrows), a venn (sets meeting at one sweet spot), a treemap or marimekko (area as share), a fishbone (causes on bones, one root cause), a wardley map (value chain over evolution), a kanban (columns, WIP chips, card states), a user journey (stages, sentiment curve, pain), a database schema (tables, columns, foreign keys), and `figure`, a placed architecture (nodes on a grid, zones, routed connectors). Optional motion: the items enter one by one, with controls. A mermaid fence still draws any of these in mermaid's grammar (`look:editorial` gives it the same manner). The grammar of every type, with a live example each: /@docs/blocks/diagram; one example per diagram-design type: /@docs/showcase/diagram-design.

Rendered in the browser.

Example

```@diagram type:layers motion:step
title: AI app stack
top: Abstraction
bottom: Silicon
- UI surface · chat, editor, canvas {tag:L5}
- Agent harness · tools, memory, loop {focal tag:L4}
- Prompt layer · system, few-shot, caching {tag:L3}
- SDK / client · auth, retries, streaming {tag:L2}
- Model weights · opus, sonnet, haiku {tag:L1}
```

What it draws

title: AI app stack
top: Abstraction
bottom: Silicon
- UI surface · chat, editor, canvas {tag:L5}
- Agent harness · tools, memory, loop {focal tag:L4}
- Prompt layer · system, few-shot, caching {tag:L3}
- SDK / client · auth, retries, streaming {tag:L2}
- Model weights · opus, sonnet, haiku {tag:L1}

Arguments

type enum Default: layers
Which figure. `layers`: full-width bands stacked top to bottom (a stack, the OSI model, a hierarchy of abstraction). `pyramid`: trapezoids narrowing to an apex, the first item at the top. `funnel`: the same, widest first. `loop`: a hub with 5–8 stations on a ring. `timeline`: events on a baseline at honest positions. `nested`: concentric rings, outer first. `process` and `data-flow`: lanes × steps with nodes, chips and arrows. `story-map`: a backbone of activities and slices of cards with a release cut. `dp-security-matrix`: roles × components with an access level per cell. `service-blueprint`: stages × layers with the line of visibility. Each one's lines are described at /@docs/blocks/diagram. Allowed: layers, pyramid, funnel, loop, timeline, nested, process, data-flow, story-map, dp-security-matrix, service-blueprint, figure, exploded, high-level, medallion, dp-integration, architecture-delta, axonometric-plan, tree, org-chart, dependency, polar, gantt, sankey, sequence, swimlane, flowchart, state, quadrant, radar, quadrant-consultant, er, uml-class, venn, treemap, fishbone, wardley, kanban, journey, db-schema
motion enum Default: none
How the items enter. `none`: the complete figure. `step`: one by one, with previous, play, pause, next and replay, and the keyboard. `reveal`: plays by itself once, when the figure first comes into view, then stays complete (replay from the controls). Items without `step:N` enter in reading order. Without JavaScript, in print, or for a reader who asked for less motion, the complete figure shows. Allowed: none, step, reveal
title titulo string
The figure's name (its accessible title); a `# Heading` line in the body does the same.
caption legenda string
An italic aside under the figure; a `> quote` line in the body does the same.
desc string
One sentence a screen reader gets instead of the drawing. Written from the items when absent.
top string
What grows upward, printed on the left margin above the direction arrow (layers): `top: Abstraction`.
bottom string
What sits at the bottom, printed under the direction arrow (layers): `bottom: Silicon`.
left string
A rotated axis label on the left margin (pyramid, funnel): `left: Rarer · fewer · compounds ↑`.

Body

Items, separated by a --- line. One `- Name · sublabel {tags}` per line; a `---` line starts a new group where the type has groups. Tags in braces: `focal` (the one item in the accent), `step:N` (the motion step), `tag:L3` (the index tag), `side:~48/yr` (a note beside the item), `value:240` (a quantity: a funnel's widths follow it).

mermaid renders: client

A diagram in mermaid's grammar, drawn by Pele (pele.run) unless the fence says `renderer:mermaid`: Pele lays a diagram out in well under a millisecond, adapts it to a phone and paints it in the page's theme. Mermaid draws what Pele does not (ZenUML; the `handDrawn` look; `themeCSS`). Either way the colours are the page's (theme keys diagram_*), unless the diagram names its own in mermaid's configuration (`%%{init: {"theme": "forest", "themeVariables": {…}}}%%`, or `config:` in its front matter), which both renderers follow. The one block with no @ spelling: a mermaid fence renders on GitHub, Obsidian, Notion and GitLab, which read the first word of the fence line and ignore the rest.

Rendered in the browser.

Example

```mermaid
flowchart LR
  A --> B
```

What it draws

flowchart LR
  A --> B

Arguments

renderer renderizador enum
Who draws it. `pele` (the default) is many times faster and follows the page's theme with no redraw; `mermaid` keeps mermaid's own drawing, for what only it does. A reader can compare a page both ways with `?diagrams=pele` or `?diagrams=mermaid` in the address. Allowed: pele, mermaid
look enum Default: page
`editorial`: the diagram in the manner of diagram-design — one accent on the node classed `focal`, the others in ink and muted by their class (`store`, `external`, `input`, `optional`, `security`, via `:::class` or `class A focal`), the name in sans 600 over a mono sublabel (`<br/>` splits them), edge labels in small mono capitals, and arrows in steps when the configuration says `%%{init: {"flowchart": {"curve": "stepAfter"}}}%%`. `page` (the default): mermaid's usual look in the page's colours. Allowed: page, editorial

Body

A diagram, in mermaid's own grammar. Mermaid source, in mermaid's own grammar, configuration included. With `look:editorial`, `# key: value` lines in the body set the sheet (`# unit:`, `# scale: 120 by 20`, `# legend: A; B {x:220}`, `# trend:`, `# source:`), and a `{x: y:}` tag on a row label pins its position; `look:page` ignores them.

Layout directives

Lines of ::: arrange the page — bands, columns, grids, media — around ordinary markdown. Every argument is a choice from a list, never CSS, and every layout works from a phone to an ultra-wide screen, in light and dark.

:::section

A band of the page: its width, its surface (or a picture under it, with a shade that keeps text readable) and the space around it. Everything inside flows top to bottom.

sticky Default: none
top holds the whole band at the top of the window while the page scrolls — a contact strip and a :::nav inside it stay together. Give the nav inside no sticky of its own. Allowed: none, top
width Default: normal
normal keeps the reading width, wide uses the page width, full runs edge to edge. Allowed: normal, wide, full
surface Default: default
The band's background, from the theme: soft (its surface colour), faint (a step lighter than soft, 40% of it on the background), alt (the theme's second ground, surface_alt: a grey band beside peach ones; not set, a neutral grey that follows neither the surface nor the accent), tint (a wash of its accent), accent (the accent itself), inverse (the theme turned over), fade (the surface colour at the top paling into the page's background at the bottom; set the theme's surface for its colour). Text colours are chosen for contrast — on a fade, against both ends — in light and dark schemes. Allowed: default, soft, faint, alt, tint, accent, inverse, fade
media Default: none
background lays the band's first picture (alone in its paragraph) under the whole band, behind the text, as a hero's: a photo band, a marble closing band. The band stays as tall as what it holds; the picture covers it, cropped to fit. Allowed: none, background
shade Default: dark
Over a background picture: dark (light text) or light (dark text), strong enough for 4.5:1 on any photo. Under light the theme's heading and button colours stay where they read on the wash, and links read at 4.5:1 in both schemes. Allowed: dark, light
tile Default: none
With media:background, repeats the picture as a texture (a marble, paper, a pattern) instead of covering the band with it, each tile 160px (small), 320px (medium) or 640px (large) wide and never stretched; shade: keeps the text readable as on a photo. The editor's preview shows the picture covering the band; the page tiles it. Allowed: none, small, medium, large
edge_top Default: none
The band's top edge as a shape instead of a straight line — wave, torn (paper), curve or slant — cut out of the band so the page shows through, like the bands of fdl.co (wave) and digfamily.co (torn). The band grows by the shape's height, so nothing inside is cut. Allowed: none, wave, torn, curve, slant
edge_bottom Default: none
The band's bottom edge as a shape: wave, torn, curve or slant. Same as edge_top, at the bottom. Allowed: none, wave, torn, curve, slant
space Default: 3
Space above and below, a step of the theme's scale. Allowed: 0, 1, 2, 3, 4, 5
space_top Default: auto
The space above in px (space_top:52), instead of space:'s step, to match a measured design to the pixel. auto keeps space:'s. Allowed:
space_bottom Default: auto
The space below in px (space_bottom:31), instead of space:'s step. auto keeps space:'s. Allowed:
font Default: inherit
The face of the band's own text: inherit, heading, ui (the theme's face for controls, font_ui) or a local stack — a broker's contact strip and breadcrumb are Poppins over Open Sans. Allowed: inherit, heading, ui, system, serif, mono, arial
align Default: left
Where text sits. narrow-center keeps it left on wide screens and centres it on a phone, where a stacked page reads better centred: a switch by screen width, not a narrow column (for that, measure:). Allowed: left, center, narrow-center
measure Default: auto
How wide the band's paragraphs and lists run: auto (the theme's reading width), narrow (about 28 characters), medium (about 40: a lede of two lines under a wide headline, as passare.com's hero sets it) or wide (about 60). Under align:center the column stays centred. Headings keep the band's width, so a headline can run wider than the lede under it. Allowed: auto, narrow, medium, wide
flow Default: auto
The space between one thing and the next inside it, a step of the theme's scale: one space for everything, whatever the things are. auto keeps each element's own margins, which is what prose wants — a heading further from the paragraph above it than from the one below. Allowed: auto, 0, 1, 2, 3, 4, 5
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
motion Default: none
How it appears as the reader scrolls to it; items of a layout arrive one after another. Nothing moves for a reader who asks for reduced motion, and without JavaScript everything is simply there. Allowed: none, fade, rise, scale
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::section width:wide surface:soft space:4 align:center
# Automate your routine
Everything between the lines is ordinary markdown.
:::

:::hero

The opening of a page: at least a given height, content centred — with its first or last thing pinned to the top or bottom edge if asked — optionally over a background image with a shade that keeps text readable.

height Default: half
auto fits the content, half is half the window, screen fills it. Allowed: auto, half, screen
media Default: none
background puts the first image inside the hero behind the text. Allowed: none, background
shade Default: dark
Over a background image: dark (light text) or light (dark text), strong enough for 4.5:1 on any photo. Allowed: dark, light
tile Default: none
With media:background, repeats the picture as a texture (a marble, paper, a pattern) instead of covering the hero with it, each tile 160px (small), 320px (medium) or 640px (large) wide and never stretched; shade: keeps the text readable as on a photo. The editor's preview shows the picture covering the hero; the page tiles it. Allowed: none, small, medium, large
align Default: center
Where the content sits. narrow-center is left on wide screens and centred on a phone: a switch by screen width, not a narrow column (for that, measure:). Allowed: center, left, narrow-center
width Default: wide
How wide the content may get. Allowed: normal, wide, full
measure Default: auto
How wide the band's paragraphs and lists run: auto (the theme's reading width), narrow (about 28 characters), medium (about 40: a lede of two lines under a wide headline, as passare.com's hero sets it) or wide (about 60). Under align:center the column stays centred. Headings keep the band's width, so a headline can run wider than the lede under it. Allowed: auto, narrow, medium, wide
surface Default: default
The ground when there is no background image (see section surface). alt is the theme's second ground (surface_alt). fade is the theme's surface colour at the top paling into the page's background at the bottom, the text chosen to read on both ends. Allowed: default, soft, alt, tint, accent, inverse, fade
edge_top Default: none
The band's top edge as a shape instead of a straight line — wave, torn (paper), curve or slant — cut out of the band so the page shows through, like the bands of fdl.co (wave) and digfamily.co (torn). The band grows by the shape's height, so nothing inside is cut. Allowed: none, wave, torn, curve, slant
edge_bottom Default: none
The band's bottom edge as a shape: wave, torn, curve or slant. Same as edge_top, at the bottom. Allowed: none, wave, torn, curve, slant
pin Default: none
Keeps the hero's first thing at its top edge (a logo, an eyebrow), its last at the bottom (a row of logos, a hint to scroll), or both, while the rest stays centred. It shows when the hero is taller than its content: height half or screen. Allowed: none, first, last, both
flow Default: auto
The space between one thing and the next inside it, a step of the theme's scale: one space for everything, whatever the things are. auto keeps each element's own margins, which is what prose wants — a heading further from the paragraph above it than from the one below. Allowed: auto, 0, 1, 2, 3, 4, 5
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
motion Default: none
How it appears as the reader scrolls to it; items of a layout arrive one after another. Nothing moves for a reader who asks for reduced motion, and without JavaScript everything is simply there. Allowed: none, fade, rise, scale
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::hero height:screen media:background shade:dark
![A desk at sunrise](/uploads/desk.jpg)
# Work that runs itself
Automate the routine between your tools.
:::

:::split

Two parts side by side — text and media — that stack when there is not room for both. By ratio, the two share the width; with a rail, the first is a side column of a fixed width and the other takes the rest.

Its items are separated by a --- line.

ratio Default: 1/2
How much of the width the first part takes. Allowed: 1/3, 1/2, 2/3
side Default: left
Which part comes first on wide screens; on narrow ones the first item is always on top. Allowed: left, right
align Default: center
Vertical alignment of the two parts. Allowed: start, center, end
space Default: 3
The gap, a step of the theme's scale. Allowed: 1, 2, 3, 4, 5
narrow Default: stack
stack puts the parts one above the other when narrow; keep keeps them side by side. Allowed: stack, keep
reverse Default: none
narrow puts the second part on top when the parts stack, so a picture written after its text comes first on a phone. Allowed: none, narrow
sticky Default: none
Which part stays in place while the other scrolls past it, as a portfolio's side column does. It only sticks while the parts are side by side, never when they stack. Allowed: none, first, second
rail Default: none
Makes the first part a side column of that width, in rem, and gives the other part everything else — a side menu, a portfolio's rail, a form beside a text. The side keeps its width on any screen instead of growing with it, and the parts stack when the other would get less than half. With a rail, ratio is not used. Allowed: none, 12, 16, 20, 24
flow Default: auto
The space between one thing and the next inside it, a step of the theme's scale: one space for everything, whatever the things are. auto keeps each element's own margins, which is what prose wants — a heading further from the paragraph above it than from the one below. Allowed: auto, 0, 1, 2, 3, 4, 5
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
motion Default: none
How it appears as the reader scrolls to it; items of a layout arrive one after another. Nothing moves for a reader who asks for reduced motion, and without JavaScript everything is simply there. Allowed: none, fade, rise, scale
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::split ratio:1/2 side:right
## Text first
A paragraph that sits beside the picture.
---
![Product](/uploads/product.png)
:::

:::columns

Items side by side in equal columns, all stacking at once when the row gets too narrow.

Its items are separated by a --- line.

threshold Default: 40
Below this width, in rem, the columns stack. Allowed: 30, 40, 50, 60
limit Default: 4
With more items than this, they stack whatever the width. Allowed: 2, 3, 4, 5
align Default: stretch
Vertical alignment of the columns. Allowed: start, center, end, stretch
items Default: plain
card draws each item as a card; stat sets each item's heading as a large number (it counts up when motion is on); step numbers the items as a process. Allowed: plain, card, stat, step
number Default: default
With items:stat, the colour of the number: default is the heading colour, accent the theme's accent as text (moved until it reads on the ground it sits on, a band's included), muted its secondary text colour. Allowed: default, accent, muted
caption Default: muted
With items:stat, the line under the number: muted (secondary text colour) or plain, the body text as any paragraph. Allowed: muted, plain
size Default: normal
With items:stat, how large the number is drawn, always in proportion to its column: normal (about 30-60px), large (38-72px), display (45-88px), for a site whose figures are the page's largest type. The top of each range needs a wide column: in a section of the default width, three columns draw large at about 53px; width:wide or fewer columns reach it. Allowed: normal, large, display
space Default: 3
The gap, a step of the theme's scale. Allowed: 1, 2, 3, 4, 5
flow Default: auto
The space between one thing and the next inside it, a step of the theme's scale: one space for everything, whatever the things are. auto keeps each element's own margins, which is what prose wants — a heading further from the paragraph above it than from the one below. Allowed: auto, 0, 1, 2, 3, 4, 5
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
motion Default: none
How it appears as the reader scrolls to it; items of a layout arrive one after another. Nothing moves for a reader who asks for reduced motion, and without JavaScript everything is simply there. Allowed: none, fade, rise, scale
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::columns items:card
### Plan
Tell us what you need.
---
### Build
We build it with you.
---
### Launch
It goes live.
:::

:::grid

As many items per row as fit, each at least `min` wide; one per row on a phone. An item can span more columns or rows with :::cell.

Its items are separated by a --- line.

min Default: 16
The smallest an item may get, in rem, before the row wraps. Allowed: 8, 10, 12, 14, 16, 18, 20, 24, 28
cols Default: auto
At most this many items per row, however wide the page gets. Six items with cols:3 come out as two rows of three instead of five and one alone. A phone still gets one per row. Allowed: auto, 2, 3, 4
items Default: plain
card draws each item as a card; stat sets each item's heading as a large number (it counts up when motion is on); step numbers the items as a process. Allowed: plain, card, stat, step
number Default: default
With items:stat, the colour of the number: default is the heading colour, accent the theme's accent as text (moved until it reads on the ground it sits on, a band's included), muted its secondary text colour. Allowed: default, accent, muted
caption Default: muted
With items:stat, the line under the number: muted (secondary text colour) or plain, the body text as any paragraph. Allowed: muted, plain
size Default: normal
With items:stat, how large the number is drawn, always in proportion to its column: normal (about 30-60px), large (38-72px), display (45-88px), for a site whose figures are the page's largest type. The top of each range needs a wide column: in a section of the default width, three columns draw large at about 53px; width:wide or fewer columns reach it. Allowed: normal, large, display
align Default: stretch
Vertical alignment of items in a row. Allowed: stretch, start, center
space Default: 3
The gap, a step of the theme's scale. Allowed: 1, 2, 3, 4, 5
flow Default: auto
The space between one thing and the next inside it, a step of the theme's scale: one space for everything, whatever the things are. auto keeps each element's own margins, which is what prose wants — a heading further from the paragraph above it than from the one below. Allowed: auto, 0, 1, 2, 3, 4, 5
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
motion Default: none
How it appears as the reader scrolls to it; items of a layout arrive one after another. Nothing moves for a reader who asks for reduced motion, and without JavaScript everything is simply there. Allowed: none, fade, rise, scale
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::grid min:16 items:card
### Fast
Pages render in milliseconds.
---
### Typed
Nothing you write becomes CSS.
:::

:::cell

Inside a grid item: how many columns and rows that item takes (bento layouts), and which layer it sits on.

span Default: 1
Columns the item takes; full takes the whole row. On a phone every item is one column. Allowed: 1, 2, 3, 4, full
rows Default: 1
Rows the item takes. Allowed: 1, 2, 3
layer Default: 0
Stacking order when items overlap (with offset). Allowed: 0, 1, 2, 3
flow Default: auto
The space between one thing and the next inside it, a step of the theme's scale: one space for everything, whatever the things are. auto keeps each element's own margins, which is what prose wants — a heading further from the paragraph above it than from the one below. Allowed: auto, 0, 1, 2, 3, 4, 5
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::grid min:14
:::cell span:2 rows:2
![Hero shot](/uploads/hero.jpg)
:::
---
### Small tile
:::

:::card

A panel: a surface, padding, the theme's radius, an optional border and shadow.

tone Default: soft
The panel's surface, with contrast-checked text (see section surface). alt is the theme's second ground (surface_alt), as on a band. ok, warn, info and danger are a status: the panel takes a light wash of the colour a pill of that status wears, for a notice, a result or a warning. Allowed: default, soft, alt, tint, accent, inverse, ok, warn, info, danger
media Default: inset
bleed: a frameless picture (`:::cover frame:none`) that opens the card runs to the card's edges, under the card's top corners, as a listing card shows its photo; the text keeps the card's padding. Allowed: inset, bleed
border Default: none
A hairline border. Allowed: none, line
text Default: inherit
The size of the panel's own text, in px, whatever the page's body size: a site whose body is 12px writes its chips at 15 (text:15). Allowed: inherit, 12, 13, 14, 15, 16, 18
font Default: inherit
The face of the panel's own text: inherit (the page's body face), heading (the theme's heading face), ui (the theme's face for controls, font_ui) or a local stack that loads nothing (system, serif, mono, arial) — a broker's search chips are Arial on an Open Sans page. Allowed: inherit, heading, ui, system, serif, mono, arial
heading Default: normal
How large the panel's own headings are: normal (the theme's), large (20px and bold, as a call-to-action tile's line is set) or larger (22px, a listing's count above its cards), whatever the theme's heading scale. Allowed: normal, large, larger
height Default: auto
How tall the panel stands at least, its content centred top to bottom: auto (as tall as what it holds), short (about 190px), medium (300px, a broker's call-to-action tile) or tall (400px). Allowed: auto, short, medium, tall
shadow Default: none
A shadow under the panel. Allowed: none, soft, lifted
space Default: 2
Padding inside, a step of the theme's scale. Allowed: 1, 2, 3, 4
offset Default: 0
Pull the element up into the content above it, in steps of the scale. Allowed: 0, up-1, up-2, up-3
tilt Default: none
A slight rotation, a few degrees. Allowed: none, left, right
flow Default: auto
The space between one thing and the next inside it, a step of the theme's scale: one space for everything, whatever the things are. auto keeps each element's own margins, which is what prose wants — a heading further from the paragraph above it than from the one below. Allowed: auto, 0, 1, 2, 3, 4, 5
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
motion Default: none
How it appears as the reader scrolls to it; items of a layout arrive one after another. Nothing moves for a reader who asks for reduced motion, and without JavaScript everything is simply there. Allowed: none, fade, rise, scale
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::card tone:accent shadow:lifted
### Founding plan
Everything, for the first hundred creators.
:::

:::inline

Items in a line that wraps: buttons, tags, logos, small facts.

Its items are separated by a --- line.

justify Default: start
How the line is distributed. Allowed: start, center, end, between
align Default: center
Vertical alignment within a line. Allowed: center, start, end
space Default: 2
The gap, a step of the theme's scale. Allowed: 1, 2, 3, 4
space_top Default: auto
The room above the line in px (space_top:34), instead of the line's own margin, to match a measured design. Allowed:
space_bottom Default: auto
The room under the line in px (space_bottom:46), instead of the line's own margin. Allowed:
sticky Default: none
top keeps the line at the top of the screen while the page scrolls under it, below the app's header: a few buttons that change how the page is viewed (Pele / Mermaid, light / dark), with no bar behind them. Allowed: none, top
logos Default: none
A logo strip: every picture in the line at one height — small 24px, medium 32px, large 48px — linked or not, drawn whole, a wide wordmark held to five times its height, and, without space:, a wider gap. A linked picture with alt text ([![App Store](/f/badge.png)](url)) is always the picture, never a button. Allowed: none, small, medium, large
logos_tone Default: original
Recolours every picture in the line: dark draws them black, for white-on-transparent logos on a light ground; light draws them white, for dark logos on an accent, inverse or photo ground. original keeps their colours. In a reader's dark scheme the two swap, so the logos stay visible on the dark ground. Allowed: original, dark, light
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::inline justify:center
[Start free](/signup)
---
[See pricing](/pricing)
:::

:::cover

Media cropped to a ratio, optionally in a device frame.

ratio Default: 16/9
The shape the image or video is cropped to. Allowed: 16/9, 16/10, 3/2, 4/3, 5/4, 1/1, 4/5, 3/4, 2/3, 9/16, 2/1, 21/9
focus Default: center
Which part of the media stays in view when it is cropped. Allowed: center, top, bottom, left, right
frame Default: rounded
none, rounded corners, a circle (avatars), a browser window or a phone around the media. Allowed: none, rounded, circle, browser, phone
shadow Default: none
A shadow under the media. Allowed: none, soft, lifted
shade Default: none
A dark wash over the media so what an overlay writes on it reads: bottom darkens the lower half (a price under a photo), top the upper half, dark the whole picture evenly. A plain overlay on a shaded cover writes in white. Allowed: none, bottom, top, dark
size Default: full
How wide the media is, never wider than its column: full fills it, half is half of it, medium up to 512px (a video poster beside text), small 96px (a headshot in a byline; with frame:circle, round), icon 40px (a feature's icon, drawn whole, never cropped). small and icon are square unless ratio: says otherwise; in a centred band or hero the media sits in the middle. Allowed: full, half, medium, small, icon
offset Default: 0
Pull the element up into the content above it, in steps of the scale. Allowed: 0, up-1, up-2, up-3
tilt Default: none
A slight rotation, a few degrees. Allowed: none, left, right
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
motion Default: none
How it appears as the reader scrolls to it; items of a layout arrive one after another. Nothing moves for a reader who asks for reduced motion, and without JavaScript everything is simply there. Allowed: none, fade, rise, scale
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::cover ratio:16/9 frame:browser shadow:lifted
![The dashboard](/uploads/dashboard.png)
:::

:::overlay

Content placed over its parent and kept inside it: a badge on a picture, or — with kind:plain — anything at all, a card over a photo, a caption, a play button.

at Default: center
Where on the parent it sits. Allowed: center, top-left, top-right, bottom-left, bottom-right, bottom
kind Default: badge
badge draws it as a small pill, which is what a label on a picture wants. plain draws nothing of its own: whatever is inside — a card, a heading, a button — sits over the parent as it is, never larger than the parent, scrolling inside itself if it would be. tags: each paragraph a small capitalised tag on a dark ground, stacked down the corner, as a listing marks its photo (exclusive, for sale, available); a paragraph that is only a picture stays a picture, a favourite button above the tags. Allowed: badge, plain, tags
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::cover ratio:4/3
![Studio](/uploads/studio.jpg)
:::overlay at:top-right
**New**
:::
:::

:::masonry

Items of different heights packed into columns, like a photo wall. Reading order runs down each column.

Its items are separated by a --- line.

min Default: 16
The narrowest a column may get, in rem. Allowed: 12, 14, 16, 18, 20, 24
items Default: plain
card draws each item as a card. Allowed: plain, card
space Default: 3
The gap, a step of the theme's scale. Allowed: 1, 2, 3, 4
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
motion Default: none
How it appears as the reader scrolls to it; items of a layout arrive one after another. Nothing moves for a reader who asks for reduced motion, and without JavaScript everything is simply there. Allowed: none, fade, rise, scale
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::masonry min:14 items:card
"Short quote." — Ana
---
A longer testimonial that takes more lines than the others.
:::

:::marquee

A strip that scrolls by itself, for logos or short quotes. It pauses on hover and stands still for a reader who asks for reduced motion.

Its items are separated by a --- line.

speed Default: normal
How fast the strip moves. Allowed: slow, normal, fast
direction Default: left
Which way it moves. Allowed: left, right
space Default: 4
The gap between items, a step of the theme's scale. Allowed: 1, 2, 3, 4, 5
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::marquee speed:slow
![Northwind](/demo/layout/logo-northwind.svg)
---
![Acme](/demo/layout/logo-acme.svg)
---
![Globex](/demo/layout/logo-globex.svg)
:::

:::nav

A site's navigation bar: the brand, then the links (a list item with a list under it is a menu), then the actions (lone links become buttons). On a phone the links move to their own scrolling row. A menu: `- Product` (or a link) with its links indented under it opens a panel, on hover, click, tap or Enter; the words after a link on its line are its second, muted line (`- [Families](./families) For the families you serve`); a label in the panel with links under it is a titled column (`- Popular features`, then its links), so a mega menu is two levels: deeper lists are drawn plain, and validate says so. On a phone the panel opens under the whole bar, or, with phone:drawer, the links are behind a menu button and each menu is a fold inside that drawer.

Its items are separated by a --- line.

sticky Default: none
top keeps the bar at the top of the page while scrolling. Allowed: none, top
surface Default: default
The bar's ground, with contrast-checked text. Allowed: default, soft, inverse
width Default: wide
How wide the bar's content may get. Allowed: wide, full
brand Default: normal
How tall the brand's picture is drawn: normal (the height of a line of text), small, or large (a wide logo with a wordmark, twice as tall). Allowed: normal, small, large
links Default: plain
plain: the links in the bar's text colour, the page being read underlined. quiet: the links in the muted colour and semi-bold, the page being read in the accent with no line, as a shop's or a broker's menu is drawn. Allowed: plain, quiet
space Default: normal
The room between the links: normal, or tight (about a word's width), for a menu of five or six on one line. Allowed: normal, tight
line Default: subtle
The line under the bar: the border colour, the accent colour, or none. Allowed: subtle, accent, none
height Default: normal
How tall the bar stands: normal (its contents and a little air), or tall (101px, a small logo floating in a roomy white bar, as a broker's or a shop's header is drawn). Allowed: normal, tall
text Default: inherit
The size of the menu's links, in px (text:15), whatever the page's body size: a broker's menu is 15px on a 12px page. Allowed: inherit, 12, 13, 14, 15, 16, 18
ground Default: solid
The bar's ground: solid, or veil (90% of it, the page showing faintly through as it scrolls under a sticky bar, as a broker's header does). Allowed: solid, veil
phone Default: row
Where the links go on a phone: row puts them on a row of their own under the brand that scrolls sideways; drawer hides them behind a menu button at the end of the bar (the actions stay in the bar, unless phone_actions:drawer) that opens them as a panel under the whole bar, one link per line, each menu a fold that opens its links under its label. Wider than a phone both are one bar. Allowed: row, drawer
phone_actions Default: bar
With phone:drawer, where the actions go on a phone: bar keeps them beside the menu button on the bar's one line (the brand's picture gives way and the buttons are drawn smaller); drawer leaves the bar the brand and the menu button alone and draws the actions at the bottom of the drawer, one full-width button per line, as passare.com's header does on a phone. Wider than a phone the actions are the bar's either way. Without phone:drawer they stay in the bar. Allowed: bar, drawer
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::nav sticky:top
**Orbit**
---
- [Features](~/features)
- [Pricing](~/pricing)
- [Blog](~/blog)
---
[Download](~/download)
:::

:::banner

A band pinned to an edge of the screen — a cookie notice, an announcement, a promotion — with anything inside. Without a script it is a band at the end of the page, where it was written; with one it floats, and can be closed.

Its items are separated by a --- line.

position Default: bottom
Where it sits once a script pins it: along the bottom edge, along the top, in the middle over the dimmed page (where the reader answers before going on), or as a card in the bottom corner. Bands on the bottom edge stack, never overlap: one with no close and no @consent (a call bar) holds the edge, and a cookie notice sits on top of it until answered. Allowed: bottom, top, center, corner
shape Default: flat
flat runs edge to edge; floating is a card with a margin, the theme's corners and a shadow. The middle and the corner are always a card. Allowed: flat, floating
dismiss Default: none
Whether the reader may close it without answering: never; until the page is opened again; or for good, remembered on this site by the band's id. A `@consent` inside closes it when answered, whatever this says. Allowed: none, once, remember
surface Default: default
The band's ground, with contrast-checked text. Allowed: default, soft, inverse
width Default: wide
How wide the band's content may get. Allowed: wide, full
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::banner position:bottom dismiss:remember surface:inverse id:cookies
Este site usa vídeos do YouTube, que carregam cookies do Google.
---
[Saiba mais](/privacidade)
:::

:::sidenav

A side menu, top to bottom: one link per line, each a full-width row with its icon; a line of only bold text names a group, and --- starts the next group. The link to the page being read is marked, which is how a template's side menu shows where the reader is.

Its items are separated by a --- line.

size Default: normal
How tall each row is: normal suits a side menu, compact a long one. Allowed: normal, compact
current Default: pill
How the link to the page being read is marked: a soft pill behind the row, a line at its start, or only bolder text. Allowed: pill, line, bold
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::sidenav
**Account**

[`icon:user` Profile](./profile)

[`icon:settings` Preferences](./preferences)
---
**Space**

[`icon:palette` Look](./look)
:::

:::rows

A list of settings or facts, one row per item: the first line is the row's title, the next its hint, and the last line — whatever it holds: a value, a button, a `switch:on`, a `pill:` — sits at the row's end. A row whose title is a link opens it from anywhere on the row, with a chevron at the end.

Its items are separated by a --- line.

inset Default: none
none draws hairlines between rows on the page itself; card puts the rows in a rounded panel of their own, the grouped list of a phone's settings. Allowed: none, card
space Default: 2
How much room each row has above and below, a step of the theme's scale. Allowed: 1, 2, 3
end Default: last
last puts the item's last line at the row's end (when the item has more than one line); none keeps every line under the title. Allowed: last, none
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::rows
**Reader notes**

Readers can mark a passage and leave a note beside it.

`switch:on`
---
**Display name**

`dropdown:Ana Ceramics`
---
[**Address and domain**](./address)

`pill:warn:Waiting for DNS`
:::

:::shell

An app's frame: a side column (the first item, usually a :::sidenav) beside the main part (the second item, usually a template's :::slot). On a wide screen it is a panel with the side column at a fixed width; on a phone it fills the screen, the side column goes away and a first line of the main part that is a link with `icon:chevron-left` becomes the bar that goes back. In the main part a `#` heading is the screen's title, with a hairline under it, and a `##` heading is a small muted label over a group of rows, as on a settings screen; a bigger heading inside the main part is a `###`.

Its items are separated by a --- line.

rail Default: 16
The side column's width, in rem. Allowed: 14, 16, 18, 20
frame Default: panel
panel draws the frame as a raised panel with the theme's radius and a shadow, over the page's ground; plain draws no panel; full makes the shell the page: edge to edge, from the top, at least as tall as the screen, with no radius or shadow (with ```view standalone: true it is the whole screen a reader gets). Allowed: panel, plain, full
divider Default: line
A hairline between the side column and the main part. Allowed: line, none
narrow Default: back
What the side column becomes on a phone: back drops it and keeps only the way back; drawer adds a Menu button to that bar, which opens the side column as a drawer from the start edge, the current page marked. Allowed: back, drawer
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::shell
:::sidenav
[`icon:user` Profile](./profile)

[`icon:settings` Preferences](./preferences)
:::
---
[`icon:chevron-left` Settings](./settings)

:::slot
:::
:::

:::timeline

A sequence of steps or events joined by a line: an order's tracking, a stepper, an activity feed, an onboarding. Each item, separated by ---, is a step: its first line the title, the next ones its details (a date, who did it). `state:done`, `state:current`, `state:upcoming`, `state:error` or `state:skipped` written in an item gives its marker and says where it is in words; an item that is only a heading names a group (Today, In progress); a :::timeline inside an item is its sub-steps.

Its items are separated by a --- line.

direction Default: vertical
vertical runs down the page; horizontal runs across, as a stepper, and turns vertical when the page is narrow. Allowed: vertical, horizontal
marker Default: dot
What sits on the line at each step: a dot coloured by its state; the step's number; or the `icon:` the item's first line starts with. Allowed: dot, number, icon
line Default: solid
The line that joins the steps. Allowed: solid, dashed, none
density Default: normal
How much room each step has: compact suits a long feed. Allowed: normal, compact
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::timeline
**Pedido criado** `state:done`

10 mar 2026
---
**Em trânsito** `state:current`

Royal Mail · previsão 12 mar
---
**Entregue** `state:upcoming`

:::drawer

A panel that slides in from an edge of the screen over the page, holding anything at all. The first item is what its button says (words, an `icon:` too); the second is what it holds. Without a script both are on the page where they were written; with one the button opens the panel, and the reader closes it with its × button, Escape, a tap outside, or by following a link inside.

Its items are separated by a --- line.

edge Default: end
The edge it slides in from: end is the right in a left-to-right page and the left in a right-to-left one; start the other side; top and bottom slide down or up. Allowed: end, start, top, bottom
size Default: normal
How much of the screen it takes: from the side, its width (18, 22 or 32rem, or all of it); from the top or the bottom, up to a height (a third, half, three quarters, or all of it), shorter when what it holds is. Allowed: narrow, normal, wide, full
collapse Default: always
always is a drawer at every width; narrow keeps what it holds on the page where it was written while the page is wide, and makes it a drawer behind its button on a phone. Allowed: always, narrow
surface Default: default
The panel's ground, with contrast-checked text. Allowed: default, soft, inverse
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::drawer edge:start
`icon:menu` Etapas
---
:::sidenav
[Intake](./intake)

[Risco](./risco)
:::
:::

:::tabs

Panels that take turns in one place, one tab each: Details, Timeline, Notes. Each item, separated by ---, is a tab; its first line — a heading, or a line that is only bold — names it, and the rest is its panel. Without a script every panel is on the page under its own name; with one the reader picks a tab (arrow keys too), and a link to anything inside a panel opens it.

Its items are separated by a --- line.

style Default: line
line underlines the tab that is open, along a hairline; pill draws the tabs as a row of buttons, the open one filled. Allowed: line, pill
hide Default: none
Hide on narrow screens (phones) or on wide ones, to show a different arrangement for each. Allowed: none, narrow, wide
id
A name for this block, so a link can land on it (`[Spaces](#spaces)`) and an agent can address it. Written as the element's id, never as a class. Without one, a link to a heading inside a band lands on the heading — halfway down its column in a split, with the picture cut off above it. Allowed: letters, numbers, dashes and underscores, starting with a letter or a number

Example

:::tabs
### Detalhes

Cliente: Ana Ceramics
---
### Timeline

Em trânsito desde 10 mar.
---
### Notas

Sem notas.
:::

:::slot

In a template (a page other pages wear): where the wearing page goes. Everything around it — a nav, a side column, a footer — is what those pages have in common. A named slot holds a default that a page may replace with :::fill.

name Default: main
main is where the page's own content goes, and a template needs one. The others are places a page may fill; what is written inside the slot is what shows when it does not. Allowed: main, hero, aside, top, bottom, cta

Example

:::nav
**[Studio](~)**
---
- [Work](~/work)
- [About](~/about)
:::

:::slot
:::

:::slot name:cta
## Let's talk
[Write to us](~/contact)
:::

:::fill

In a page that wears a template: what goes into one of the template's named slots instead of its default. It leaves the page's own flow and shows where the template put that slot.

name Default: aside
The slot to fill. One the template does not have stays where it was written, so nothing a person wrote disappears. Allowed: hero, aside, top, bottom, cta

Example

:::fill name:cta
## Hiring designers
[See the roles](~/jobs)
:::

# The page's own content