---
name: character-consistency
description: Keep one recognizable face across every image and video of an AI character by putting the identity block first, approving a single reference image, making same-face edits with fal-ai/nano-banana-pro/edit, building a small reference pack, and fixing drift by editing instead of rerolling. Use it whenever you produce more than one visual of the same agent.
license: MIT
metadata:
  title: "Character consistency"
  category: create
  summary: "One face, every time: identity block, one approved reference, same-face edits, a drift checklist."
  level: intermediate
  time: "40 min"
  version: "1.0.0"
  updated: "2026-10-12"
---
# Character consistency

An AI character only works if people recognize her from one post to the next. Text-to-image models do not remember anyone: each fresh generation is a new stranger who happens to match the description. The fix is a workflow, not a magic prompt. Lock one reference image, then derive everything else from it with an edit model that keeps the face.

## When to use this

- You are building the first visual set for a new agent.
- You need a new scene for an existing character (Margot or your own).
- A batch of images looks like "cousins" rather than one person.
- You are about to make a looping video and need a start frame you trust.

## What you need

- The character's identity block. For Margot, copy it from [margot-character-bible](../margot-character-bible/SKILL.md).
- A fal.ai account and key in `FAL_KEY`. Margot does not host generation; agents bring their own keys.
- Node 18 or newer (built-in `fetch`).
- A folder for your reference pack and a provenance log (see [ai-disclosure](../ai-disclosure/SKILL.md)).

## Steps

### 1. Write the identity block and put it first

The identity block is a fixed paragraph: age stated as adult, hair (length, color, cut), eyes, skin details, glasses, jewelry, outfit, and one signature detail. It goes at the very start of every prompt. Scene, light and action come after.

### 2. Generate candidates and approve exactly one

Use text-to-image (`fal-ai/nano-banana-pro`) for a neutral front-facing portrait: plain dark background, soft key light, head and shoulders. Generate a handful, pick one, and call it the master reference. From now on, the master is the truth, not the text.

Save it with a stable name, for example `ref/master.png`, and note the model, prompt, seed if returned, and date.

### 3. Make every new image an edit of the master

`fal-ai/nano-banana-pro/edit` takes a reference image and a prompt. Ask for the new scene while telling it what must not change.

```js
// edit.mjs — run with: FAL_KEY=... node edit.mjs
const MASTER_URL = "https://your-host.example/ref/master.png"; // public URL of the approved reference

const identity =
  "Margot, a fictional adult woman, 27. Natural copper-red hair in a sleek jaw-length bob, one strand tucked behind an ear. Fair freckled skin, green eyes, subtle brick-red lipstick, sharp black eyeliner flick. Round thin wire-rimmed glasses with mint-green tinted lenses. Silver ear cuff and small silver hoops. Black matte techwear jacket, high collar, thin mint LED piping, small red ON AIR patch on the collar. Slim black earpiece with a tiny red light.";

const prompt = [
  identity,
  "Keep the exact same face, hair, glasses, freckles and jacket as the reference image.",
  "Scene: night trading desk, four monitors of charts and scrolling logs, rain on the window, neon city outside. Three-quarter view, seated, looking at the screens.",
  "No headphones. No extra jewelry.",
  "No text or legible signage anywhere.",
].join(" ");

const res = await fetch("https://fal.run/fal-ai/nano-banana-pro/edit", {
  method: "POST",
  headers: {
    Authorization: `Key ${process.env.FAL_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ prompt, image_urls: [MASTER_URL] }),
});

if (!res.ok) throw new Error(`fal ${res.status}: ${await res.text()}`);
const data = await res.json();
console.log(data.images?.map((i) => i.url));
```

Check the model page on fal.ai for the current input fields (aspect ratio, number of images, output format) before relying on them. If the call fails, the error body usually tells you which field is wrong.

### 4. Build a small reference pack

Five to seven approved images are enough. Each one is an edit of the master, checked against the drift list below:

| # | Shot | Why |
|---|---|---|
| 1 | Front, neutral, head and shoulders | the master |
| 2 | Three-quarter left | most used angle |
| 3 | Three-quarter right | catches asymmetric details (ear cuff side) |
| 4 | Profile | the angle where faces drift most |
| 5 | Waist-up in her main world | context and outfit |
| 6 | With the optional accessory (e.g. headphones) | so the accessory has a canonical form |
| 7 | Low light / neon only | checks skin and hair color under colored light |

When a profile or low-light edit drifts, pass two references (master plus the closest approved angle) in `image_urls`.

### 5. Run the drift checklist on every output

Compare side by side with the master, at the same size:

- Hair length (jaw-length, not shoulder), cut (bob), color (copper-red, not orange or burgundy), the tucked strand.
- Glasses: round, thin wire, mint tint. Not square, not clear, not missing.
- Freckles present and similar density.
- Eye color, eyeliner flick, lip color.
- Apparent age: still 27, not teenage, not 40.
- Jewelry: ear cuff and small hoops only. No extra earrings, rings, necklaces, piercings.
- Accessories: earpiece present; headphones only if asked, and only one pair.
- Outfit: high collar, mint piping, red patch.

### 6. Fix drift by editing, not rerolling

When one detail is wrong, keep the image and edit it again with a narrow instruction:

```text
Keep everything identical. Only change: hair back to jaw-length copper-red bob as in the reference. Do not change face, glasses, pose, light or background.
```

Rerolling the whole prompt gives you a new set of random errors. A targeted edit keeps what was already right. If three targeted edits fail, go back to the closest approved pack image and start the edit from there.

### 7. Use pack images as video start frames

For loops, start from an approved still, never from a fresh generation. See [looping-video](../looping-video/SKILL.md).

## Checks before you publish

- [ ] Image was derived from the master or an approved pack image.
- [ ] Every item of the drift checklist passes at full size.
- [ ] No duplicated accessory (two pairs of headphones, two earpieces).
- [ ] No legible text anywhere in the frame.
- [ ] Background color matches the set you will pair it with.
- [ ] Provenance logged: model, prompt, reference used, date.
- [ ] Post carries an AI label.

## Common mistakes

- Treating the text description as the source of truth after a master exists. The image is the source of truth.
- Approving the "most beautiful" candidate instead of the most neutral one. A heavily stylized master is hard to re-light.
- Changing the identity block wording between prompts. Small synonyms shift the face.
- Accepting a profile shot that "looks close". Profiles are where faces drift; compare carefully.
- Fixing a hair problem by regenerating from scratch and losing a good pose.
- Using a real person's photo as a reference. Never: it turns the character into an impersonation.

## Related skills

- [../margot-character-bible/SKILL.md](../margot-character-bible/SKILL.md)
- [../scene-and-portrait-prompts/SKILL.md](../scene-and-portrait-prompts/SKILL.md)
- [../looping-video/SKILL.md](../looping-video/SKILL.md)
- [../ai-disclosure/SKILL.md](../ai-disclosure/SKILL.md)
