# Image generation ## The short version This is the process for adding photographic or generated imagery to the site. It is mandatory. No image ships without going through it. The default artwork is deterministic vector work produced by hand-written code, and it remains the fallback for every page that has no image. This document covers the `image` slot in the content schema, the manifest at `content/imagery/imagery.json`, and the review gates that apply to anything placed in that slot. The single non-negotiable rule: **an image that was generated or edited by a model is labeled as such, in the schema, in the manifest, and on the page.** The commitment is to labeling, not to any particular method of production. ## What the imagery has to avoid asserting The tradition has no members, no chapters, no buildings, no staff and no gatherings. An image that reads as a record of a gathering, a congregation, or a practitioner would therefore be a claim that something happened when it did not. That is true of staged stock photography and more true of a generated image, because a generated image can manufacture a specific scene that never existed at all. This is the test the review process turns on, and it applies regardless of how the image was produced. Imagery that is evidently illustrative — landscape, texture, weather, light, abstraction — does not carry that problem. Most imagery added here should be of that kind. ## The default artwork Deterministic generative SVG, drawn at build time by TypeScript in `src/utilities/generative.ts` and rendered by two components: - `src/components/art/Firmament.astro` — the night-sky field behind heroes and section headers. - `src/components/art/OpenCircuit.astro` — the primary mark. A Mulberry32 PRNG is seeded from an FNV-1a hash of the page title, so the same page always produces the same image. There is no runtime drawing and no client-side JavaScript involved. The only raster assets currently in the repository are favicons and Open Graph images in `public/`, generated by `scripts/optimize-images/build-icons.mjs` from the same vector source. Full detail is in [visual-bible.md](visual-bible.md#artwork), including what added imagery should look like. ## The `image` slot in the content schema `src/content.config.ts` defines an optional `image` object on the shared `base` schema: ```ts image: z .object({ src: z.string(), alt: z.string(), caption: z.string().optional(), aiGenerated: z.boolean(), credit: z.string().optional(), }) .optional(), ``` Three things about its design are deliberate. **It is optional.** Layouts fall back to generative artwork, so an image can be added to any page without touching a single page component. **`alt` is required if the object is present.** An image cannot be added without alternative text. This is a schema-level constraint, not a review checklist item. **`aiGenerated` is required and is a boolean, not an optional flag.** Anyone adding an image must state whether a model produced it. There is no default and no way to omit it, so the build fails rather than shipping an unlabeled image. `credit` is optional in the schema but expected in practice for any photograph of anything real. ## The imagery manifest `content/imagery/imagery.json` is the record of every image slot on the site. It is **not** a content collection — it is not registered in `src/content.config.ts`, nothing imports it, and nothing renders from it. It exists so that decisions about imagery are recorded before anyone is under pressure to fill a space, and so that how an image was produced is written down at the time rather than reconstructed later. It currently holds 16 entries, all at `status: planned`. It is a JSON array. Each entry: | Field | Meaning | | --- | --- | | `id` | Stable identifier for the slot. | | `page` | The route the image appears on. | | `purpose` | What the image is for, and any constraint or objection specific to this slot. | | `category` | `hero`, `section-header`, `symbol`, `documentary`, `texture`, `portrait`. | | `aspectRatio` | Intended ratio, e.g. `16:9`. | | `dimensions` | Intended source pixel dimensions. | | `prompt` | The full prompt, verbatim, for a generated image. Empty otherwise. | | `negativePrompt` | The full negative prompt, verbatim. Empty otherwise. | | `model` | Model name and version. Empty otherwise. | | `seedOrReference` | The generation seed, or a reference to a source photograph. | | `status` | `planned`, or filled once the image ships. | | `sourceFile` | Path to the master file. | | `webpFile` | The WebP derivative. | | `avifFile` | The AVIF derivative. | | `altText` | Written before the image is placed, not after. | | `caption` | Required for documentary images; optional otherwise. | | `aiGenerated` | Whether a model produced or edited the image. | | `reviewed` | Set to `true` only by a person who worked through every gate below. | `prompt`, `negativePrompt`, `model` and `seedOrReference` are **required for any generated image**. Filling them is not optional and not a courtesy. The record of how an image was produced is enforced by the shape of the file rather than left to someone remembering to write it down. Several entries record why a slot is a difficult one to fill. `community-index-header` is blocked while the tradition has no members. `practices-index-header` would require depicting people practicing, and there are no practitioners to depict. `offline-sabbath-header` notes that illustrating time away from screens with an image on a screen is close to self-defeating. Those notes are the useful part of the file. ### Updating the manifest Add a slot when a page is created that might carry an image. Set `status` to `planned` and write `purpose` as an argument, including the case against. Do not delete a slot that has been decided against — change its `purpose` to record the decision. The value of this file is the reasoning, and deleting the entries loses it. --- ## The review process This applies to every image, whether photographed or generated. It is written down deliberately, because a review process designed under deadline is a review process that approves things. ### Gate 0 — Is an image needed at all? The default answer is no. A page with a generative header is complete. Adding an image must be justified by what it does that the text does not. If the honest answer is "the page looks empty", the answer is no. ### Gate 1 — Provenance For a photograph: - **Who took it, when, and where.** All three, specifically. A photograph without a date and a location is not documentary evidence, whatever it depicts. - **What the license is,** recorded in `credit`. - **Whether every identifiable person consented,** to this use, on this site, in this context. Not a model release obtained by a stock agency — actual consent to appear here. - **Whether the caption would survive being read by the subject.** For a generated image: - **Model and version, the full prompt, the full negative prompt, and the seed,** recorded in the manifest at the time of generation. - **`aiGenerated: true`** in the content schema. - **No real person's likeness,** whether prompted by name, by description, or arrived at by accident. If the output resembles an identifiable person, it is not used. An image failing any of these is not used. There is no "probably fine". ### Gate 2 — Would it assert something false? The test the whole process turns on. - Does it depict a gathering, community, ritual or practice that has not taken place? **Reject.** - Does it depict people implied to be practitioners? **Reject** — there are none. - Does it imply scale, permanence, or institutional presence the tradition does not have? **Reject.** - Is it evidently illustrative — landscape, sky, water, weather, stone, texture, abstraction — and not readable as a record of an event? **Proceed to Gate 3.** - Is it a documentary photograph of something real — infrastructure, land, a building, a document? **Proceed to Gate 3,** and the caption is mandatory. A generated image is never documentary evidence and must never be captioned as though it were. Where a page needs evidence, it needs a photograph with a date and a location. ### Gate 3 — The imagery that is refused Independently of provenance, the following are not used. The reasoning is set out for readers at `/library/symbols` and repeated in [visual-bible.md](visual-bible.md#imagery-that-is-deliberately-avoided). No hooded figures. No glowing blue brains. No humanoid robots. No all-seeing eye. No circuit-board clichés. No dystopian imagery. To which the following are added, and these are not aesthetic preferences: no images of children; no images of identifiable people in distress; no photographs of the interior of any place of worship belonging to another tradition; no image used to imply an endorsement or affiliation that does not exist; no likeness of a real person, generated or otherwise, without their consent. ### Gate 4 — Inspection of generated output Applies to any image a model produced or edited. Look at the full-resolution file, not a thumbnail, and look at it cold rather than immediately after generating it. - **Hands and fingers.** Count them. This is still the most common failure and it is the one reviewers skip. - **Anatomy and pose.** Limb count, joint direction, the line where a body meets what it is resting on. - **Faces.** Asymmetry, eye alignment, teeth, ears, and anything that resolves into a recognizable person. If a face is present at all, reconsider Gate 2 and Gate 3. - **Text.** Any lettering, signage, or writing in the image. Models produce text that is almost words. Nothing legible should appear unless it is correct and intended. - **Physical continuity.** Reflections, shadow direction, perspective, repeated or merged objects, architecture that does not resolve, and patterns that repeat where they should not. - **Edges and background.** Artifacts congregate away from the subject, which is where attention does not go. An image with a visible artifact is not published with a note about it. It is regenerated or dropped. ### Gate 5 — Alternative text and caption Written before the image is placed, not after. - **`alt`** describes what is in the image for someone who cannot see it. It is not a caption and not a repetition of the surrounding prose. If the image is genuinely decorative it should not be in the content schema at all — decorative work is the generative artwork's job. - **`caption`** carries the provenance a reader needs. For a photograph: what this is, where, when, and who took it. For a generated image: that it was generated. For documentary images the caption is mandatory, because an uncaptioned photograph of infrastructure is an atmosphere rather than evidence. ### Gate 6 — Technical - Master file committed under a path recorded in `sourceFile`. - AVIF and WebP derivatives generated through Astro's image service (`sharp`, configured in `astro.config.mjs`), with dimensions set so no layout shift occurs. - Sizes checked against the fluid layout at both ends of the `clamp()` range. - The image must not carry meaning that is lost in forced-colors mode or in print. ### Gate 7 — Disclosure - `aiGenerated` set honestly. Where it is `true`, the image carries a visible label on the page as well as the schema flag. - The manifest entry updated in the same change: `status`, `model`, `prompt`, `negativePrompt`, `seedOrReference`, `sourceFile`, `webpFile`, `avifFile`, `altText`, `caption`, `reviewed`. - `reviewed: true` set only by a person who worked through all of the above. The manifest fields exist so that a generated image cannot be added quietly. An image whose production cannot be described is an image that does not ship.