llms.txt

Elements

Snaps are built from 16 components organized into four categories. Every component lives in ui.elements as a named entry. The type field names the component; props carries its configuration; children names child element IDs; on binds event handlers.

"my-element": {
  "type": "text",
  "props": { "content": "Hello" }
}
#ComponentCategoryDescription
1badgeDisplayInline label with color and icon
2buttonDisplayAction button with variants and icon
3iconDisplayStandalone icon from curated set
4imageDisplayHTTPS image with aspect ratio
5itemDisplayContent row with actions slot
6item_groupContainerGroups items into a styled list
7progressDisplayHorizontal progress bar
8separatorDisplayVisual divider
9stackContainerVertical or horizontal layout
10textDisplayText block with size and weight
11bar_chartDataHorizontal bar chart with labeled bars
12cell_gridDataColored cell grid, optionally interactive
13inputFieldText or number input
14sliderFieldNumeric range slider
15switchFieldBoolean toggle
16toggle_groupFieldSingle or multi-select choice group

Field components (input, slider, switch, toggle_group) collect user input. Their values are sent in the POST payload under inputs[name] when a submit action fires.


badge

Inline label with color and optional icon. Use for metadata, status indicators, and counts alongside content. "default" (filled) draws attention; "outline" is subtler. Pair with an icon for scannability.

NewLiveERC-20
PropTypeRequiredDefaultDescription
labelstringYesDisplay text. Max 30 chars
variantstringNo"default""default" (filled) or "outline" (bordered)
colorPaletteColorNo"accent"Badge color
iconIconNameNoLeading icon
{ "type": "badge", "props": { "label": "New" } }
{ "type": "badge", "props": { "label": "Live", "color": "green", "icon": "zap" } }
{ "type": "badge", "props": { "label": "ERC-20", "variant": "outline", "color": "blue" } }

button

The only component that fires actions — bind them via on.press. Default variant is "secondary" (bordered); use "primary" (filled) for the main CTA, typically one per page. See Actions for the full list of action types.

PropTypeRequiredDefaultDescription
labelstringYesButton text. Max 30 chars
variantstringNo"secondary"Visual style
iconIconNameNoLeading icon

Variants

VariantDescription
primarySolid accent background, white text — primary CTA
secondaryAccent-colored border, transparent fill
{
  "type": "button",
  "props": { "label": "Submit", "variant": "primary" },
  "on": { "press": { "action": "submit", "params": { "target": "https://my-snap.com/" } } }
}
{
  "type": "button",
  "props": { "label": "Open" },
  "on": { "press": { "action": "open_url", "params": { "target": "https://example.com" } } }
}

icon

Standalone icon from the curated set. Best as a visual accent inside item action slots or horizontal stacks. Avoid using icons as standalone content — pair with text or use inside a badge.

arrow-right
check
heart
star
zap
share
play
chevron-right
PropTypeRequiredDefaultDescription
nameIconNameYesIcon identifier
colorPaletteColorNo"accent"Icon color
sizestringNo"md""sm" (16px) or "md" (20px)
{ "type": "icon", "props": { "name": "star", "color": "amber" } }

Available Icons

CategoryIcons
Navigationarrow-right arrow-left external-link chevron-right
Statuscheck x alert-triangle info clock
Socialheart message-circle repeat share user users
Contentstar trophy zap flame gift
Mediaimage play pause
Commercewallet coins
Actionsplus minus refresh-cw bookmark
Feedbackthumbs-up thumbs-down trending-up trending-down

image

HTTPS image with fixed aspect ratio. Use "16:9" for hero and banner images, "1:1" for avatars or thumbnails, "4:3" for general photos, and "9:16" for tall portrait content.

PropTypeRequiredDescription
urlstringYesHTTPS URL. Supports jpg, png, gif, webp. GIFs autoplay and loop.
aspectstringYes"1:1" "16:9" "4:3" "9:16"
altstringNoAlt text for accessibility
{ "type": "image", "props": { "url": "https://example.com/photo.jpg", "aspect": "16:9" } }

item

The go-to component for structured content rows: leaderboards, settings, key-value info. Has a title, optional description, and an actions slot on the right side. Put badges, icons, or buttons in children for the action slot.

Engagement Score
Based on 24h activity
92
Settings
PropTypeRequiredDefaultDescription
titlestringYesPrimary text. Max 100 chars
descriptionstringNoSecondary text below title. Max 160 chars
variantstringNo"default"Visual style

