ZvessaDocs

Layout, text and tokens

Every page in Zvessa is built from the same small set of layout and text blocks. A block never holds a size, font or colour. It names a text role, a size step or a colour role, and the space's style says what those look like. Change a token once and every page follows.

On this page

The AI and MCP clients use these blocks through propose_change, like any other block. People add them by hand in the page editor (Page header, Section, Grid, Shelf, List rows, Space, Badge, Tags).

How a page is put together #

A calm page usually reads top to bottom like this:

  1. header: the page's title, with an optional small line over it, a line under it, a mark or logo, and one or two action buttons. When it is the first block it is the page title, and the bar at the top shows its title once you scroll (the iPhone large-title behaviour).
  2. section blocks, each with a small uppercase title and an optional "See all" link.
  3. Inside a section: a grid of cards or stats, a scroll shelf people swipe sideways, a row of buttons or badges, or a group of item rows.
  4. An item (or a section with open: true) that holds blocks opens them as their own screen, so a settings page can live inside one page.

Defaults are quiet: no extra lines or frames unless the style asks for them, small uppercase labels over groups, one icon per row.

Example #

json
[
  { "id": "top", "kind": "header", "props": { "title": "Studio", "eyebrow": "Today", "subtitle": "Everything happening in your space", "mark": "S" },
    "children": [{ "id": "top-search", "kind": "button", "props": { "icon": "search", "href": "#search" } }] },
  { "id": "glance", "kind": "section", "props": { "title": "At a glance", "action": "See all", "href": "#stats" }, "children": [
    { "id": "glance-grid", "kind": "grid", "props": { "columns": 2 }, "children": [
      { "id": "members", "kind": "stat", "props": { "label": "Members", "value": "128", "change": "12%", "trend": "up" } },
      { "id": "bookings", "kind": "stat", "props": { "label": "Bookings", "value": "24" } } ] } ] },
  { "id": "settings", "kind": "group", "props": { "title": "Your space" }, "children": [
    { "id": "people", "kind": "item", "props": { "title": "People & invites", "icon": "users", "href": "#people" } },
    { "id": "alerts", "kind": "item", "props": { "title": "Notifications", "icon": "bell", "value": "On", "href": "#alerts" } } ] }
]

Designing a header #

Everything about a header is a setting on the block:

