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

# Headers & footers

> Repeat a header and footer on every page, and print page numbers.

`page.header` and `page.footer` are nodes that **repeat on every page** — at the top and bottom respectively. Both are optional, and each is an ordinary [node](/templates/overview#the-node-catalog), so anything you can put in the body goes there too.

```json theme={"dark"}
{
  "page": {
    "header": { "type": "row", "items": [ "...branding..." ] },
    "content": { "type": "column", "items": [ "...the document..." ] },
    "footer": { "type": "richText", "align": "center", "spans": [ "...page numbers..." ] }
  }
}
```

The body flows between them. On a multi-page document the header and footer are redrawn on each page, and the content area shrinks to leave room — you don't position them yourself.

## A branded header

A header is usually a `row`: the brand on the left, document metadata on the right.

```json theme={"dark"}
{
  "type": "row",
  "items": [
    { "size": { "kind": "relative", "weight": 1 }, "child": { "type": "column", "items": [
      { "type": "text", "value": "{{brand.name}}", "style": { "fontSize": 18, "bold": true } },
      { "type": "text", "value": "{{brand.tagline}}", "style": { "fontSize": 9, "color": "grey.darken1" } }
    ] } },
    { "size": { "kind": "constant", "width": 180 }, "child": { "type": "column", "items": [
      { "type": "text", "value": "INVOICE", "style": { "fontSize": 20, "bold": true }, "align": "right" },
      { "type": "text", "value": "{{invoice.number}}", "style": { "color": "grey.darken2" }, "align": "right" }
    ] } }
  ]
}
```

## Page numbers

Page numbers come from a [`richText`](/templates/text#richtext) node using the `pageNumber` and `totalPages` spans. Put it in the footer (or header) so it repeats and resolves per page:

```json theme={"dark"}
{
  "type": "richText",
  "align": "center",
  "spans": [
    { "value": "Page ", "style": { "fontSize": 9, "color": "grey.darken1" } },
    { "pageNumber": true },
    { "value": " of ", "style": { "fontSize": 9, "color": "grey.darken1" } },
    { "totalPages": true }
  ]
}
```

That renders `Page 1 of 3`, `Page 2 of 3`, and so on. `pageNumber` and `totalPages` are filled in by the renderer — they're the only dynamic values that don't come from your `data`.

<Note>
  Page-number spans only do something useful where the node repeats. In `page.content` they'd render a single time on the first page. Keep them in `header` or `footer`.
</Note>

## A plain footer

Not every footer needs page numbers. A one-line legal/contact footer is just a `text` node:

```json theme={"dark"}
{
  "type": "text",
  "value": "{{company.name}} · {{company.email}} · Payable within 14 days",
  "style": { "fontSize": 8, "color": "grey.darken1" },
  "align": "center"
}
```

<Card title="See it in a multi-page document" icon="copy" href="/examples/gallery#multi-page-report">
  The report example combines a repeating header, a long auto-paginating table, and a page-number footer.
</Card>
