---
title: "Syntax"
description: "The syntax of GistUI Lang - statements, components, named arguments, enums and flags, strings, references and pipe tables."
---

> Documentation Index
> Fetch the complete documentation index at: https://gistui.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Syntax

GistUI Lang is what the model writes. It is designed to be cheap in tokens, hard to get wrong, and renderable line by line. You rarely write it yourself, but reading it helps when you debug an answer or write a fixture.

## Statements

A program is a list of statements, one per line: `id = value`.

```gistui
root = Page(head, body)
head = Header("Q3 revenue", "All regions")
body = Card("Revenue grew **8%**.")
```

- `root` comes first. It is what gets drawn.
- An id may be used before it is defined. Order: `root`, then containers, then leaves, then data tables last.
- Ids are short and lowercase. Every id is defined once and used at least once.

## Components

```gistui
Name(positionals, children…, key:value)
```

```gistui
root = Card(Header("Storage", "4.2 of 5 GB used", size:sm), Progress(4.2, "Used", max:5, tone:warning), Buttons(Button("Upgrade"), Button("Manage", v:ghost)), gap:md)
```

| Part | Rule | Example |
|---|---|---|
| Positional arguments | Required props, in signature order | `Header("Storage", "4.2 of 5 GB used")` |
| Children | Any number of components or strings, after the positionals | `Card(a, b, c)` |
| Named arguments | Optional props, `key:value`, in any order | `size:sm`, `max:5` |

Optional props are **always named**. A skipped argument is never padded with `null` or `""`.

## Enums and flags are bare words

```gistui
row = Row(a, b, wrap, gap:lg)
card = Card(a, b, sunk)
tag = Tag("Live", success)
```

- `gap:lg`: an enum value, unquoted.
- `wrap`: a flag. The bare word turns a boolean prop on.
- `sunk`, `success`: an enum value alone sets the one prop that has it (`v:sunk`, `tone:success`).

The parser decides from the catalog, not from guessing. Two rules keep it unambiguous:

- A statement with that name always wins: `Card(a, row)` with `row = …` defined is a child.
- Inside a list, a bare word is a reference, so strings in lists are quoted: `icons:["user", "users"]`.

Flag names are reserved words and cannot be ids. The list is at the end of [the full reference](/docs/language/reference/).

## Strings

Strings are JSON strings: double quotes, `\n` for a new line, no raw line breaks. A string in child position is Markdown.

```gistui
root = Card("### Summary", "Revenue is **up 8%**. See the [full report](https://example.com).\n\n- Enterprise grew fastest\n- Churn fell")
```

Strings never interpolate. Join with `+`: `"Total: " + $count`.

## Tables

Data is written as pipe rows. A line that starts with `|` continues the table; the first line that does not ends it.

```gistui
root = Grid(Card(Chart(rev, type:bar, title:"Revenue")), Card(Table(rev)), cols:2)
rev = |Month|Revenue:n|Target:n
|Jul|380000|350000
|Aug|402000|375000
|Sep|431000|400000
```

- The first row is the header. `Revenue:n` marks a number column, `Name:s` a text column; without a hint the type comes from the first data row.
- The first column is the x axis or category. Every other column is a series.
- **One table can feed several components.** Here the same `rev` draws a chart and a table.
- Numeric cells may be written as `$1,200` or `45%`; charts get the number, tables keep the text.

`Chart`, `Table`, `Stats`, `Timeline`, `KeyValue` and `Pricing` all take a table.

## Comments, prose and fences

- A line starting with `#` is a comment.
- A line that is not a statement (a sentence the model added) is ignored, with a warning. It does not break the program.
- `gistui` code fences are stripped. In inline mode the text outside fences is chat text.
- `#gistui 1` on the first line names the format version. It is optional.

## What a model gets wrong, and what happens

The format defines how each common slip is read, so every implementation recovers the same way.

| Written | Read as |
|---|---|
| `'single quotes'` | a string |
| `key=value` | `key:value` |
| `card = Card(a, b` at the end of a line | the bracket is closed |
| `Card(a, b,)` | the trailing comma is ignored |
| `{"label": "x"}` | `{label: "x"}` |
| `// comment` | a comment |
| `size:"lg"` | `size:lg` |

Each is reported as a `lenient-syntax` warning. See [Diagnostics](/docs/reference/diagnostics/).

## Next

- [State and expressions](/docs/language/state-and-expressions/): `$state`, `@query`, `@each`, operators.
- [Edits and multi-turn](/docs/language/edits/): changing a UI that is already shown.
- [The full reference](/docs/language/reference/): the exact text the model receives.

Source: https://gistui.com/docs/language/index.mdx
