themes-noir/seed/seed.json
Alex Dunmow 1451f06d9f feat(noir): WO-TF-022 Wave A — detective/true-crime dossier rebuild
Re-persona noir from photography to the locked detective/true-crime
direction: case-file panels, typewriter type, redaction bars, evidence
board, film grain. High-key gallery (light) / darkroom black + amber
safelight (dark).

- 49 mandatory builtin overrides (chrome, marketing, primitives,
  commerce, blog family, auth, page-suggestions), re-skinned from the
  frozen builtin defaults with every field/provider/tag/JS preserved;
  legacy button/card field reads reconciled to the new contract.
- 7 page templates (default, full-width, landing, article, blog-index,
  contact, auth) + themed email wrapper.
- 4 persona blocks (case_file, evidence_board, redacted_quote,
  case_dossier); old photography blocks deleted (now overrides).
- 5 dual-mode presets (19 tokens, light+dark tuned).
- Bundled OFL fonts (Source Serif 4, IBM Plex Mono) + licenses;
  RECOMMENDED_FONTS/ICONS updated; required_icon_packs=lucide.
- Master pages + seed demo ("The Cold File": home/about/blog x3/contact
  with case_tips data table + row_inserted email-admins workflow/login).
- noir CSS vocabulary via manifest css.input_css_append; MID motion
  (scroll-reveal + gallery lightbox, reduced-motion honored, no canvas).

Verified: make build exit 0; check-safety 32 checks 19 ok 13 skip -> OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 12:48:44 +08:00

220 lines
11 KiB
JSON

