Skip to content

Authoring Guide

Glyph JS extends standard Markdown with a component system that turns plain text into interactive, visually rich documents. This guide covers everything you need to know to author Glyph Markdown files, from basic syntax to advanced features like cross-block references and layout modes.

Standard Markdown

Glyph Markdown is a superset of CommonMark. All standard Markdown features work exactly as you would expect.

Headings

# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6

Inline formatting

**Bold text** and *italic text* and ~~strikethrough~~.
Inline `code` uses backticks. [Links](https://example.com) and
![images](https://example.com/image.png) use the standard syntax.

Lists

- Unordered item A
- Unordered item B
- Nested item
1. Ordered item one
2. Ordered item two
1. Nested ordered item

Blockquotes

> This is a blockquote.
>
> It can span multiple paragraphs.

Code blocks

Standard fenced code blocks are fully supported with automatic syntax highlighting. GlyphJS uses highlight.js grammars to tokenize code and applies --glyph-code-token-* CSS custom properties for theming.

```typescript
const greeting: string = "Hello, Glyph!";
console.log(greeting);
```

Supported languages include the 42 common languages from highlight.js (JavaScript, TypeScript, Python, Rust, Go, Java, C/C++, SQL, YAML, JSON, etc.) plus an extended set of functional and math/scientific languages:

  • Functional: Scala, Haskell, Clojure, Elixir, Erlang, F#, OCaml, Elm, Scheme, SML, Lisp, ReasonML, Hy, Flix, Clean
  • Math / scientific: Julia, MATLAB, Mathematica, LaTeX, Scilab, Maxima, Gauss, Stan, Stata, Fortran, Mizar, Coq, Prolog

Unknown or missing languages fall back to plain unstyled text.

Customizing token colors — override the CSS custom properties on any ancestor element:

.my-document {
--glyph-code-token-keyword: #d73a49;
--glyph-code-token-string: #032f62;
--glyph-code-token-comment: #6a737d;
--glyph-code-token-number: #005cc5;
--glyph-code-token-function: #6f42c1;
--glyph-code-token-type: #e36209;
--glyph-code-token-builtin: #6f42c1;
--glyph-code-token-attr: #005cc5;
--glyph-code-token-literal: #005cc5;
--glyph-code-token-operator: #d73a49;
--glyph-code-token-variable: #e36209;
--glyph-code-token-regexp: #032f62;
--glyph-code-token-meta: #6a737d;
}

Images

![Alt text describing the image](https://example.com/photo.png "Optional title")

Images render inside a <figure> element with lazy loading enabled by default.

Thematic breaks

---

A horizontal rule separates sections visually.


YAML Frontmatter

Every Glyph Markdown file can begin with a YAML frontmatter block enclosed in --- fences. Frontmatter controls document-level metadata and layout behavior.

---
glyph-id: my-document
title: System Architecture
layout:
mode: document
spacing: relaxed
---

Supported frontmatter fields

FieldTypeDescription
glyph-idstringStable document identifier. Used for cross-document references and deterministic IR output. If omitted, an ID is derived from the file path or content hash.
titlestringDocument title. If omitted, the compiler infers it from the first h1 heading.
descriptionstringShort description. If omitted, inferred from the first paragraph.
authorsstring[]List of author names.
tagsstring[]Tags for categorization.
varsobjectCompile-time scalar variables. String values are interpolated wherever {{key}} appears in prose or ui: YAML fields. See Variables & Macros.
layoutobjectLayout configuration (see Layout Modes below).

Variables & Macros

Glyph Markdown supports a compile-time variable system that eliminates repetition. All substitution happens before the IR is produced — the runtime and the reader see the final values, not the variable syntax.

Scalar variables

Define scalars in the vars: frontmatter key or in a ui:vars block, then reference them with {{key}} in prose or in the YAML fields of any ui: block:

---
vars:
company: Acme Corp
quarter: Q1 2026
---
# {{company}} — {{quarter}} Report
```ui:callout
type: info
title: "{{quarter}} Update"
content: "{{company}} achieved strong results this quarter."
```

Block variables

Bind a name to an entire ui: component by appending =name to the lang string. A _ prefix suppresses the initial render:

```ui:callout=_note
type: info
content: "Internal use only."
```
{{note}}
More text.
{{note}}

Each {{note}} reference in a standalone paragraph is replaced with a clone of the block.

Parameterized templates

Templates are suppressed block variables with named parameter slots:

```ui:callout=_kpi(label, value)
type: info
title: "{{label}}"
content: "{{value}}"
```
{{kpi("Revenue", "$13.1M")}}
{{kpi("NPS Score", "72")}}

For the full reference — including ui:vars, scalar expansion rules, arity errors, and diagnostics — see the Variables & Macros guide.


UI Components — the ui: Fenced Block Syntax

Glyph JS introduces interactive components via a special fenced code block syntax. Any fenced code block whose language identifier starts with ui: is treated as a Glyph UI block rather than a regular code block.

How it works

```ui:component-name
# YAML payload goes here
key: value
```

The parser:

  1. Detects any fenced code block whose language starts with ui:.
  2. Strips the ui: prefix to determine the component type (e.g., graph, table, callout).
  3. Parses the body of the block as YAML.
  4. Extracts the reserved keys glyph-id and refs (if present) before passing the remaining data to the component.
  5. Replaces the code node in the AST with a GlyphUIBlock node.

The YAML payload is validated against the component’s Zod schema at compile time by @glyphjs/compiler. The parser itself does not validate schemas — it handles only syntax.

Reserved YAML keys

Three top-level YAML keys have special meaning and are stripped from the component data before schema validation:

KeyPurpose
glyph-idAssigns a stable, user-defined block ID for cross-block references.
refsDeclares outgoing references to other blocks (see Cross-block References).
interactiveWhen set to true, enables interaction event emission for this block (see Interaction Events).

All other keys are passed through as the component’s data payload.


Component Catalog

Glyph JS ships eight built-in components. Each is described below with its full YAML schema and an example.

Callout — ui:callout

Highlighted blocks for tips, warnings, errors, and informational notes. Useful for drawing the reader’s attention to important content.

Schema fields:

FieldTypeRequiredDescription
type"info" | "warning" | "error" | "tip"YesVisual style of the callout.
titlestringNoOptional heading displayed above the content.
contentstringYesThe callout body. Supports Markdown formatting (re-parsed by the compiler).

Example:

```ui:callout
type: tip
title: Use glyph-id for stable references
content: |
Assigning a `glyph-id` to your blocks ensures that references
remain valid even when you reorder content.
```

Graph — ui:graph

Interactive node-and-edge diagrams. Supports DAGs, flowcharts, mind maps, and force-directed layouts. Rendered with D3 and Dagre.

Schema fields:

FieldTypeRequiredDescription
type"dag" | "flowchart" | "mindmap" | "force"YesGraph variant.
nodesarrayYesList of node objects (see below).
edgesarrayYesList of edge objects (see below).
layout"top-down" | "left-right" | "bottom-up" | "radial" | "force"NoLayout direction. Defaults vary by graph type.

Node object:

FieldTypeRequiredDescription
idstringYesUnique node identifier within this graph.
labelstringYesDisplay text for the node.
typestringNoSemantic type (e.g., "service", "database"). Used for styling.
styleRecord<string, string>NoCSS-like style overrides.
groupstringNoGrouping key for clustering nodes visually.

Edge object:

FieldTypeRequiredDescription
fromstringYesSource node ID.
tostringYesTarget node ID.
labelstringNoText displayed on the edge.
typestringNoSemantic type (e.g., "depends-on").
styleRecord<string, string>NoCSS-like style overrides.

Example:

```ui:graph
glyph-id: architecture-graph
type: dag
nodes:
- id: api
label: API Gateway
type: service
- id: auth
label: Auth Service
type: service
- id: db
label: PostgreSQL
type: database
edges:
- from: api
to: auth
label: authenticates
- from: auth
to: db
label: queries
layout: top-down
```

Table — ui:table

Sortable, filterable data tables with optional aggregation. Column types enable type-aware sorting and filtering.

Schema fields:

FieldTypeRequiredDescription
columnsarrayYesColumn definitions (see below).
rowsarrayYesArray of row objects. Each row is a key-value record matching column keys.
aggregationarrayNoAggregation functions applied to columns (see below).

Column object:

FieldTypeRequiredDescription
keystringYesProperty name used to look up the value in each row.
labelstringYesDisplay header for the column.
sortablebooleanNoWhether the column supports click-to-sort.
filterablebooleanNoWhether the column shows a filter control.
type"string" | "number" | "date" | "boolean"NoData type hint for sorting and filtering behavior.

Aggregation object:

FieldTypeRequiredDescription
columnstringYesColumn key to aggregate.
function"sum" | "avg" | "count" | "min" | "max"YesAggregation function.

Example:

```ui:table
columns:
- key: name
label: Name
sortable: true
filterable: true
type: string
- key: role
label: Role
type: string
- key: experience
label: Years of Experience
sortable: true
type: number
rows:
- name: Alice
role: Engineer
experience: 8
- name: Bob
role: Designer
experience: 5
- name: Carol
role: Manager
experience: 12
aggregation:
- column: experience
function: avg
```

Chart — ui:chart

Line, bar, area, and OHLC (financial) charts. Rendered with D3.

Schema fields:

FieldTypeRequiredDescription
type"line" | "bar" | "area" | "ohlc"YesChart variant.
seriesarrayYesData series (see below).
xAxisobjectNoX-axis configuration: key (data field) and optional label.
yAxisobjectNoY-axis configuration: key (data field) and optional label.
legendbooleanNoWhether to show the legend.

Series object:

FieldTypeRequiredDescription
namestringYesSeries display name.
dataarrayYesArray of data-point records. Each record maps string keys to number or string values.

Example:

```ui:chart
type: line
series:
- name: Revenue
data:
- { month: Jan, value: 4200 }
- { month: Feb, value: 5100 }
- { month: Mar, value: 4800 }
- name: Expenses
data:
- { month: Jan, value: 3100 }
- { month: Feb, value: 3400 }
- { month: Mar, value: 3200 }
xAxis:
key: month
label: Month
yAxis:
key: value
label: USD
legend: true
```

Relation — ui:relation

Entity-relationship diagrams for modeling data structures and their connections. Similar to ui:graph but requires cardinality on relationships and treats nodes as entities with typed attributes.

Schema fields:

FieldTypeRequiredDescription
entitiesarrayYesEntity definitions (see below).
relationshipsarrayYesRelationship definitions (see below).
layout"top-down" | "left-right"NoLayout direction.

Entity object:

FieldTypeRequiredDescription
idstringYesUnique entity identifier.
labelstringYesDisplay name.
attributesarrayNoList of attribute objects with name (string), type (string), and optional primaryKey (boolean).

Relationship object:

FieldTypeRequiredDescription
fromstringYesSource entity ID.
tostringYesTarget entity ID.
labelstringNoRelationship label.
cardinality"1:1" | "1:N" | "N:1" | "N:M"YesCardinality constraint.

Example:

```ui:relation
entities:
- id: user
label: User
attributes:
- name: id
type: uuid
primaryKey: true
- name: email
type: string
- name: name
type: string
- id: post
label: Post
attributes:
- name: id
type: uuid
primaryKey: true
- name: title
type: string
- name: body
type: text
- id: comment
label: Comment
attributes:
- name: id
type: uuid
primaryKey: true
- name: text
type: text
relationships:
- from: user
to: post
label: authors
cardinality: "1:N"
- from: post
to: comment
label: has
cardinality: "1:N"
- from: user
to: comment
label: writes
cardinality: "1:N"
layout: top-down
```

Timeline — ui:timeline

Chronological event sequences rendered as a visual timeline. Useful for project milestones, incident reports, or system evolution histories.

Schema fields:

FieldTypeRequiredDescription
eventsarrayYesEvent objects (see below).
orientation"vertical" | "horizontal"NoTimeline orientation. Defaults to vertical.

Event object:

FieldTypeRequiredDescription
datestringYesDate or datetime string (e.g., "2026-01-15" or "2026-01-15T09:00:00Z").
titlestringYesEvent heading.
descriptionstringNoDetailed description of the event.
typestringNoSemantic type for styling (e.g., "milestone", "incident", "release").

Example:

```ui:timeline
events:
- date: "2026-01-15"
title: Project kickoff
description: Initial planning and team formation.
type: milestone
- date: "2026-02-01"
title: Alpha release
description: Core parser and compiler shipped.
type: release
- date: "2026-03-01"
title: Beta release
description: Runtime and all built-in components ready.
type: release
- date: "2026-04-01"
title: v1.0 stable
description: Full test suite, documentation, and playground.
type: milestone
orientation: vertical
```

Tabs — ui:tabs

Tabbed content containers. Each tab holds Markdown content that the compiler re-parses, so you can use full Markdown formatting inside tabs.

Schema fields:

FieldTypeRequiredDescription
tabsarrayYesTab objects (see below).

Tab object:

FieldTypeRequiredDescription
labelstringYesTab heading displayed in the tab bar.
contentstringYesMarkdown string. Parsed recursively by the compiler to produce child blocks.

Example:

```ui:tabs
tabs:
- label: Overview
content: |
This is the **overview** tab with standard Markdown.
It can contain multiple paragraphs, lists, and inline formatting.
- label: Installation
content: |
Install via your package manager:
```bash
pnpm add @glyphjs/runtime @glyphjs/components
```
- label: Configuration
content: |
Edit `glyph.config.ts` to set up your theme and register
components.
- Choose a layout mode
- Configure your color scheme
```

Steps — ui:steps

Sequential step-by-step guides with progress indication. Each step has a title, an optional status, and Markdown content.

Schema fields:

FieldTypeRequiredDescription
stepsarrayYesStep objects (see below).

Step object:

FieldTypeRequiredDescription
titlestringYesStep heading.
status"pending" | "active" | "completed"NoVisual progress indicator.
contentstringYesMarkdown string. Parsed recursively by the compiler.

Example:

```ui:steps
steps:
- title: Install dependencies
status: completed
content: |
Run `pnpm install` to install all packages.
- title: Configure the project
status: active
content: |
Edit `glyph.config.ts` to set up your theme and register
the built-in components.
- title: Build and deploy
status: pending
content: |
Run `pnpm build` and deploy the output to your hosting
provider.
```

Cross-block References

References create navigable links between blocks, enabling explorable, interconnected documents. For example, a table can link to a graph, allowing users to click through from a data row to the relevant node in a diagram.

Assigning a block ID with glyph-id

To reference a block, it needs a stable identifier. Add the glyph-id key to any ui: block’s YAML payload:

```ui:graph
glyph-id: architecture-graph
type: dag
nodes:
- id: api
label: API Gateway
- id: db
label: Database
edges:
- from: api
to: db
```

The compiler strips glyph-id from the component data before schema validation. If no glyph-id is provided, the compiler generates a deterministic, content-addressed ID automatically.

Rules for glyph-id:

  • Must be unique within the document.
  • Use lowercase kebab-case by convention (e.g., team-table, deploy-steps).
  • The compiler validates uniqueness and reports a diagnostic if duplicates are found.

Declaring references with refs

The refs array declares outgoing references from one block to another. Each ref must specify a target — the glyph-id of the destination block.

```ui:table
glyph-id: team-table
columns:
- key: name
label: Name
- key: role
label: Role
rows:
- name: Alice
role: Engineer
- name: Bob
role: Designer
refs:
- target: architecture-graph
type: data-source
label: "See architecture diagram"
```

Reference fields:

FieldTypeRequiredDescription
targetstringYesThe glyph-id of the target block.
typestringNoSemantic type: "navigates-to", "details", "depends-on", "data-source", or a custom type prefixed with custom:.
labelstringNoHuman-readable label displayed on the reference link.
sourceAnchorstringNoSub-element within the source block (e.g., a specific node ID or row key).
targetAnchorstringNoSub-element within the target block.
bidirectionalbooleanNoIf true, the reference is navigable in both directions. Defaults to false.

Inline Markdown references (future)

The syntax [text](#glyph:block-id) is reserved for inline cross-block navigation within standard Markdown paragraphs. The compiler will resolve these into Reference objects. This feature is planned for a future release.

Unresolved references

If a refs entry points to a glyph-id that does not exist in the document, the compiler emits a warning diagnostic and marks the reference as unresolved. The IR is still produced — unresolved references do not block compilation.


Layout Modes

Layout modes control how the document’s blocks are arranged on screen. Set the mode in your YAML frontmatter under the layout key.

Document mode (default)

Single-column, reading-optimized layout with a configurable maximum width. Blocks flow top-to-bottom in source order. This is the default when no layout is specified.

---
layout:
mode: document
maxWidth: "960px"
spacing: normal
---

Dashboard mode

A CSS grid layout with configurable columns. Blocks are placed into a grid, and you can control per-block placement using blockLayout overrides keyed by glyph-id.

---
layout:
mode: dashboard
columns: 3
spacing: compact
blockLayout:
architecture-graph:
gridColumn: "1 / 3"
span: 2
team-table:
gridColumn: "3"
---

This places the architecture-graph block across the first two columns and the team-table in the third column.

Presentation mode

Full-viewport, one-block-at-a-time display — similar to a slide deck. Each top-level block occupies the full screen, and the user navigates between them.

---
layout:
mode: presentation
spacing: relaxed
---

Layout properties reference

PropertyTypeDescription
mode"document" | "dashboard" | "presentation"Layout strategy.
columnsnumberNumber of grid columns (dashboard mode).
maxWidthstringCSS max-width value (document mode).
spacing"compact" | "normal" | "relaxed"Vertical spacing between blocks.
blockLayoutRecord<string, BlockLayoutOverride>Per-block layout overrides keyed by block glyph-id.

BlockLayoutOverride fields:

FieldTypeDescription
gridColumnstringCSS grid-column value.
gridRowstringCSS grid-row value.
spannumberNumber of columns the block should span.

Interaction Events

Glyph JS components can emit interaction events when users interact with them — clicking chart data points, sorting tables, answering quiz questions, expanding file tree nodes, and more. This enables host applications to react to user behavior, log analytics, or feed interactions back into an LLM conversation.

Enabling interaction events

Add the reserved interactive: true key to any ui: block’s YAML payload:

```ui:chart
interactive: true
type: bar
series:
- name: Revenue
data:
- { month: Jan, value: 4200 }
- { month: Feb, value: 5100 }
xAxis:
key: month
yAxis:
key: value
```

The interactive key is stripped before schema validation, just like glyph-id and refs. When interactive is true, the runtime injects an onInteraction callback into the component’s props.

Supported events by component

ComponentEvent kindTrigger
ui:quizquiz-submitUser submits an answer.
ui:tabletable-sortUser clicks a sortable column header.
ui:tabletable-filterUser changes a column filter.
ui:tabstab-selectUser switches tabs.
ui:accordionaccordion-toggleUser expands or collapses a section.
ui:filetreefiletree-selectUser clicks a file or directory.
ui:graphgraph-node-clickUser clicks a graph node.
ui:chartchart-selectUser clicks a data point or bar.
ui:comparisoncomparison-selectUser clicks an option column header.

Consuming events in host applications

Register an onInteraction callback when creating the runtime:

import { createGlyphRuntime, debounceInteractions } from '@glyphjs/runtime';
const runtime = createGlyphRuntime({
ir: compiledDocument,
components: builtinComponents,
onInteraction: debounceInteractions((event) => {
console.log(event.kind, event.payload);
// Send to analytics, update app state, or feed back to an LLM
}, 300),
});

The debounceInteractions helper debounces events per-stream (keyed by blockId + kind), so rapid interactions like repeated sorting do not flood your callback.

Event structure

Every interaction event includes:

FieldTypeDescription
kindstringDiscriminant identifying the event type (e.g., "chart-select").
timestampstringISO 8601 timestamp of the interaction.
documentIdstringThe Glyph IR document ID (injected by the runtime).
blockIdstringThe block’s unique ID.
blockTypestringThe block’s component type (e.g., "ui:chart").
payloadobjectEvent-specific data (varies by kind).

All event types are exported from @glyphjs/types for use in TypeScript applications.


Best Practices

Write for both humans and machines

Glyph Markdown is designed to be authored by LLMs and read by humans. Keep your YAML payloads clean and well-structured so that both audiences can understand the document at a glance.

Use glyph-id on any block you might reference

Even if you do not need cross-block references today, assigning a glyph-id makes your block IDs stable and human-readable. Content-addressed IDs change when you edit the block’s content.

Keep YAML payloads focused

Each ui: block should represent a single, self-contained visualization. If you find yourself putting too much data into a single block, consider splitting it into multiple blocks and linking them with refs.

Leverage standard Markdown for narrative

Use headings, paragraphs, lists, and blockquotes around your ui: blocks to provide narrative context. A graph without an explanation is hard to interpret; a paragraph without a visualization can be hard to grasp. Combine both for maximum clarity.

Use frontmatter for document metadata

Always include at least a title in your frontmatter. This ensures the compiler produces clean metadata even when the document structure changes.

---
title: Quarterly Review
layout:
mode: document
spacing: normal
---

Validate early with the compiler

Run @glyphjs/compiler during development. It validates every ui: block’s YAML payload against its Zod schema and reports errors with precise line and column numbers. Fix validation errors before sharing your document.

Use dashboard mode for data-dense documents

When your document contains multiple tables, charts, and graphs, switch to dashboard mode with a multi-column grid. Assign glyph-id values and use blockLayout to control placement.


Common Patterns

Narrative with embedded visualization

The most common pattern: prose before and after a ui: block providing context.

# System Architecture
The platform follows a three-tier architecture with an API gateway,
authentication service, and database layer.
```ui:graph
type: dag
nodes:
- id: api
label: API Gateway
- id: auth
label: Auth Service
- id: db
label: PostgreSQL
edges:
- from: api
to: auth
- from: auth
to: db
layout: top-down
```
All incoming requests pass through the API Gateway, which delegates
authentication before any data access occurs.

Linked table and graph

A table and a graph that reference each other, allowing navigation between the two views of the same data.

```ui:graph
glyph-id: service-map
type: flowchart
nodes:
- id: web
label: Web App
- id: api
label: API
- id: worker
label: Worker
edges:
- from: web
to: api
- from: api
to: worker
layout: left-right
```
```ui:table
glyph-id: service-details
columns:
- key: service
label: Service
- key: status
label: Status
- key: uptime
label: Uptime
type: number
rows:
- service: Web App
status: healthy
uptime: 99.9
- service: API
status: healthy
uptime: 99.7
- service: Worker
status: degraded
uptime: 97.2
refs:
- target: service-map
type: navigates-to
label: "View service map"
```

Step-by-step tutorial

Use ui:steps combined with ui:callout blocks for structured tutorials.

# Getting Started
```ui:steps
steps:
- title: Install the packages
status: completed
content: |
Run the following command:
```bash
pnpm add @glyphjs/runtime @glyphjs/components
```
- title: Create your first document
status: active
content: |
Create a file called `hello.md` and add a heading and a
`ui:callout` block.
- title: Compile and render
status: pending
content: |
Use the compiler to produce IR, then pass it to the runtime.
```
```ui:callout
type: info
title: What is next?
content: |
Once you have the basics working, explore the
Component Catalog to see all available visualizations.
```

Dashboard layout with multiple visualizations

Combine frontmatter layout configuration with glyph-id and blockLayout to create a data dashboard.

---
title: Q1 Metrics Dashboard
layout:
mode: dashboard
columns: 2
spacing: compact
blockLayout:
revenue-chart:
gridColumn: "1 / 3"
team-stats:
gridColumn: "1"
milestone-timeline:
gridColumn: "2"
---
# Q1 Metrics
```ui:chart
glyph-id: revenue-chart
type: bar
series:
- name: Revenue
data:
- { month: Jan, value: 42000 }
- { month: Feb, value: 51000 }
- { month: Mar, value: 48000 }
xAxis:
key: month
yAxis:
key: value
label: USD
```
```ui:table
glyph-id: team-stats
columns:
- key: team
label: Team
- key: headcount
label: Headcount
type: number
rows:
- team: Engineering
headcount: 12
- team: Design
headcount: 4
- team: Product
headcount: 3
```
```ui:timeline
glyph-id: milestone-timeline
events:
- date: "2026-01-15"
title: Planning complete
type: milestone
- date: "2026-02-01"
title: Alpha shipped
type: release
- date: "2026-03-15"
title: Beta shipped
type: release
orientation: vertical
```

Interactive document with LLM feedback loop

Use interactive: true to enable interaction events, then feed those events back into an LLM conversation for adaptive responses.

---
title: Architecture Review
glyph-id: arch-review
---
# Architecture Review
```ui:graph
glyph-id: system-graph
interactive: true
type: dag
nodes:
- id: api
label: API Gateway
group: backend
- id: auth
label: Auth Service
group: backend
- id: cache
label: Redis Cache
group: infra
- id: db
label: PostgreSQL
group: infra
edges:
- from: api
to: auth
label: authenticates
- from: api
to: cache
label: caches
- from: auth
to: db
label: queries
layout: top-down
```
Click any node above to learn more about that service.
```ui:table
glyph-id: service-metrics
interactive: true
columns:
- key: service
label: Service
sortable: true
- key: latency
label: P99 Latency (ms)
sortable: true
type: number
- key: uptime
label: Uptime %
sortable: true
type: number
rows:
- service: API Gateway
latency: 45
uptime: 99.9
- service: Auth Service
latency: 120
uptime: 99.7
- service: Redis Cache
latency: 2
uptime: 99.99
- service: PostgreSQL
latency: 15
uptime: 99.8
```

In the host application, wire onInteraction to your LLM API:

import { createGlyphRuntime, debounceInteractions } from '@glyphjs/runtime';
const runtime = createGlyphRuntime({
ir: compiledDocument,
components: builtinComponents,
onInteraction: debounceInteractions(async (event) => {
// Feed the interaction into the LLM conversation
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({
role: 'user',
content: `The user interacted with the document: ${JSON.stringify(event)}`,
}),
});
// The LLM can respond with new Glyph Markdown to render
const { markdown } = await response.json();
if (markdown) {
// Re-compile and update the runtime with the LLM's response
const newIr = compile(markdown);
runtime.update(newIr);
}
}, 500),
});

This pattern enables documents that respond to user exploration — clicking a graph node could prompt the LLM to generate a detailed breakdown of that service, sorting a table could trigger a summary of the sorted data.


Error Handling

The Glyph compiler uses a collect-all-errors strategy. Your document always produces valid IR output, even when errors are present.

Error typeBehavior
YAML parse errorThe block is preserved with its raw source text. A diagnostic is attached to the block.
Schema validation errorThe block is preserved with the original data. Zod error paths are included in the diagnostic.
Unresolved referenceA warning diagnostic is emitted. The reference is kept with unresolved: true.
Unknown component typeAn info diagnostic is emitted. The block is preserved as-is and renders a fallback placeholder.
UNDEFINED_VARIABLEA warning is emitted; the literal {{key}} text is preserved in the output.
CIRCULAR_VARIABLE_REFAn error is emitted; expansion stops and the literal is preserved.
UNDEFINED_BLOCK_VARA warning is emitted; the standalone {{name}} paragraph is kept as-is.
TEMPLATE_ARITY_MISMATCHAn error is emitted; the invocation paragraph is kept as-is.

Check the diagnostics array on the CompilationResult to find and fix issues. Each diagnostic includes severity (error, warning, or info), a message, and the source position in your Markdown file.