/** * What a drawing is made of: the ask Claude is given, the reply read back * into SVGs, and the wall every SVG passes before it is kept. Pure * functions, no I/O — `src/draw.ts` runs Claude, `src/actions.ts` keeps * the rows. * * Every SVG is drawn in two placeholder colours, INK and GLOW. A palette is * those two swapped for two others, here for a download and in * `static/glyph.js` for the preview, so one drawing reads in any theme. * The colours themselves are data: `design/palettes.json`. */ import colours from "../design/palettes.json"; export const KINDS = { mark: "logo mark", icon: "app icon", badge: "badge", spot: "spot illustration", } as const; export type Kind = keyof typeof KINDS; export const isKind = (value: unknown): value is Kind => typeof value === "string" && Object.hasOwn(KINDS, value); /** The placeholder colours every SVG is drawn in. */ export const INK: string = colours.placeholder.ink; export const GLOW: string = colours.placeholder.glow; /** Palettes a drawing can be shown and saved in. */ export const PALETTES: Readonly< Record > = colours.palettes; export type Palette = keyof typeof colours.palettes; export const isPalette = (value: unknown): value is Palette => typeof value === "string" && Object.hasOwn(PALETTES, value); export const COUNT = 4; export const PROMPT_MAX = 400; /** The most a kept SVG may weigh, in characters. */ export const SVG_MAX = 16_000; /** What Claude is asked, for one prompt. */ export function ask(prompt: string, kind: Kind): string { return `You are a sharp vector designer. Draw ${COUNT} distinct ${KINDS[kind]} concepts for this brief: ${prompt} Rules for every SVG: - Root element exactly: - First child: with a two-to-four word name for the concept. - Use ONLY these colours, written as hex in fill/stroke attributes: ${INK} (main ink) and ${GLOW} (accent glow), plus "none". No other colours, no gradients, no opacity tricks, no CSS, no