Variants

VariantDescription
defaultNo background, no border

Children

Rendered in the actions slot (right side). Use for badges, icons, buttons, or any trailing content.

"score": {
  "type": "item",
  "props": { "title": "Engagement Score", "description": "Based on 24h activity" },
  "children": ["score-badge"]
},
"score-badge": { "type": "badge", "props": { "label": "92", "color": "green" } }
"nav": {
  "type": "item",
  "props": { "title": "Settings" },
  "children": ["nav-arrow"]
},
"nav-arrow": { "type": "icon", "props": { "name": "chevron-right", "color": "gray" } }

item_group

Wraps related items for visual grouping. Use separator: true for settings-style lists and border: true for card-like sections.

First place
Alice
Second place
Bob
Third place
Charlie
PropTypeRequiredDefaultDescription
borderbooleanNofalseShow border around the group
separatorbooleanNofalseShow divider lines between items
gapstringNoSpacing between items: "none" "sm" "md" "lg"

Children: item elements only.

"results": {
  "type": "item_group",
  "props": {},
  "children": ["r1", "r2", "r3"]
},
"r1": { "type": "item", "props": { "title": "First place", "description": "Alice" } },
"r2": { "type": "item", "props": { "title": "Second place", "description": "Bob" } },
"r3": { "type": "item", "props": { "title": "Third place", "description": "Charlie" } }

progress

Horizontal progress bar for completion, scores, or any bounded numeric value. Always uses the theme accent color. The label appears above the bar — use it for context like "78%" or "Level 3 of 5".

Upload progress
PropTypeRequiredDescription
valuenumberYesCurrent value (0 to max, finite)
maxnumberYesMaximum value (must be > 0, finite)
labelstringNoLabel text above the bar. Max 60 chars
{ "type": "progress", "props": { "value": 65, "max": 100, "label": "Upload progress" } }

separator

Visual divider between logical sections of a page. Most snaps use 2-4 separators. Overusing them creates visual clutter.

Section A

Section B
PropTypeRequiredDefaultDescription
orientationstringNo"horizontal""horizontal" or "vertical"
{ "type": "separator", "props": {} }

stack

Layout container for arranging children. Every page starts with a vertical stack as root. Use horizontal stacks for button rows, badge groups, or side-by-side cards. justify: "between" is useful for navigation bars.

Child 1
Child 2
Child 3
PropTypeRequiredDefaultDescription
directionstringNo"vertical""vertical" or "horizontal"
gapstringNo"md"Spacing between children: "none" "sm" "md" "lg"
justifystringNoContent alignment: "start" "center" "end" "between" "around"
"page": {
  "type": "stack",
  "props": {},
  "children": ["header", "content", "actions"]
}
"row": {
  "type": "stack",
  "props": { "direction": "horizontal", "gap": "sm" },
  "children": ["b1", "b2", "b3"]
}

text

The primary content element. Use weight: "bold" for headings and emphasis. Use size: "sm" for captions, timestamps, and secondary info.

Welcome to Snaps
Last updated 2 hours ago
PropTypeRequiredDefaultDescription
contentstringYesText content. Max 320 chars
sizestringNo"md""md" (body), "sm" (caption)
weightstringNo"normal""bold" "normal"
alignstringNo"left""left" "center" "right"
{ "type": "text", "props": { "content": "Welcome to Snaps", "weight": "bold" } }
{ "type": "text", "props": { "content": "Last updated 2 hours ago", "size": "sm", "align": "center" } }

bar_chart

Horizontal bar chart for displaying ranked or comparative data. Each bar shows a label on the left, a colored fill bar, and a numeric value on the right. Use for poll results, leaderboards, or any ranked values.

PropTypeRequiredDefaultDescription
barsobject[]Yes1–6 bar entries (see below)
maxnumberNomax valueUpper bound for bar scale
colorPaletteColorNo"accent"Default bar color

Bar Object

PropTypeRequiredDescription
labelstringYesBar label. Max 40 chars
valuenumberYesBar value (≥ 0)
colorPaletteColorNoPer-bar color override
{
  "type": "bar_chart",
  "props": {
    "bars": [
      { "label": "Poblano", "value": 42 },
      { "label": "Negro", "value": 38 },
      { "label": "Verde", "value": 15, "color": "green" }
    ]
  }
}

