Alex Dunmow 02a84ab31e feat(cyberpunk): Wave A build — 49 builtin overrides, 7 templates, canvas hero, seed
WO-TF-015 (game-studio / hacker-collective persona, GO-BIG motion).

- Overrides: all 49 mandatory builtin keys in templates/overrides/cyberpunk/
  (dashed keys), each restyled to neon-HUD chrome preserving builtin field
  reads + scripts. Legacy button/card/heading/text reconciled to new field
  names (label/link/style, text/media). Auth surface (auth-form,
  auth-status, password-reset-form) reproduces the builtin hardcoded HTMX
  endpoints + Cap widget verbatim. page-suggestions ships themed 404 chrome.
- Page templates: 7 (default, full-width, landing, article, blog-index,
  contact, auth), dual-mode via theme_mode, scanline overlay chrome.
- Hero override: dependency-free canvas digital-rain showpiece — lazy-init
  via IntersectionObserver, prefers-reduced-motion honored, static neon
  gradient no-JS fallback, token-derived colors only.
- Blocks: deleted 6 builtin-duplicating theme blocks (now overrides); kept
  code_neon (+ copy handler); added persona blocks glitch_hero, roster_grid,
  patch_notes with schemas + sample data.
- Presets: 5 (neon-noir, acid-rain, toxic-bloom, hotline, ghost-protocol),
  all 19 tokens, light+dark both tuned.
- Fonts: bundled OFL woff2 (Orbitron, Share Tech Mono, Inter latin subsets)
  in assets/fonts + fonts.json + LICENSES; all font-family via CSS vars.
- Email: preset-aware email-safe wrapper (tables, inline styles, colors.*).
- Master pages + demo seed (home, about, blog+3 posts, contact with
  data-table + row_inserted email-admins workflow, login).
- manifest CSS: hud-frame, clip-cut, cyberpunk-eyebrow, canvas-rain utils.
- plugin.mod + manifest required_icon_packs = [lucide, simple-icons].

make build + verify exit 0; check-safety exit 0.

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

220 lines
11 KiB
JSON

