Skip to main content
Every block is a tagged object with a type field. You pass blocks to page.content, and each block’s optional style overrides its role style for that one block. Here is the full union once, then a section per block below.
type Block =
  | { type: "heading"; text: InlineContent; level?: 1 | 2 | 3 | 4 | 5 | 6; style?: StyleProperties }
  | { type: "paragraph"; text: InlineContent; style?: StyleProperties }
  | { type: "code"; text: string; language?: string; style?: StyleProperties }
  | { type: "formula"; text: string; style?: StyleProperties }
  | { type: "list"; items: InlineContent[]; ordered?: boolean; style?: StyleProperties }
  | { type: "image"; src: string; width?: number; height?: number; style?: StyleProperties }
  | { type: "divider"; style?: StyleProperties }
  | { type: "spacer"; size?: number }
  | { type: "note"; text: InlineContent; title?: InlineContent; variant?: "info" | "warn" | "success" | "muted"; style?: StyleProperties }
  | { type: "table"; rows: TableRow[]; headers?: TableRow; columns?: number | number[]; style?: StyleProperties }
  | { type: "chart"; chart: ChartKind; data: ChartData; height?: number; title?: string; legend?: boolean; style?: StyleProperties }
  | { type: "group"; children: Block[]; gap?: number; style?: StyleProperties };

heading

A title with a level from 1 to 6. text accepts inline content.
{ type: "heading", text: "Quarterly Report", level: 1 }

paragraph

A run of body text. text accepts inline content.
{ type: "paragraph", text: "Revenue grew across every region this quarter." }

code

A tinted monospace block. language is a label only and does not enable syntax highlighting.
{ type: "code", language: "ts", text: "const total = items.reduce((a, b) => a + b, 0);" }

formula

LaTeX, typeset to vector paths. See Formulas for math fonts.
{ type: "formula", text: "\\int_0^\\infty e^{-x^2}\\,dx = \\frac{\\sqrt{\\pi}}{2}" }

list

An ordered or unordered list. Each item is inline content.
{ type: "list", ordered: true, items: ["First", "Second", "Third"] }

image

References a file path or a name registered with load_image. width and height size it.
{ type: "image", src: "logo.png", width: 120 }

divider

A horizontal rule.
{ type: "divider" }

spacer

Vertical space sized by size.
{ type: "spacer", size: 24 }

note

A callout box. variant is one of info, warn, success, or muted. Both text and title accept inline content.
{ type: "note", variant: "info", title: "Note", text: "Figures are unaudited." }

table

Rows of cells with optional headers and column sizing. See Tables for cell shapes and column widths.
{
  type: "table",
  headers: ["Metric", "Q3", "Q4"],
  rows: [
    ["Revenue", "1.2M", "1.6M"],
    ["Margin", "18%", "24%"],
  ],
}

chart

A native vector chart. chart is the chart kind and data holds the values. See Charts for chart kinds and data shapes.
{
  type: "chart",
  chart: "bar",
  title: "Revenue by quarter",
  legend: true,
  height: 220,
  data: {
    labels: ["Q1", "Q2", "Q3", "Q4"],
    series: [{ name: "2025", values: [16, 22, 20, 28] }],
  },
}

group

Keeps its children together across page breaks, so a heading and its paragraph never split. gap adds space between children.
{
  type: "group",
  gap: 6,
  children: [
    { type: "heading", text: "Summary", level: 2 },
    { type: "paragraph", text: "This section stays together." },
  ],
}
Anywhere a block takes text, it accepts inline content: a string, one inline node, or an array mixing both. See Inline content.