# The placeholder protocol

Build and review the entire site before a single image exists. Every image slot is a
`<Placeholder>` that reserves the final geometry and carries the brief for the asset that
will replace it.

Copy [`../assets/Placeholder.astro`](../assets/Placeholder.astro) and
[`../assets/collect-image-manifest.mjs`](../assets/collect-image-manifest.mjs) into the
project rather than rewriting them.

## Why

- **Layout is finalized when changes are cheap.** Reflowing a page after twenty images
  exist means regenerating twenty images.
- **The brief is written while the page context is live.** You know what the shot has to
  do in the composition, because you just built the composition.
- **The site is always shippable.** A half-generated site is never broken, and a demo can
  be shown on placeholders if a deadline arrives early.

## The contract

The shape is fixed; everything inside it is derived from the vertical.

```astro
<Placeholder
  id="<entity>-<variant>-<view>"
  ratio="<binding aspect ratio>"
  label="<short human label, shown while reviewing>"
  alt="<the real, final alternative text>"
  brief="<shot> · <contents, left to right> · <mood, written about the viewer>
         · <treatment> · <explicit negatives>"
/>
```

Two worked examples, deliberately from different verticals, so the pattern is legible
without one trade's vocabulary standing in for the rule:

```astro
<!-- considered purchase, evidence-role image: the shot has to prove a claim -->
<Placeholder
  id="unit-studio-main" ratio="3/2" label="Studio — main view"
  alt="The studio seen from the entry corner, with daylight from the window wall"
  brief="Documentary photo from the entry corner at eye level, camera square to the wall.
         Bed, wardrobe, desk, TV, fridge, washing machine, air conditioner all visible.
         Mood: this is enough, and it works. Deep depth of field, matte, mild grain.
         No staged decor, no wide-angle size inflation."
/>

<!-- impulse purchase, atmosphere-role image: the shot has to create appetite -->
<Placeholder
  id="dish-khao-soi-hero" ratio="4/3" label="Khao soi — signature"
  alt="A bowl of khao soi with crisp noodles, lime and pickled greens on a worn wood table"
  brief="Overhead-ish three-quarter shot on a worn wooden table, daylight from a window
         at the left. One bowl, condiments beside it, a used spoon — mid-meal, not styled.
         Mood: you can smell it. Shallow-ish focus on the bowl, warm, matte.
         No garnish towers, no dry ice, no branded tableware."
/>
```

Note what changes between them and what does not. The **shape** is identical. The
**register** is not: one is shot to be believed, the other to be wanted. Derive that from
the vertical's position on the image-role axis, never from the previous site.

| Prop | Rule |
| --- | --- |
| `id` | Unique per asset. **One id means one asset means one ratio.** |
| `ratio` | **Binding.** The placeholder occupies the box the final image will occupy. |
| `label` | Human-readable, shown in the placeholder box while reviewing. |
| `alt` | Renders now, to assistive technology. This is the real, final alt text. |
| `brief` | **Never renders.** Emitted as `data-brief`, harvested into the manifest. |

## Writing a brief

Four parts, in this order. The third is the one people skip and the one that matters.

1. **Shot** — subject, framing, lens feel, time of day, camera height and angle.
2. **Contents** — what is in frame, concretely, roughly left to right.
3. **Mood** — *what the image has to make the viewer feel.* Write it as a sentence about
   the viewer, not about the picture. "Mood: you would recognise this door on your first
   evening home."
4. **Treatment and negatives** — light, colour, depth of field, finish, then an explicit
   list of what must not appear.

Repeat the **subject invariants** in every brief — the handful of facts that make every
image obviously the same business. What they are is vertical-specific: for a building it
is architecture, materials, furniture tier and condition; for a kitchen it is tableware,
surfaces, plating style and light; for a clinic it is equipment age, uniform, flooring and
signage. Decide the list once, in the image design system, and copy it verbatim into every
prompt. Consistency across the set beats novelty in any one image.

## The manifest

```bash
pnpm build && pnpm images:manifest
```

Walks the built HTML, collects every placeholder, and writes
`docs/image-asset-manifest.md`: id, binding ratio, alt text, the routes it appears on,
the brief, and a status checkbox. **That file is the hand-off to image generation** — the
generation step works from the manifest, not from reading pages.

The collector fails loudly if one id appears at two different ratios. That check exists
because it is an easy mistake to make (a card crop and a hero crop of "the same" shot) and
it hands the generation step a self-contradicting spec.

## Swapping

One `id` at a time. Keep the component signature; change what it renders. The ratios were
binding, so nothing in the layout may move — if something moves, the placeholder was wrong,
not the image.
