# Image

> A picture your data points at, or one a generation endpoint produces.

Source: https://docxcelerate.com/docs/nodes/image/

A static image points at something you hold — a signature, a logo, a site photograph — with every field able to vary per recipient. A dynamic image describes what is wanted and leaves the endpoint to make it.

> **What the renderers do today:** Both shipped renderers print a labelled frame in place of the picture — `[image: <alt>]` in the DOCX, a dashed box in the browser. The node carries its path, alt and size through unchanged.

- **Helpers:** `Image`
- **Node kind:** `image`
- **Category:** Media
- **Resolves:** Both
- **Children:** None.

| Option | Type | What it does |
| --- | --- | --- |
| `id` | `string` | Stable address for the node. Engines target it and build artifacts diff on it, so treat a rename as a breaking change. Optional: a node without one takes an id from where it sits, which is what keeps branches and loops from forcing you to invent names. Two nodes claiming one id is an error rather than a race. |
| `src` _required_ | `string` | Static only. Lands on the node as `path`. A `data:` URI carries the bytes and is the only form that survives into a DOCX; a path or URL draws on screen only. |
| `fallbackSrc` | `string` | Static only. A raster to embed in place of an SVG, which Word will not take alone. Screen renderers ignore it and draw the SVG. |
| `alt` | `string` | Static only. Alternative text, carried into the DOCX — and the words printed in the frame when there is no picture yet. |
| `width` | `number` | Static only. Rendered width in points, honoured by both renderers. |
| `height` | `number` | Static only. Rendered height in points, on the same terms as `width`. |
| `placeholder` | `string` | Dynamic only. What previews show in place of generated content. Also settable with `useSetPlaceholders`. Optional, but a document that reads badly without one cannot be reviewed. |
| `generalPrompt` _required_ | `string` | Dynamic only. What this node should say. |
| `infoPrompt` | `string` | Dynamic only. Context the model should have but should not restate. |
| `negativePrompt` | `string` | Dynamic only. What to avoid — claims, tones, or facts it must not invent. |
| `systemPrompt` | `string` | Dynamic only. Role and voice, applied ahead of the other prompts. |
| `examplePrompt` | `string` | Dynamic only. What a good answer looks like, written out as finished text. Shown last, because it is what the answer gets measured against. |
| `derivers` | `DeriverInvocation[]` | Values the engine computes before the node resolves, written to `derived.*` and readable from a template token. Built with `derive()`. These survive publishing and run per document — use them for anything computed from request data. `useDeriver` runs one during the build instead. |

## Every field is a prop

`src`, `alt`, `width` and `height` are plain props, computed from state before
the element is returned. A signature that differs per office, a logo per brand,
a photograph keyed by reference — all of it stays inside the component instead
of becoming a branch in the template:

```tsx
export const Signature: Image = () => {
  const [state] = useState((data: MemberData) => ({
    src: data.signatureUrl,
    manager: data.managerName,
  }));

  return (
    <Image id="signature" src={state.src} alt={`Signed by ${state.manager}`} width={180} />
  );
};
```

## src becomes path

The prop is `src`; the resolved node calls it `path`. Expand *What it resolves
to* on the first variant below to see it.

## Dynamic images

A dynamic image is described rather than supplied, taking the same prompt slots
as a dynamic paragraph.

`negativePrompt` earns its place here more than anywhere. Generated imagery
fails in predictable ways — baked-in text, invented logos, recognisable faces —
and the slot rules them out once, in the node.

## Variants

### Static

A signature whose file and caption both follow the data.

Source: `src/nodes/image/static.node.tsx`

```tsx
import { Image, useState } from "docxcelerate/template";
import type { SampleData } from "../sample-data.ts";

/**
 * Every field is a plain prop, computed from state before the element is
 * returned — so a signature that varies by manager needs no branching in the
 * template that places it.
 */
export const Signature: Image = () => {
  const [state] = useState((data: SampleData) => ({
    src: data.signatureUrl,
    manager: data.managerName,
  }));

  return (
    <Image
      id="signature"
      src={state.src}
      alt={`Signed by ${state.manager}`}
      width={180}
      height={60}
    />
  );
};
```

**What it resolves to**

```json
{
  "id": "signature",
  "kind": "image",
  "mode": "static",
  "path": "assets/signature-lindqvist.png",
  "alt": "Signed by Tomas Lindqvist",
  "width": 180,
  "height": 60
}
```

### Dynamic

Described rather than supplied, with the failure modes fenced off.

Source: `src/nodes/image/dynamic.node.tsx`

```tsx
import { Image, useSetPlaceholders, useSetPrompts, useState } from "docxcelerate/template";
import type { SampleData } from "../sample-data.ts";

/**
 * The same prompt set as a dynamic paragraph, for artwork the engine produces
 * rather than something you hold. The placeholder is what previews show, so
 * the layout is settled before any image exists.
 */
export const CentrePhoto: Image = () => {
  const [state] = useState((data: SampleData) => ({ centreName: data.centreName }));

  useSetPrompts({
    generalPrompt: `A wide daylight photograph of the entrance to ${state.centreName}, ` +
      `people arriving, no text overlay.`,
    negativePrompt: "No logos, no recognisable faces, no stock-photo staging.",
  });

  useSetPlaceholders(`Photograph of ${state.centreName}`);

  return <Image id="centre-photo" />;
};
```

**What it resolves to**

```json
{
  "id": "centre-photo",
  "kind": "image",
  "mode": "dynamic",
  "placeholder": "Photograph of Riverside Leisure Centre"
}
```

**What the endpoint is asked**

- `general` — A wide daylight photograph of the entrance to Riverside Leisure Centre, people arriving, no text overlay.
- `negative` — No logos, no recognisable faces, no stock-photo staging.

## Notes

- **Only a `data:` URI travels.** It carries the bytes, so a document written
  by an engine somewhere else still has the picture. A path or an http URL draws
  on screen, where a browser can fetch it, but packs into a `.docx` as a note:
  nothing is ever fetched or read from disk while packing, because the machine
  writing the document is not the machine the file was on.
- Word will not embed an SVG on its own, so give one a `fallbackSrc` raster. The
  screen draws the SVG and the Word file gets the raster.
- `alt` is worth writing either way: it describes the picture in the Word file,
  and it is what a node with no picture yet prints in its place.
