# Documents and nodes

> A document is a tree of components, each taking its data as state and returning the nodes it wants.

Source: https://docxcelerate.com/docs/essentials/documents-and-nodes/

A document in Docxcelerate is two things: a **template** and the **data type** it
expects.

The template is a tree of components, and each component returns **nodes** — a
paragraph, a section, a table. When you build the template against some data, you
get back a `DocumentModel`: plain JSON describing what the document says, with no
styling and no layout in it. Turning that into a `.docx` or a preview page comes
later, and is somebody else's job.

If you have written a React or Vue component before, most of this will feel
familiar. The parts that differ are called out as we go.

## A component takes its data as state

Here is about the smallest useful component you can write:

```tsx
import { Paragraph, useState } from "docxcelerate/template";
import type { DocumentData } from "../types.ts";

export const Greeting: Paragraph = () => {
  const [state] = useState((data: DocumentData) => ({
    name: data.residentName,
  }));

  return <Paragraph id="greeting">Dear {state.name},</Paragraph>;
};
```

`useState` is where your data enters the component — and it is the only place it
can. Everything after that line reads from `state`.

**Why route everything through one call?** Because it puts everything the
component depends on in one place. You can read the top of the file and know what
data it needs, instead of hunting for it through the rest of the code.

The initializer is ordinary TypeScript, so you can do whatever you like inside
it. There is no template language to learn: conditionals, formatting, imports and
`.map()` all work the way you already expect.

One thing that might look odd: `Paragraph` is both the element and the component
type. In TypeScript a value and a type can share a name, so writing
`const Greeting: Paragraph` declares what this component returns. Try to return a
`<Section>` from it and you get a compile error.

## Data can also arrive as props

If a component is handed what it needs, it doesn't have to go and fetch it:

```tsx
export const Arrears: Paragraph<{ amount: number }> = ({ amount }) => {
  const { currency } = useFormat();

  return <Paragraph id="arrears">You owe {currency(amount)}.</Paragraph>;
};
```

Something still has to read the data first, so a props-only component sits under
a parent that took it into state.

**Which should you use?** Props for components you want to reuse against
different values. State for components that know which document they belong to.

## Decisions are ordinary `if`

You do not need a special construct to make a document conditional. Write the
`if` you would write anywhere else:

```tsx
export const Balance: Paragraph = () => {
  const [state] = useState((data: DocumentData) => ({
    settled: data.balanceDue === 0,
  }));

  if (state.settled) {
    return <Paragraph id="settled">Nothing outstanding.</Paragraph>;
  }

  return <Paragraph id="arrears">A balance remains.</Paragraph>;
};
```

A ternary works too, and so does `{condition && <Node />}` inside your JSX.

Give each arm its own id, as above. The resolved document then records which one
this recipient actually got — which is the difference between a document you can
audit later and one you can only look at.

Something changes about branching when you publish a document to an engine, but
you don't need it yet. We cover it in
[what changes when you publish](/docs/essentials/templates/#what-changes-when-you-publish).

## Ids

An id is how an engine addresses a particular node, and how two build artifacts
line up when you diff them. Renaming one is a breaking change for anything
pointing at it, much like renaming an API route.

**You can usually leave ids out.** A node without one is named after what it is —
its heading, or the component that produced it — so `<Greeting />` becomes
`greeting`. That is what stops loops and branches from forcing you to invent
names for nodes nobody refers to.

The one thing you cannot do is use an id twice. Two nodes claiming the same id is
an error, reported with both positions, rather than a race the later one wins.

## Sections nest, nodes don't

`Section` is the only element that groups other nodes under a heading, and its
title carries into the document outline:

```tsx
<Section id="opening" title="Opening">
  <Greeting />
  <Offer />
</Section>
```

`Table` holds nodes too — rows, and cells inside them — but it doesn't head
anything. See [Section](/docs/nodes/section/) for how deeply you can nest, and
[Table](/docs/nodes/table/) for grids.

## Hooks

Hooks are how a component reaches the build going on around it:

| Hook | What it gives you |
| --- | --- |
| `useState` | Data, taken in once and kept |
| `useShared` | A value left for the components rendered after this one |
| `useSetPrompts` | Prompts for the node this returns — what makes it dynamic |
| `useSetPlaceholders` | What previews show in place of generated content |
| `usePlaceholderData` | Stand-in names, dates and figures for previews |
| `useFormat` | Locale-aware currency, dates, lists and plurals |
| `useAvailableTokens` | The token budget this build allotted |
| `useDeriver` | Runs a registered deriver now |

There is one rule, and it is the same one React has: **call every hook before the
first `await`, and before any branch or `return`.** Hooks are matched up by the
order you call them in, so a hook reached only sometimes would attach itself to
the wrong component.

If you get this wrong, you get an error that says so. It will not fail quietly.

## Building the document

Once you have a template, building it is one call:

```ts
import { buildDocument } from "docxcelerate";

const doc = await buildDocument(documentTemplate, data);
```

What comes back is a `DocumentModel` — a `schemaVersion`, an `id`, a `title` and
an array of `nodes`. There is no styling or layout in it. Those get applied later
by whichever renderer you hand it to.

If you have a document project (one defined with `defineDocumentProject`), reach
for `buildProjectPreviewDocument` instead. It applies the project's style and
resolves dynamic nodes to their placeholders:

```ts
import { buildProjectPreviewDocument } from "docxcelerate";

const doc = await buildProjectPreviewDocument(project);
```

This is exactly what the preview app calls, so what you build in code matches what
you saw in the browser.