cell_grid

Grid of colored cells for pixel art, game boards, color pickers, and small data matrices. Cells are defined sparsely — only specify cells that have color or content. Use select to enable tap-to-select; taps write to POST inputs under name.

PropTypeRequiredDefaultDescription
namestringNo"grid_tap"POST inputs key for selection data
colsnumberYesColumn count (2–32)
rowsnumberYesRow count (2–16)
cellsobject[]YesSparse cell definitions (see below)
gapstringNo"sm"Cell spacing: "none" (0px) "sm" (1px) "md" (2px) "lg" (4px)
rowHeightnumberNo28Pixel height per row (8–64). Grid height = rows × rowHeight
selectstringNo"off"Selection mode: "off" "single" "multiple"

Cell Object

PropTypeRequiredDescription
rownumberYesRow index (0-based)
colnumberYesColumn index (0-based)
colorPaletteColorNoCell fill color
contentstringNoCell text content
{
  "type": "cell_grid",
  "props": {
    "cols": 4,
    "rows": 4,
    "cells": [
      { "row": 0, "col": 0, "color": "red" },
      { "row": 0, "col": 3, "color": "blue" },
      { "row": 1, "col": 1, "color": "green", "content": "X" },
      { "row": 3, "col": 3, "color": "purple" }
    ],
    "select": "multiple"
  }
}

input

Text or number input field for short free-text entry. Set type: "number" for numeric input (changes the mobile keyboard). Always provide a label for accessibility. Value is collected in POST inputs under name.

PropTypeRequiredDefaultDescription
namestringYesInput name (POST inputs key)
typestringNo"text""text" or "number"
labelstringNoLabel text above input. Max 60 chars
placeholderstringNoPlaceholder text. Max 60 chars
defaultValuestringNoPre-filled value
maxLengthnumberNoMax character count (1–280)

POST value: string.

{ "type": "input", "props": { "name": "email", "label": "Email", "placeholder": "you@example.com" } }

slider

Numeric range slider for bounded choices like ratings, quantities, or percentages. Always set meaningful min/max values and add a label so users know what they're adjusting. Value is collected in POST inputs under name.

Rating (1-10)7
PropTypeRequiredDefaultDescription
namestringYesSlider name (POST inputs key)
minnumberYesMinimum value (must be ≤ max)
maxnumberYesMaximum value (must be ≥ min)
stepnumberNo1Increment step (must be > 0, finite)
defaultValuenumberNomidpointInitial value (must be between min and max)
labelstringNoLabel text above slider. Max 60 chars

POST value: number.

{ "type": "slider", "props": { "name": "rating", "label": "Rating (1–10)", "min": 1, "max": 10 } }

switch

Boolean toggle for binary preferences (on/off, yes/no). Good for settings-style pages — the label should describe the enabled state ("Enable notifications", not "Notifications toggle"). Value is collected in POST inputs under name.

Enable notifications
PropTypeRequiredDefaultDescription
namestringYesSwitch name (POST inputs key)
labelstringNoLabel text beside the switch. Max 60 chars
defaultCheckedbooleanNofalseInitial checked state

POST value: boolean.

{ "type": "switch", "props": { "name": "notifications", "label": "Enable notifications" } }

toggle_group

Choice group for selecting between 2-6 discrete options. Prefer this over multiple buttons when the choices are parallel and exclusive. Use multiple: true for multi-select scenarios like tags or interests. Value is collected in POST inputs under name.

PropTypeRequiredDefaultDescription
namestringYesGroup name (POST inputs key)
optionsstring[]YesChoice labels. Min 2, max 6. Each max 30 chars
multiplebooleanNofalseAllow multiple selections
orientationstringNo"horizontal""horizontal" or "vertical"
defaultValuestring or string[]NoPre-selected option(s)
variantstringNo"default""default" (solid) or "outline" (bordered)
labelstringNoLabel text above the group. Max 60 chars

POST value: the selected option string (or string[] when multiple is true).

{ "type": "toggle_group", "props": { "name": "plan", "label": "Choose a plan", "options": ["Free", "Pro", "Team"] } }
{
  "type": "toggle_group",
  "props": {
    "name": "interests",
    "label": "Select interests",
    "multiple": true,
    "orientation": "vertical",
    "options": ["Dev", "Design", "Data", "Product"]
  }
}