Repository Public
1/** Editorial taxonomy: series templates and the controlled tag vocabulary. Seeded into PostgreSQL by scripts/seed.ts. */2export interface SeriesTemplate {3 slug: string; kind: "fiction" | "factual" | "experimental"; accent: string;4 titleEn: string; titleFr: string; descriptionEn: string; descriptionFr: string;5 /** Editorial rules handed to the Creative Director and the Screenwriter. */6 rules: string; defaultLanguage: "en" | "fr" | "bilingual";7}89export const SERIES: SeriesTemplate[] = [10 { slug: "impossible-worlds", kind: "fiction", accent: "#7fb7c9", defaultLanguage: "en",11 titleEn: "Impossible Worlds", titleFr: "Mondes impossibles",12 descriptionEn: "Alternate realities that could not exist, and that obey their own rules perfectly.",13 descriptionFr: "Des réalités parallèles qui ne pourraient pas exister, et qui obéissent parfaitement à leurs propres règles.",14 rules: "State one impossible premise in the first shot and never break it. Every later shot shows a consequence of that single rule. End on the consequence nobody expected but which follows logically." },15 { slug: "one-minute-ideas", kind: "factual", accent: "#e8c27a", defaultLanguage: "en",16 titleEn: "One-Minute Ideas", titleFr: "Idées en une minute",17 descriptionEn: "One scientific, mathematical or economic idea, made visible. Every claim is checked against sources.",18 descriptionFr: "Une idée scientifique, mathématique ou économique rendue visible. Chaque affirmation est vérifiée avec des sources.",19 rules: "Teach exactly one idea through one concrete visual metaphor that stays on screen. Every factual sentence must be checkable and is listed in `claims`. No numbers unless they are certain. Never depict a real, identifiable person. The last line states the idea plainly." },20 { slug: "micro-cinema", kind: "fiction", accent: "#d98b6a", defaultLanguage: "en",21 titleEn: "Micro Cinema", titleFr: "Microcinéma",22 descriptionEn: "Complete stories in under a minute: a setup, a tension, a payoff.",23 descriptionFr: "Des histoires complètes en moins d'une minute : une mise en place, une tension, une chute.",24 rules: "One character, one want, one obstacle, one reversal. The payoff must re-colour the first image. Narration is sparse; the images carry the story." },25 { slug: "visual-paradoxes", kind: "experimental", accent: "#b6a2e0", defaultLanguage: "en",26 titleEn: "Visual Paradoxes", titleFr: "Paradoxes visuels",27 descriptionEn: "Thought experiments and conceptual illusions you can watch happen.",28 descriptionFr: "Des expériences de pensée et des illusions conceptuelles que l'on peut regarder se produire.",29 rules: "Stage one named or original thought experiment as a physical scene. Show the paradox, do not explain it away: the last line hands the question to the viewer. If a known paradox is used, name it correctly and list the attribution in `claims`." },30 { slug: "tomorrows-cities", kind: "experimental", accent: "#8fc7a4", defaultLanguage: "en",31 titleEn: "Tomorrow's Cities", titleFr: "Villes de demain",32 descriptionEn: "Speculative architecture and urban futures, designed down to the street corner.",33 descriptionFr: "Architecture spéculative et futurs urbains, pensés jusqu'au coin de la rue.",34 rules: "One design decision and its effect on an ordinary day. Stay at human scale: a street, a room, a commute. Present it as speculation, never as a forecast or an existing project." },35 { slug: "objects-with-stories", kind: "fiction", accent: "#c9a37f", defaultLanguage: "en",36 titleEn: "Objects with Stories", titleFr: "Objets à histoires",37 descriptionEn: "Ordinary objects that turn out to matter more than anyone knew.",38 descriptionFr: "Des objets ordinaires qui comptent davantage que quiconque ne le pensait.",39 rules: "The object is in every shot and never speaks. Its meaning changes once, through what happens around it. Macro and close framing; hands rather than faces." },40 { slug: "ai-experiments", kind: "experimental", accent: "#9aa7b8", defaultLanguage: "en",41 titleEn: "AI Experiments", titleFr: "Expériences IA",42 descriptionEn: "Honest experiments on what generative media can and cannot do.",43 descriptionFr: "Des expériences honnêtes sur ce que les médias génératifs savent faire, et ne savent pas faire.",44 rules: "Pose one question about generative media and design the film as the test. Say on screen (in narration) what was attempted and what the model actually did, including the failure." },45 { slug: "bilingual-shorts", kind: "fiction", accent: "#e0a2b4", defaultLanguage: "bilingual",46 titleEn: "Bilingual Shorts", titleFr: "Courts bilingues",47 descriptionEn: "Stories written in French and English at once, where the two languages do different work.",48 descriptionFr: "Des histoires écrites en français et en anglais à la fois, où les deux langues ne font pas le même travail.",49 rules: "Alternate French and English lines so that each language says something the other does not. Never translate a line literally inside the film; the captions carry the other language." },50];5152export interface TagDef { slug: string; kind: "genre" | "mood" | "topic" | "technique" | "style"; en: string; fr: string }53const t = (kind: TagDef["kind"], rows: [string, string, string][]): TagDef[] => rows.map(([slug, en, fr]) => ({ slug, kind, en, fr }));54export const TAGS: TagDef[] = [55 ...t("genre", [["drama", "Drama", "Drame"], ["science", "Science", "Science"], ["speculative", "Speculative", "Spéculatif"], ["fable", "Fable", "Fable"], ["essay", "Essay", "Essai"], ["comedy", "Comedy", "Comédie"], ["mystery", "Mystery", "Mystère"], ["documentary-fiction", "Docu-fiction", "Docufiction"]]),56 ...t("mood", [["contemplative", "Contemplative", "Contemplatif"], ["melancholic", "Melancholic", "Mélancolique"], ["playful", "Playful", "Ludique"], ["tense", "Tense", "Tendu"], ["wondrous", "Wondrous", "Émerveillé"], ["tender", "Tender", "Tendre"], ["eerie", "Eerie", "Inquiétant"], ["hopeful", "Hopeful", "Plein d'espoir"]]),57 ...t("topic", [["time", "Time", "Temps"], ["memory", "Memory", "Mémoire"], ["physics", "Physics", "Physique"], ["mathematics", "Mathematics", "Mathématiques"], ["economics", "Economics", "Économie"], ["cities", "Cities", "Villes"], ["nature", "Nature", "Nature"], ["technology", "Technology", "Technologie"], ["language", "Language", "Langue"], ["everyday-objects", "Everyday objects", "Objets du quotidien"], ["space", "Space", "Espace"], ["perception", "Perception", "Perception"]]),58 ...t("technique", [["image-to-video", "Image-to-video", "Image vers vidéo"], ["narration", "Narration", "Narration"], ["macro", "Macro photography", "Macrophotographie"], ["single-location", "Single location", "Lieu unique"], ["long-take", "Long takes", "Plans longs"], ["visual-metaphor", "Visual metaphor", "Métaphore visuelle"], ["time-lapse", "Time-lapse", "Accéléré"]]),59 ...t("style", [["35mm", "35mm film", "Pellicule 35 mm"], ["noir", "Noir", "Noir"], ["miniature", "Miniature", "Miniature"], ["painterly", "Painterly", "Pictural"], ["minimal", "Minimal", "Minimaliste"], ["retro-futurist", "Retro-futurist", "Rétrofuturiste"], ["naturalist", "Naturalist", "Naturaliste"], ["stop-motion", "Stop-motion look", "Aspect image par image"]]),60];61export const tagVocabulary = () => (["genre", "mood", "topic", "technique", "style"] as const).map((k) => `${k}: ${TAGS.filter((x) => x.kind === k).map((x) => x.slug).join(", ")}`).join("\n");6263export const COLLECTIONS = [64 { slug: "first-light", titleEn: "First Light", titleFr: "Premières lueurs", descriptionEn: "The opening programme: the first films made by the system.", descriptionFr: "Le programme d'ouverture : les premiers films produits par le système." },65];66