WhatSettingOptions
Sizesizelarge (default, the big title), inline (a compact bar), hero (a tall band)
Heightheightcompact, regular, tall
Backgroundbackgroundnone (default), surface, tint, gradient, glass (frosted), image
Title styletitleVariantany text role below
Title fontfontbody, display, mono (the style's) or a font name
Title weightweight400, 500, 600, 700, 800
Title colourtitleTonea colour role or value, or gradient (accent to accent2)
Alignmentalignstart, center
Logomark / imagea letter, emoji or icon name; or an https picture
Colourtintthe mark and band colour
Line under itdividertrue or false
Actionschild button blocksicon-only buttons when they have an icon and no label

Text roles (tokens) #

Each role is a token in the style at type.roles.<role> with these settings: size (8-96 px, before type.scale), weight (400-800), font (body, display, mono or a font name), case (none or upper), tracking (-2 to 6 px), leading (1-2, line height as a multiple of size) and tone (a colour role). display, title and headline also follow the style's headingCase and tracking when they don't set their own.

Values below read: size · weight · font · case · tracking · leading · colour. A dash means the style's default.

RoleClassicFuturistic
display34 · 800 · display (system) · - · -0.4 · 1.15 · text34 · 800 · display (mono) · - · -0.4 · 1.15 · text
title28 · 700 · display (system) · - · -0.3 · 1.2 · text28 · 700 · display (mono) · - · -0.3 · 1.2 · text
headline22 · 700 · display (system) · - · - · 1.25 · text22 · 700 · display (mono) · - · - · 1.25 · text
subtitle17 · 600 · body (system) · - · - · 1.3 · text17 · 600 · body (system) · - · - · 1.3 · text
body15 · - · body (system) · - · - · 1.45 · text15 · - · body (system) · - · - · 1.45 · text
callout16 · - · body (system) · - · - · 1.45 · text216 · - · body (system) · - · - · 1.45 · text2
caption13 · - · body (system) · - · - · 1.35 · text212.5 · - · body (system) · - · - · 1.35 · text3
label12.5 · 600 · body (system) · upper · 0.6 · 1.3 · text310.5 · 500 · mono (mono) · upper · 1.3 · 1.3 · text3
overline11 · 600 · body (system) · upper · 1.2 · 1.3 · text310.5 · 500 · mono (mono) · upper · 1.3 · 1.3 · text3
number28 · 700 · display (system) · - · - · 1.1 · text28 · 500 · mono (mono) · - · - · 1.1 · text
quote17 · - · body (system) · - · - · 1.5 · text217 · - · body (system) · - · - · 1.5 · text2
code13 · - · mono (mono) · - · - · 1.5 · text13 · - · mono (mono) · - · - · 1.5 · text

To change one for a whole space, change the look, for example:

json
{ "op": "add", "path": "/look/changes/type/roles/title", "value": { "size": 32, "font": "serif" } }

A page's own look (/pages/N/look) can do the same for that page only.

Other tokens the blocks read #

TokenWhereWhat it does
type.body, type.display, type.monostyleThe three fonts roles point at
type.scalestyleScales every role (0.75-1.5)
space.densitystyleThe spacing unit: compact 6, regular 8, roomy 10 px. Size steps are xs 0.5, sm 1, md 2, lg 3, xl 5 units
shape.radius, shape.radiusSmallstyleCorners of cards, buttons, chips
shape.marksstyleLit corner marks on cards (Futuristic)
surface.treatment, surface.depthstyleFill, outline, glass or gradient; flat, shadow or glow
parts.card, parts.header, parts.button, parts.tile, parts.chipstyleRestyle one part: treatment, depth, radius, bg, text, line
Colour rolesstylebg, surface, raised, text, text2, text3, line, accent, accent2, onAccent, success, warn, danger, gold and any name a style adds

Cards #

SizeUse it for
smSmall squares in grids and shelves
mdThe everyday card (default)
lgA big card with room for a story
wideIcon or picture on the left, words on the right; takes the full width of a grid
heroTall, the picture fills it and the words sit on top; full width

Variants: default (the style's card), outline, filled (a soft tint), accent (solid colour, or a lit edge in outlined styles), glass, plain (no frame).

Every layout and text block #

The page's header (app bar), first on a page: a small line over the title (eyebrow), the title, a subtitle, an optional mark or logo, and its action buttons (children: button blocks, icon-only when they have an icon and no label). size 'large' is the phone's big title, 'inline' a compact bar title, 'hero' a tall picture band with the title on it. When it is the first block it replaces the page's own title, and the bar shows its title as you scroll.

SettingTypeWhat it does
titlestringTitle. Empty uses the page's name
subtitlestringA line under the title
eyebrowstringA small line over the title (the space's name, a date, a section)
sizestring'large' (default), 'inline' or 'hero'
alignstring'start' (default) or 'center'
markstringA letter, emoji or icon name in a square before the title (like an app's logo)
imagestringhttps URL: the picture behind a 'hero' header, or the logo square otherwise
tintstringColour of the mark square or the hero band without a picture: a style colour role. Default accent
titleVariantstringThe title's text role (display, title, headline, subtitle, body, callout, caption, label, overline, number, quote, code). Default display (large), subtitle (inline), title (hero)
titleTonestringThe title's colour: a style colour role or a colour value. 'gradient' paints it from accent to accent2
fontstringThe title's font: 'body', 'display' or 'mono' (the style's), or a font name (system, rounded, serif, mono…)
weightstringThe title's weight: 400, 500, 600, 700 or 800
backgroundstringBehind the header: 'none' (default, the page shows through), 'surface', 'tint' (a soft wash of tint), 'gradient' (tint to accent2), 'glass' (frosted, see-through) or 'image' (the picture in image)
heightstring'compact', 'regular' (default) or 'tall'
dividerbooleanA thin line under the header

Holds child blocks.

heading #

A title for a part of a page, with an optional small line over it and a line under it.

SettingTypeWhat it does
textstring, requiredThe words
levelnumber1 (title), 2 (headline), 3 (subtitle) or 4 (small label). Default 1
subtitlestringA quieter line under it
eyebrowstringA small line over it
alignstring'start' (default), 'center' or 'end'

text #

Words in one of the style's text roles. variant picks the role: display, title, headline, subtitle, body, callout, caption, label, overline, number, quote, code. body is a paragraph, callout a bigger quiet intro, caption small print, label and overline small capitals, number a big figure, quote a pulled quote, code fixed-width.

SettingTypeWhat it does
textstring, requiredThe words. New lines are kept
variantstringThe text role: display, title, headline, subtitle, body, callout, caption, label, overline, number, quote, code. Default body
alignstring'start' (default), 'center' or 'end'
tonestringA colour role from the style (accent, accent2, success, warn, danger, gold, text2…). Default depends on the block. Default the role's own
linesnumberShow at most this many lines, then …

list #

A list of short lines: bullets, numbers or ticks.

SettingTypeWhat it does
itemsstring[], requiredOne string per item
variantstring'bullet' (default), 'number' or 'check'

badge #

A small pill with a word or a count: New, Live, 3, Beta, Sold out.

SettingTypeWhat it does
textstring, requiredThe words
tonestringA colour role from the style (accent, accent2, success, warn, danger, gold, text2…). Default depends on the block. Default accent
iconstringAn icon name (home, chat, calendar, star, settings, users, bolt, game, coin…) or an emoji
variantstring'soft' (default: a light tint), 'solid' or 'outline'

chips #

A row of small tags that wraps: topics, skills, opening days, filters to read.

SettingTypeWhat it does
itemsstring[], requiredOne tag per item
tonestringA colour role from the style (accent, accent2, success, warn, danger, gold, text2…). Default depends on the block. Default neutral

card #

A framed box: a picture or icon, a small line over the title, the title, a line under it, text, a badge, and child blocks. size 'sm' (a small square for grids and shelves), 'md' (default), 'lg' (big, a picture on top), 'wide' (picture or icon on the left, words on the right) or 'hero' (tall, the picture fills it with the words on top). With href the whole card opens it.

SettingTypeWhat it does
titlestringTitle
textstringText
subtitlestringA line under the title
eyebrowstringA small line over the title
sizestring'sm', 'md' (default), 'lg', 'wide' or 'hero'
variantstring'default' (the style's card), 'outline', 'filled' (a tint of tint), 'accent' (solid tint), 'glass' or 'plain' (no frame)
imagestringhttps URL of a picture
iconstringAn icon name (home, chat, calendar, star, settings, users, bolt, game, coin…) or an emoji
tintstringColour of the icon square and of 'filled' and 'accent' cards: A colour role from the style (accent, accent2, success, warn, danger, gold, text2…). Default depends on the block
badgestringA small label in the corner (New, 2, Live)
hrefstring'#page-id' opens a page, 'https://…' a website, 'chat:<conversation key>' a conversation (e.g. chat:support, chat:general), 'ai' the AI chat (people who manage), 'mailto:' or 'tel:' a mail or a phone call
actionstringWords of a button at the bottom that opens href (Book, Open, Play)

Holds child blocks.

stat #

A big number with a label, and optionally its change (+12%) and a note.

SettingTypeWhat it does
labelstring, requiredWhat the number is
valuestring, requiredThe number or short value
changestringThe change, as people should read it: +12%, -3, New
trendstring'up', 'down' or 'flat': colours the change (up green, down red)
notestringA short line under it
iconstringAn icon name (home, chat, calendar, star, settings, users, bolt, game, coin…) or an emoji
hrefstring'#page-id' opens a page, 'https://…' a website, 'chat:<conversation key>' a conversation (e.g. chat:support, chat:general), 'ai' the AI chat (people who manage), 'mailto:' or 'tel:' a mail or a phone call

image #

A picture from a URL, in a shape you pick, with an optional caption.

SettingTypeWhat it does
srcstring, requiredhttps URL
altstringWhat the picture shows
ratiostringShape: 1:1, 4:3, 3:2, 16:9, 21:9, 3:4, 9:16. Default 16:9
captionstringSmall words under it
roundbooleanA circle (a face, a logo)

button #

A button that opens a page, a conversation, a link or the AI. With an icon and no label it is a round icon button (header actions).

SettingTypeWhat it does
labelstringButton words
hrefstring'#page-id' opens a page, 'https://…' a website, 'chat:<conversation key>' a conversation (e.g. chat:support, chat:general), 'ai' the AI chat (people who manage), 'mailto:' or 'tel:' a mail or a phone call
variantstring'primary' (default), 'secondary', 'plain' or 'danger'
iconstringAn icon name (home, chat, calendar, star, settings, users, bolt, game, coin…) or an emoji
sizestring'sm', 'md' (default) or 'lg'
fullbooleanFill the width

section #

A part of a page with a small title, an optional line under it and a link on the right (See all), holding child blocks. variant 'card' puts the children on one card. With open true it shows as one row that opens its children as their own screen (a settings page inside a page).

SettingTypeWhat it does
titlestringSmall title over the section
subtitlestringA line under the title
actionstringWords of the link on the right (See all, Edit)
hrefstringWhere the link goes: '#page-id' opens a page, 'https://…' a website, 'chat:<conversation key>' a conversation (e.g. chat:support, chat:general), 'ai' the AI chat (people who manage), 'mailto:' or 'tel:' a mail or a phone call
variantstring'plain' (default) or 'card'
openbooleanShow as one row that opens the children as their own screen
iconstringWith open: the row's icon. An icon name (home, chat, calendar, star, settings, users, bolt, game, coin…) or an emoji

Holds child blocks.

stack #

Lays out child blocks in a column (or a row).

SettingTypeWhat it does
directionstring'column' (default) or 'row'
gapnumberSpace between children in px, 0-64, default 12 (row and grid take size steps instead)
alignstring'stretch' (default), 'start', 'center' or 'end'

Holds child blocks.

row #

Child blocks side by side, wrapping onto the next line when they don't fit: buttons, badges, small cards, stats.

SettingTypeWhat it does
gapstringSpace between: xs, sm, md, lg, xl. Default sm
alignstringUp and down: 'start', 'center' (default), 'end' or 'stretch'
justifystringAcross: 'start' (default), 'center', 'end' or 'between'
equalbooleanEvery child gets the same width (stats, cards)

Holds child blocks.

grid #

Child blocks in columns of equal width: cards, stats, pictures. A child can span more columns with props.span.

SettingTypeWhat it does
columnsnumberColumns on a phone, 1 to 6. Default 2
columnsWidenumberColumns on a tablet or the web, 1 to 8. Default twice columns, up to 4
gapstringSpace between: xs, sm, md, lg, xl. Default sm

Holds child blocks.

scroll #

A shelf of child blocks people swipe sideways: cards, pictures, stats. Each child is as wide as its size (cards) or itemSize.

SettingTypeWhat it does
itemSizestringWidth of children that don't say: 'sm', 'md' (default), 'lg' or 'full'
gapstringSpace between: xs, sm, md, lg, xl. Default sm
snapbooleanStop on each child. Default true

Holds child blocks.

group #

Grouped list rows on one card with thin lines between them (a settings list, a menu, a contact card). Its children are usually item blocks.

SettingTypeWhat it does
titlestringSmall title over the group
footerstringA small note under it
variantstring'inset' (default: on a card) or 'plain' (rows on the page)

Holds child blocks.

item #

One list row: an icon or picture, a title, a line under it, a value on the right, a badge, and an arrow when it opens something. Opens href, or, when it holds child blocks, opens them as their own screen titled by the row.

SettingTypeWhat it does
titlestring, requiredTitle
subtitlestringA line under the title
iconstringAn icon name (home, chat, calendar, star, settings, users, bolt, game, coin…) or an emoji
tintstringColour of the icon square: A colour role from the style (accent, accent2, success, warn, danger, gold, text2…). Default depends on the block. Default accent
tonestringHow the icon square is painted: 'soft' (default), 'solid' or 'glossy'
imagestringhttps URL of a round picture in place of the icon (a face, a logo)
valuestringShort words on the right (On, 3 members, $40)
badgestringA small pill on the right (New, 2)
hrefstring'#page-id' opens a page, 'https://…' a website, 'chat:<conversation key>' a conversation (e.g. chat:support, chat:general), 'ai' the AI chat (people who manage), 'mailto:' or 'tel:' a mail or a phone call
dangerbooleanRed title (Delete, Leave)
chevronbooleanThe arrow on the right. Default: shown when it opens something

Holds child blocks.

divider #

A thin line between parts, optionally with a word in the middle.

SettingTypeWhat it does
labelstringA word in the middle (or, Today)
insetbooleanStart the line after the space of an icon, like between list rows

spacer #

Empty space between parts.

SettingTypeWhat it does
sizestringxs, sm, md, lg, xl. Default md