Caret Docs typewithcaret.com →
This page is an implementation prompt

It is written to be handed to your coding agent as-is — point it at https://docs.typewithcaret.com/imagine-references/ and ask it to implement the two behaviors below in your backend. Nothing here is specific to a language, an image model, or a storage engine.

Caret Imagine · backend behavior

Generate the same person twice.

Ask an image model for “my sister at the beach” and you get a stranger — a different stranger every time. Identity is not something a text prompt can carry. The fix is boring and it works: collect real photographs of the people and things you care about, distil each subject into one reference sheet, and pass that sheet to the image model whenever the user names that subject.

Imagine is the Caret surface where this belongs. The keyboard sends a prompt over the /imagine route and expects one image back; everything between those two points is yours. References are entirely a backend behavior — the contract does not change, no new route appears, and a backend without references stays perfectly valid.

What you are building

Two behaviors, and they are separate on purpose.

1 · Setup, once per subjectmanual

The user gathers 8–15 clean photographs of a person, pet, or object and gives it a name. You generate one reference sheet from that set, show it to the user for approval, and store it under that name. This happens deliberately, not in the middle of a generation.

2 · Generation, every timeautomatic

When an Imagine prompt names a saved reference, resolve the name, pass that subject’s sheet to the image model as a reference image, and say which references you applied. When the prompt names none, use none. Never apply a reference the user did not name.

1 · Collect the source photos

Aim for 8–15 photographs per subject. Fewer than eight and the sheet starts inventing; more than fifteen mostly adds redundancy and cost. Cover this spread:

One front photo is not enough

A single frontal portrait contains no information about profile, head depth, or how the face behaves at an angle — so the model fills those in, differently each run. The result looks right in thumbnails and wrong to anyone who knows the person. If you have exactly one usable photo, say so plainly and treat the output as a likeness, not the person.

2 · Quality rules for the source photos

The set is the ceiling on everything downstream. Reject:

And keep the set from one era. Photographs spanning a decade, a major weight change, or four hairstyles average into someone who is nobody. Pick the current era and stay in it. Vary background and setting across the set, but not the person.

3 · Generate one reference sheet per subject

Feed the whole approved set to your image model and produce a single image: six large panels in a clean grid, one subject, consistent identity across every panel.

PanelWhat it shows
1Front, head and shoulders, neutral expression, eyes to camera
2Left three-quarter view
3Right three-quarter view
4Full profile, 90°
5Natural expression — a relaxed, characteristic smile
6Full body, standing, neutral pose, whole figure in frame

Non-negotiable properties of the sheet:

Show the sheet to the user before you save it. If a panel is off — wrong nose in profile, a face that drifts between panels — fix the source set and regenerate. A bad sheet is worse than no sheet, because it is consistently wrong.

4 · Store it under a clear name

One directory per subject, holding the approved sheet, the originals it was built from, and a small metadata record. Any store works — this shape is the point, not the filesystem.

references/
  ada/
    sheet.png          the approved six-panel sheet — the only thing sent to the model
    sources/           the originals, kept so the sheet can be rebuilt
    meta.json
{
  "name": "ada",
  "kind": "person",
  "aliases": ["ada b", "my sister", "my sister ada"],
  "sheet": "sheet.png",
  "source_count": 12,
  "created": "2026-08-18",
  "refreshed": "2026-08-18",
  "consent": "asked and given, 2026-08-17",
  "notes": "round tortoiseshell glasses, always"
}

Names are how the user reaches a reference, so make them unambiguous and predictable: short, lowercase, one subject each. Record the aliases the user actually says out loud — “my sister”, “the dog”, “my green mug” — because that is what will be in the prompt. Refuse a new name that collides with an existing one or with a common noun that will match by accident: a reference named cat will hijack every prompt containing the word cat.

5 · Generation behavior

On each Imagine request, in this order:

  1. Scan the prompt for saved names and aliases. Case-insensitive, whole words only, longest match first so “my sister ada” does not resolve twice.
  2. No match → no reference. Generate exactly what was asked for, with no reference image attached. This is the common case and it must stay fast and unsurprising.
  3. Match → attach that subject’s sheet as an image reference to the model call, alongside the user’s prompt.
  4. Several matches → attach each sheet if your model accepts multiple reference images. If it accepts one, ask the user which subject leads rather than silently picking.
  5. Say what you used. Report the applied references back to the user — in the response text, a log line, or both. A reference that is applied invisibly is indistinguishable from a model that has started hallucinating someone the user knows.
Never apply a reference the user did not name

No “most recently used” default, no “this prompt says my dog so it probably means Biscuit”, no auto-attaching the only reference on file. A prompt that says “a woman reading on a train” means a woman, not the user’s sister. Silently inserting a real, identifiable person into an image nobody asked to put them in is the single worst failure this feature has, and it is entirely avoidable: match on names, or use nothing.

Two prompt-craft rules once a sheet is attached. Refer to the subject by role — “the person in the reference image” — rather than re-describing their face in words; a text description of a face competes with the reference and the model splits the difference. And keep the rest of the prompt about the scene: pose, setting, light, style. The sheet handles identity, the prompt handles everything else.

prompt:     "the person in the reference image, sitting on a harbour wall
             at golden hour, 35mm, shallow depth of field"
references: [references/ada/sheet.png]
applied:    ada

If a subject is named but no sheet exists yet, do not improvise one mid-generation. Generate without it and tell the user the reference is missing, or offer to run setup — that is a deliberate, consented step, not something to do while they wait for a picture.

6 · Pets, objects, and places

The workflow is identical for anything you need to draw repeatably; only the six panels change.

Naming, resolution, and “only when named” are exactly the same. Consent is the part that does not apply — a mug cannot object to being drawn.

7 · Consent, access, and privacy

A reference library is a folder of biometric-grade portraits of people who are not in the room when the images get generated. Treat it that way.

Reference uploads and model inputs must be handled according to the privacy controls of the product you are building — the same rules that govern any other user content it processes. Be concrete with the user about where the sheet goes: if your image model is a remote API, that person’s face leaves the machine on every single generation that names them, and the provider’s retention terms apply to it. A local image model keeps it on your hardware. Either is a legitimate choice; making it without telling the user is not.

8 · Keep the sheets fresh

A reference sheet is a snapshot with an expiry date. New haircut, new glasses, a beard, weight change, a child who grows visibly in six months — the sheet keeps confidently producing last year’s person.

Done when

The contract side of Imagine — the finalizer fields, aspect ratio, quality, idempotent replay, how to return the bytes — is on the protocol page. If you have not built a backend yet, build one against that page first; references are something you add to a backend that already works.