Skip to content

Themes

The thematic component of every artefact keryx generates — image-prompt styles, palette, music tone, voice — is config, not code. The Python reference scripts held these as constants (STYLES, PALETTE, the portrait prompt, the voice settings); keryx lifts them into a theme catalog in config so they can be added and edited without a rebuild, and so a second brand is just a new set of themes. Generators resolve a theme by keyword and never carry hardcoded thematic values (design spec §6).

Model

A theme is a self-contained aesthetic profile identified by a keyword and tagged with a type declaring the artefact it themes. Keywords are unique within a type, so editorial can name both an article theme and a reel theme; the command's type disambiguates.

Type Drives Fields
article cover art (keryx cover) palette, prompt (style prefix), aspect
reel the 9:16 reel (keryx reel build + voice + music) palette, card (mode, scrim, fonts, illustration style), music (prompt, gain), voice (id, stability, similarity, model, pronunciation)
portrait the avatar (keryx portrait) palette, prompt

Types are open-ended — a new generator adds a new type.

Config shape (nested by type → keyword):

themes:
  defaults:            # the keyword used when --theme is omitted, per type
    article: editorial
    reel: editorial
    portrait: default
  article:
    editorial: { palette: {...}, prompt: "Editorial conceptual illustration…", aspect: "16:9" }
  reel:
    editorial:
      palette: {...}
      card:  { mode: overlay, scrim: {from: 0.52, color: charcoal}, style: "…wordless…" }
      music: { prompt: "restrained editorial bed", gain: 0.16 }
      voice: { id: MhaH9hcD2Ulcr80j28Z1, stability: 0.6, similarity: 0.92 }
  portrait:
    default: { palette: {...}, prompt: "Stylised editorial avatar…" }

Resolution

Every generator takes --theme <keyword>. When omitted it falls back to themes.defaults.<type> for the command's type. An unknown keyword is a hard error (it lists what's available) — a typo'd or unregistered --theme never silently falls back to an unthemed render. Resolution is pure and unit-tested (no I/O), so timing/wrapping/theme logic stays deterministic (R-GLOBAL-10).

Themes and avatars (cards gen --avatar)

When a card is generated with an avatar (cards gen --avatar <name> --theme <kw>), it is an image-to-image render anchored by the avatar's reference photo. The theme's card style is woven into the prompt and takes precedence over the avatar's own configured style — but two things temper how much an off-brand theme restyles an avatar card:

  1. the avatar reference image strongly anchors appearance at the model level (that's what preserves the likeness), and
  2. avatar prompts carry a fixed flat-illustration directive to keep the house look.

So a far-off-brand theme (e.g. a neon palette over the editorial house style) will restyle an avatar card only weakly. For a strong off-brand look, use scene-only cards (cards gen without --avatar), or tune the avatar's own style/palette. Scene-only cards apply the theme's style prefix directly with no reference anchor.

Seeding

keryx init seeds the catalog with the house set, at parity with the blog Python scripts:

  • article clay, editorial (default), blueprint — the three cover-style prompt prefixes from gen-cover.py.
  • reel editorial (default), clay, blueprint — mirroring the article flavours: they share the petrol-teal / amber / cream / charcoal palette and the voice clone (MhaH9hcD2Ulcr80j28Z1, stability 0.6 / similarity 0.92) but each has its own card treatment + illustration style.
  • portrait default — the risograph avatar prompt.

The seeded palette (from gen-reel.py):

Role Hex
teal #14534F
amber #E8923B
cream #F2EAD8
charcoal #282A2C

Managing themes

Use keryx theme to list, show, add (or clone with --from), edit (--set key=value), and remove themes. Edits persist through the GTB config layer and are picked up live via config hot-reload; secrets are never written to the theme config.

Parity note

The seeded values are intended to be identical to the Python scripts. The per-card reel illustration style strings and the clay/blueprint music prompts are derived from the cover styles / spec examples (the Python scripts did not yet generate per-card imagery); they are seeds to tune via keryx theme edit, not fixed constants. See PHASE-DECISIONS-LOG.md (Phase 1a).