{
"demo": true,
"settings": {
"merge": {
"companyName": "Neon Forge",
"tagline": "We build games and the tools that ship them."
}
},
"data_tables": [
{
"key": "contact_submissions",
"name": "Contact Enquiries",
"description": "Seeded contact-form submissions for the Neon Forge demo. A submission becomes a row here and emails the site admins.",
"columns": [
{ "key": "name", "label": "Name", "type": "text", "required": true },
{ "key": "email", "label": "Email", "type": "email", "required": true },
{ "key": "studio", "label": "Studio", "type": "text", "required": false },
{ "key": "message", "label": "Message", "type": "text", "required": true }
]
}
],
"pages": [
{
"slug": "/",
"title": "Neon Forge",
"template_key": "landing",
"blocks": [
{
"block_key": "hero",
"title": "Hero",
"slot": "main",
"sort_order": 1,
"content": {
"template": "centered",
"minHeight": "screen",
"eyebrow": "Build 2.049",
"headline": "Ship the impossible",
"subheadline": "A game studio and the tools that ship it.",
"description": "We build a rendering engine, live ops, and a build farm that never sleeps. Then we make games on top of it.",
"ctaPrimary": { "text": "Get the SDK", "url": "/contact" },
"ctaSecondary": { "text": "Read the devlog", "url": "/blog" }
}
},
{
"block_key": "feature-grid",
"title": "What we ship",
"slot": "main",
"sort_order": 2,
"content": {
"eyebrow": "The stack",
"heading": "One pipeline, end to end",
"intro": "Engine, tooling, and live service. Built in house, shipped together.",
"layout": "card",
"columns": 3,
"items": [
{ "icon": "lucide:cpu", "title": "Render engine", "text": "Neon lighting, volumetric fog, and a deferred path tuned for night maps." },
{ "icon": "lucide:terminal", "title": "Build farm", "text": "Shader caching across branches. Green builds in minutes, not hours." },
{ "icon": "lucide:radio", "title": "Live ops", "text": "Ship events, patch balance, and roll back without a redeploy." }
]
}
},
{
"block_key": "cyberpunk:roster_grid",
"title": "The crew",
"slot": "main",
"sort_order": 3,
"content": {
"eyebrow": "The crew",
"heading": "Who ships this",
"intro": "A small team that builds the engine, the game, and the pipeline in between.",
"members": [
{ "name": "Nova Reyes", "handle": "@nova", "role": "Engine lead", "status": true },
{ "name": "Kai Okafor", "handle": "@kaisdf", "role": "Graphics", "status": true },
{ "name": "Sable Lin", "handle": "@sable", "role": "Live ops", "status": false },
{ "name": "Juno Vale", "handle": "@juno", "role": "Gameplay", "status": true },
{ "name": "Rin Castellano", "handle": "@rin", "role": "Tools", "status": true },
{ "name": "Ash Mori", "handle": "@ash", "role": "Netcode", "status": false }
]
}
},
{
"block_key": "cyberpunk:patch_notes",
"title": "Patch notes",
"slot": "main",
"sort_order": 4,
"content": {
"heading": "Patch notes",
"intro": "What changed, build by build.",
"entries": [
{ "version": "v2.049.0", "date": "2049.04.01", "tag": "FEATURE", "items": [ { "text": "Volumetric neon fog on all night maps." }, { "text": "Build farm caches shaders across branches." } ] },
{ "version": "v2.048.3", "date": "2049.03.18", "tag": "FIX", "items": [ { "text": "Fixed a stall when hot-reloading materials." }, { "text": "Reduced desync on high-latency links." } ] },
{ "version": "v2.048.0", "date": "2049.03.02", "tag": "BALANCE", "items": [ { "text": "Tuned dash cooldown from 4s to 3.2s." } ] }
]
}
},
{
"block_key": "cta",
"title": "CTA",
"slot": "main",
"sort_order": 5,
"content": {
"background": "band",
"heading": "Start building tonight",
"text": "Grab the SDK and ship your first build before the coffee runs out.",
"primaryLabel": "Get the SDK",
"primaryUrl": "/contact"
}
}
]
},
{
"slug": "/about",
"title": "The studio",
"template_key": "default",
"blocks": [
{ "block_key": "heading", "title": "Heading", "slot": "main", "sort_order": 1, "content": { "text": "The studio", "level": 1 } },
{ "block_key": "rich-text", "title": "Story", "slot": "main", "sort_order": 2, "content": { "html": "<p>Neon Forge started as a build tool for a game that shipped late. The tool outlived the game. We kept building it, then built more games to prove it out.</p><p>Now we run both. The engine and live service on one side, the games that stress test them on the other. Everything we make, we run in production first.</p>" } },
{ "block_key": "cyberpunk:code_neon", "title": "Quickstart", "slot": "main", "sort_order": 3, "content": { "language": "bash", "code": "npm install @neon-forge/sdk\nnpx neon-forge init my-game\nnpx neon-forge ship --stage prod", "copy": "on" } },
{ "block_key": "divider", "title": "Divider", "slot": "main", "sort_order": 4, "content": { "variant": "line", "weight": "medium" } },
{ "block_key": "quote", "title": "Quote", "slot": "main", "sort_order": 5, "content": { "style": "pull", "quote": "Build the tool. Ship the game. Repeat.", "attribution": "The studio" } }
]
},
{
"slug": "/blog",
"title": "Devlog",
"template_key": "blog-index",
"blocks": [
{ "block_key": "card", "title": "Post: Rain", "slot": "main", "sort_order": 1, "content": { "layout": "vertical", "title": "Making it rain", "text": "<p>How we built a dependency-free digital-rain effect that stays smooth at 60 fps.</p>", "link": "/blog/making-it-rain", "linkLabel": "Read on" } },
{ "block_key": "card", "title": "Post: Shaders", "slot": "main", "sort_order": 2, "content": { "layout": "vertical", "title": "Caching shaders across branches", "text": "<p>Green builds in minutes. What we changed in the build farm and why.</p>", "link": "/blog/caching-shaders", "linkLabel": "Read on" } },
{ "block_key": "card", "title": "Post: Netcode", "slot": "main", "sort_order": 3, "content": { "layout": "vertical", "title": "Netcode on bad links", "text": "<p>Cutting desync on 200ms connections without rewriting the sim.</p>", "link": "/blog/netcode-bad-links", "linkLabel": "Read on" } }
]
},
{
"slug": "/blog/making-it-rain",
"title": "Making it rain",
"template_key": "article",
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "Making it rain", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>The hero on our home page runs a digital-rain canvas. No libraries, no images, just a small script that draws falling glyphs.</p><p>The trick is to fade the last frame instead of clearing it. That leaves a trail. Cap the frame rate and it stays cheap, even on a laptop.</p>" } }
]
},
{
"slug": "/blog/caching-shaders",
"title": "Caching shaders across branches",
"template_key": "article",
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "Caching shaders across branches", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>Every branch used to recompile the whole shader set. That is minutes per build, times every push.</p><p>We keyed the cache on the shader source, not the branch. Two branches that share a shader now share the compile. Builds got short again.</p>" } }
]
},
{
"slug": "/blog/netcode-bad-links",
"title": "Netcode on bad links",
"template_key": "article",
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "Netcode on bad links", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>Players on slow connections kept desyncing. Rewriting the simulation was off the table.</p><p>We added client prediction with a short rollback window. The client guesses, the server corrects, and the gap closes before anyone notices.</p>" } }
]
},
{
"slug": "/contact",
"title": "Contact",
"template_key": "contact",
"blocks": [
{
"block_key": "contact-form",
"title": "Contact form",
"slot": "main",
"sort_order": 1,
"content": {
"heading": "Request access",
"description": "Tell us what you are building. We reply within one business day.",
"submitLabel": "Request access",
"successMessage": "Message received. We will reply within one business day.",
"fields": [
{ "name": "name", "label": "Your name", "type": "text", "required": true, "width": "half" },
{ "name": "email", "label": "Email", "type": "email", "required": true, "width": "half" },
{ "name": "studio", "label": "Studio", "type": "text", "required": false, "width": "full" },
{ "name": "message", "label": "What are you building", "type": "textarea", "required": true, "width": "full" }
],
"formConfig": { "enabled": true, "captchaEnabled": false, "targetTable": "contact_submissions" }
}
},
{
"block_key": "contact-card",
"title": "Reach us",
"slot": "main",
"sort_order": 2,
"content": {
"heading": "Other ways in",
"columns": 3,
"channels": [
{ "icon": "lucide:mail", "label": "Email", "value": "crew@neonforge.dev", "link": "mailto:crew@neonforge.dev" },
{ "icon": "simple-icons:github", "label": "Source", "value": "github.com/neon-forge", "link": "https://github.com/neon-forge" },
{ "icon": "lucide:message-square", "label": "Discord", "value": "Join the build channel", "link": "#" }
]
}
}
]
},
{
"slug": "/login",
"title": "Sign in",
"template_key": "auth",
"blocks": [
{ "block_key": "auth-form", "title": "Sign in", "slot": "main", "sort_order": 1, "content": { "default_tab": "login", "show_social": false } }
]
}
],
"menu_items": [
{ "menu": "main", "label": "Home", "page_slug": "/", "sort_order": 1 },
{ "menu": "main", "label": "Studio", "page_slug": "/about", "sort_order": 2 },
{ "menu": "main", "label": "Devlog", "page_slug": "/blog", "sort_order": 3 },
{ "menu": "main", "label": "Contact", "page_slug": "/contact", "sort_order": 4 }
]
}