{
"demo": true,
"settings": {
"merge": {
"companyName": "The Cold File",
"tagline": "Cases that were never closed."
}
},
"data_tables": [
{
"key": "case_tips",
"name": "Case Tips",
"description": "Seeded tip-line submissions for The Cold File demo. A submission becomes a row here and emails the site admins.",
"columns": [
{ "key": "name", "label": "Name", "type": "text", "required": false },
{ "key": "email", "label": "Email", "type": "email", "required": true },
{ "key": "subject", "label": "Case or subject", "type": "text", "required": false },
{ "key": "message", "label": "Message", "type": "text", "required": true }
]
}
],
"pages": [
{
"slug": "/",
"title": "The Cold File",
"template_key": "landing",
"blocks": [
{
"block_key": "hero",
"title": "Hero",
"slot": "main",
"sort_order": 1,
"content": {
"template": "centered",
"eyebrow": "A true-crime file",
"headline": "The Cold File",
"subheadline": "Cases that were never closed.",
"description": "We read the record, walk the ground, and lay out what is known. One case at a time. You decide what it adds up to.",
"ctaPrimary": { "text": "Read the files", "url": "/blog" },
"ctaSecondary": { "text": "Submit a tip", "url": "/contact" }
}
},
{
"block_key": "noir:case_file",
"title": "Featured case",
"slot": "main",
"sort_order": 2,
"content": {
"caseNumber": "CF-0451",
"subject": "The Harbour Light",
"status": "cold",
"summary": "A night watchman clocked out at two and never reached the gate. His lamp was still burning at dawn. The tide had turned twice.",
"fields": [
{ "label": "Filed", "value": "March 1998" },
{ "label": "Location", "value": "Pier 9, East Dock" },
{ "label": "Last contact", "value": "02:04, radio check" },
{ "label": "Status", "value": "Open, unsolved" }
]
}
},
{
"block_key": "feature-grid",
"title": "How we work",
"slot": "main",
"sort_order": 3,
"content": {
"eyebrow": "Method",
"heading": "How we work a file",
"intro": "No theory before the record. We build the case from what can be checked.",
"columns": 3,
"layout": "card",
"items": [
{ "icon": "lucide:file-text", "title": "Read the record", "text": "Reports, transcripts, and the file as it was left. We start where the paper starts." },
{ "icon": "lucide:map-pin", "title": "Walk the ground", "text": "We stand where it happened and check the file against the place." },
{ "icon": "lucide:search", "title": "Follow the thread", "text": "One fact at a time. We show our work and mark what stays unknown." }
]
}
},
{
"block_key": "noir:redacted_quote",
"title": "Transcript",
"slot": "main",
"sort_order": 4,
"content": {
"label": "Interview 3, page 12",
"quote": "I told them what I saw at the water. They wrote it down and the name came back",
"redacted": "withheld pending review",
"attribution": "Witness statement",
"source": "Case CF-0451, sealed appendix"
}
},
{
"block_key": "cta",
"title": "Closing CTA",
"slot": "main",
"sort_order": 5,
"content": {
"background": "band",
"heading": "Know something we don't?",
"text": "Tips are read in confidence. Names stay off the page unless you ask otherwise.",
"primaryLabel": "Submit a tip",
"primaryUrl": "/contact",
"secondaryLabel": "Read the files",
"secondaryUrl": "/blog"
}
}
]
},
{
"slug": "/about",
"title": "About the File",
"template_key": "default",
"blocks": [
{ "block_key": "heading", "title": "Heading", "slot": "main", "sort_order": 1, "content": { "text": "About the File", "level": 1 } },
{ "block_key": "rich-text", "title": "Story", "slot": "main", "sort_order": 2, "content": { "html": "<p>The Cold File is a true-crime publication. We take one unsolved case at a time and set it out plainly, from the record up.</p><p>We do not name the guilty. We do not sell a theory. We show what is known, mark what is not, and leave the reader to weigh it. When new facts arrive, the file is updated in the open.</p>" } },
{ "block_key": "divider", "title": "Divider", "slot": "main", "sort_order": 3, "content": { "variant": "line", "weight": "thick", "width": "narrow" } },
{ "block_key": "quote", "title": "Quote", "slot": "main", "sort_order": 4, "content": { "style": "pull", "align": "center", "quote": "A cold case is not a closed one. It is a file waiting for one more fact.", "attribution": "The Cold File" } }
]
},
{
"slug": "/blog",
"title": "The Case Files",
"template_key": "blog-index",
"blocks": [
{ "block_key": "card", "title": "Case: Harbour Light", "slot": "main", "sort_order": 1, "content": { "layout": "vertical", "title": "The Harbour Light", "text": "<p>A watchman clocked out and never reached the gate. The lamp burned until dawn.</p>", "link": "/blog/the-harbour-light", "linkLabel": "Open the file" } },
{ "block_key": "card", "title": "Case: Room 14", "slot": "main", "sort_order": 2, "content": { "layout": "vertical", "title": "Room 14", "text": "<p>A guest checked in under a false name and left one suitcase behind. Nobody saw the door open.</p>", "link": "/blog/room-14", "linkLabel": "Open the file" } },
{ "block_key": "card", "title": "Case: The Last Bus", "slot": "main", "sort_order": 3, "content": { "layout": "vertical", "title": "The Last Bus", "text": "<p>The driver logged the final stop on time. The bus reached the depot empty and locked from inside.</p>", "link": "/blog/the-last-bus", "linkLabel": "Open the file" } }
]
},
{
"slug": "/blog/the-harbour-light",
"title": "The Harbour Light",
"template_key": "article",
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "The Harbour Light", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>The watchman made his last radio check at four minutes past two. He was due at the gate by half past. He never signed out.</p><p>The lamp on Pier 9 was still lit at dawn. The tide had turned twice. No boat was reported missing. No body was found. The file was opened, worked for a season, and set aside.</p><p>We walked the pier at the same hour. The record and the place do not agree on one point. We are still checking which one is wrong.</p>" } }
]
},
{
"slug": "/blog/room-14",
"title": "Room 14",
"template_key": "article",
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "Room 14", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>The guest signed the register in a hand that did not match the name. He paid a week in advance and asked for the quiet end of the hall.</p><p>On the fourth night the room went dark and stayed that way. The suitcase was still there. The bed was made. The window was latched from the inside.</p><p>The file lists three people who saw him arrive and none who saw him leave. We are trying to reconcile that.</p>" } }
]
},
{
"slug": "/blog/the-last-bus",
"title": "The Last Bus",
"template_key": "article",
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "The Last Bus", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>The driver logged the final stop on schedule. Twelve minutes later the bus rolled into the depot. It was empty and the doors were locked from inside.</p><p>The fare box held the right count for a full run. The seats were cold. The last passenger on the ticket record never reached home.</p><p>We have the route, the timing, and the log. What we do not have is the twelve minutes.</p>" } }
]
},
{
"slug": "/contact",
"title": "Tip Line",
"template_key": "contact",
"blocks": [
{
"block_key": "contact-form",
"title": "Tip Line",
"slot": "main",
"sort_order": 1,
"content": {
"heading": "Submit a tip",
"description": "Tips are read in confidence. Tell us the case and what you know. Leave contact details only if you want a reply.",
"submitLabel": "Send tip",
"successMessage": "Thank you. Your tip has been logged. We read every one.",
"fields": [
{ "name": "name", "label": "Your name", "type": "text", "required": false, "width": "half" },
{ "name": "email", "label": "Email", "type": "email", "required": true, "width": "half" },
{ "name": "subject", "label": "Case or subject", "type": "text", "required": false, "width": "full" },
{ "name": "message", "label": "What do you know?", "type": "textarea", "required": true, "width": "full" }
],
"formConfig": { "enabled": true, "captchaEnabled": false, "targetTable": "case_tips" }
}
},
{
"block_key": "hours-location",
"title": "Where to find us",
"slot": "aside",
"sort_order": 1,
"content": {
"heading": "The Desk",
"hours": [
{ "day": "Monday to Friday", "hours": "9am to 6pm" },
{ "day": "Saturday", "hours": "By appointment" },
{ "day": "Sunday", "closed": true }
],
"specialHoursNote": "Tips are read outside these hours. Replies are not.",
"address": "Room 14, The Old Exchange\nEast Dock",
"phone": "+1 555 0199"
}
}
]
},
{
"slug": "/login",
"title": "Access",
"template_key": "auth",
"blocks": [
{ "block_key": "auth-form", "title": "Sign in", "slot": "main", "sort_order": 1, "content": { "default_tab": "login", "show_social": false } },
{ "block_key": "text", "title": "Foot", "slot": "footer", "sort_order": 1, "content": { "text": "<p>Registered readers get new files first and the sealed appendices as they clear review.</p>" } }
]
}
],
"menu_items": [
{ "menu": "main", "label": "Home", "page_slug": "/", "sort_order": 1 },
{ "menu": "main", "label": "The Case Files", "page_slug": "/blog", "sort_order": 2 },
{ "menu": "main", "label": "About the File", "page_slug": "/about", "sort_order": 3 },
{ "menu": "main", "label": "Tip Line", "page_slug": "/contact", "sort_order": 4 }
]
}