Full Wave A build to the OVERRIDE-CONTRACT (frozen cms a0f07e2ae): - 49 mandatory builtin overrides in templates/overrides/magazine-bold/, re-skinned to streetwear cover-story chrome (massive condensed uppercase Archivo Black headlines, heavy 2px rules, hard square edges, mono datelines, fluoro accent slabs). Every content field, provider var, custom tag and JS block preserved verbatim from the frozen builtin defaults; legacy button (link/style/label) and card (media/text) field reads already reconciled. - 7 page templates: default, full-width, landing, article, blog-index, contact, auth. - 4 persona blocks (deleted masthead/photo_essay/pull_quote/issue_archive/ colophon — now overrides of navbar/gallery/quote/post-index/footer): cover_story, lookbook, drop_calendar, credits_ticker. - 5 dual-mode presets (newsprint+voltage light / ink-black+fluoro dark), all 19 tokens, dark tuned not inverted. - Bundled OFL woff2: Archivo Black (display), Inter (body), IBM Plex Mono (labels); fonts.json + assets/fonts/LICENSES.md. All font-family via var(--font-heading|body|mono, fallback). - Themed email-safe wrapper (tables, inline styles, streetwear defaults). - Master pages (navbar/footer/slot chrome) + seed demo site (OFFCUT label: home, about, blog + 3 posts, contact with data table + row_inserted → email-admins workflow, login) in fashion-label voice. - MID motion tier: marquee ticker, scroll reveal, duotone hover, scroll progress bar — all prefers-reduced-motion honored with static fallback, no canvas. - Icon packs (lucide, simple-icons) declared in plugin.mod + RECOMMENDED_ICONS. Verified: `make build` exit 0; `check-safety` 32 checks 19 ok 13 skip -> OK. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
230 lines
14 KiB
JSON
230 lines
14 KiB
JSON
{
|
|
"demo": true,
|
|
"settings": {
|
|
"merge": {
|
|
"companyName": "OFFCUT",
|
|
"tagline": "A streetwear label and its cover stories."
|
|
}
|
|
},
|
|
"data_tables": [
|
|
{
|
|
"key": "contact_submissions",
|
|
"name": "Studio Inbox",
|
|
"description": "Seeded contact-form submissions for the OFFCUT 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": "subject", "label": "Subject", "type": "text", "required": false },
|
|
{ "key": "message", "label": "Message", "type": "text", "required": true }
|
|
]
|
|
}
|
|
],
|
|
"pages": [
|
|
{
|
|
"slug": "/",
|
|
"title": "OFFCUT",
|
|
"template_key": "landing",
|
|
"blocks": [
|
|
{
|
|
"block_key": "magazine-bold:cover_story",
|
|
"title": "Cover",
|
|
"slot": "lead",
|
|
"sort_order": 1,
|
|
"content": {
|
|
"kicker": "Drop 04 / Spring",
|
|
"headline": "Cut from the offcuts",
|
|
"deck": "One drop. Made from last season's leftover cloth. Nothing reordered.",
|
|
"link": "/drops",
|
|
"linkLabel": "See the drop"
|
|
}
|
|
},
|
|
{
|
|
"block_key": "magazine-bold:credits_ticker",
|
|
"title": "Credits",
|
|
"slot": "lead",
|
|
"sort_order": 2,
|
|
"content": { "items": [ { "label": "Photography Kit Sato" }, { "label": "Styling Remi Vaughn" }, { "label": "Cast Ari, Dune, Lux" }, { "label": "Set The Old Print Works" } ] }
|
|
},
|
|
{
|
|
"block_key": "heading",
|
|
"title": "River heading",
|
|
"slot": "river",
|
|
"sort_order": 1,
|
|
"content": { "text": "From the studio", "level": 2 }
|
|
},
|
|
{
|
|
"block_key": "card",
|
|
"title": "Story: Offcut method",
|
|
"slot": "river",
|
|
"sort_order": 2,
|
|
"content": { "layout": "vertical", "title": "The offcut method", "text": "<p>How we build a full drop from cloth other people threw away.</p>", "link": "/blog/the-offcut-method", "linkLabel": "Read the story" }
|
|
},
|
|
{
|
|
"block_key": "card",
|
|
"title": "Story: Casting the block",
|
|
"slot": "river",
|
|
"sort_order": 3,
|
|
"content": { "layout": "vertical", "title": "Casting off the block", "text": "<p>We cast the drop on the street it was cut on. Here is who showed up.</p>", "link": "/blog/casting-off-the-block", "linkLabel": "Read the story" }
|
|
},
|
|
{
|
|
"block_key": "card",
|
|
"title": "Story: One colour",
|
|
"slot": "river",
|
|
"sort_order": 4,
|
|
"content": { "layout": "vertical", "title": "One colour, all season", "text": "<p>Why the whole drop runs a single fluoro accent, and nothing else.</p>", "link": "/blog/one-colour-all-season", "linkLabel": "Read the story" }
|
|
},
|
|
{
|
|
"block_key": "magazine-bold:drop_calendar",
|
|
"title": "Drops",
|
|
"slot": "river",
|
|
"sort_order": 5,
|
|
"content": {
|
|
"heading": "Drop calendar",
|
|
"intro": "Every drop is one run. When it is gone it is gone.",
|
|
"drops": [
|
|
{ "date": "14 MAR", "name": "Offcut 04", "detail": "Spring drop. Reworked shell jackets and cargo sets.", "status": "live" },
|
|
{ "date": "02 MAY", "name": "Offcut 05", "detail": "Workwear capsule. Signed up members first.", "status": "soon" },
|
|
{ "date": "09 FEB", "name": "Offcut 03", "detail": "Winter drop. Fleece and heavy cotton.", "status": "sold" }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"block_key": "newsletter-signup",
|
|
"title": "Drop alerts",
|
|
"slot": "river",
|
|
"sort_order": 6,
|
|
"content": { "title": "Drop alerts", "description": "One email per drop. We tell you when, and nothing else.", "listSlug": "main", "source": "home", "submitText": "Get alerts", "successMessage": "You are on the list. Watch your inbox before the next drop.", "placeholder": "you@example.com", "layout": "card" }
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"slug": "/about",
|
|
"title": "About",
|
|
"template_key": "default",
|
|
"blocks": [
|
|
{ "block_key": "heading", "title": "Heading", "slot": "main", "sort_order": 1, "content": { "text": "About OFFCUT", "level": 1 } },
|
|
{ "block_key": "rich-text", "title": "Bio", "slot": "main", "sort_order": 2, "content": { "html": "<p>OFFCUT is a streetwear label built on leftover cloth. We buy end-of-run rolls that mills cannot sell and cut them into short, numbered drops.</p><p>Every drop is one run. We do not reorder. When a size is gone it stays gone. That keeps the work honest and keeps the waste down.</p><p>The studio is in an old print works. The photography, the lookbook and the label all come out of the same room.</p>" } },
|
|
{
|
|
"block_key": "magazine-bold:lookbook",
|
|
"title": "Lookbook",
|
|
"slot": "main",
|
|
"sort_order": 3,
|
|
"content": {
|
|
"heading": "Drop 04 lookbook",
|
|
"intro": "Shot on the block, styled in one colour.",
|
|
"looks": [
|
|
{ "caption": "Shell jacket, offcut nylon", "credit": "On Ari" },
|
|
{ "caption": "Cargo set, reworked cotton", "credit": "On Dune" },
|
|
{ "caption": "Fleece half-zip", "credit": "On Lux" }
|
|
]
|
|
}
|
|
},
|
|
{ "block_key": "quote", "title": "Quote", "slot": "main", "sort_order": 4, "content": { "style": "block", "align": "center", "quote": "We only make what we can cut from what is already there.", "attribution": "OFFCUT studio" } }
|
|
]
|
|
},
|
|
{
|
|
"slug": "/blog",
|
|
"title": "Stories",
|
|
"template_key": "blog-index",
|
|
"blocks": [
|
|
{ "block_key": "card", "title": "Featured: Offcut method", "slot": "featured", "sort_order": 1, "content": { "layout": "horizontal", "title": "The offcut method", "text": "<p>How we build a full drop from cloth other people threw away. The lead story this season.</p>", "link": "/blog/the-offcut-method", "linkLabel": "Read the story" } },
|
|
{ "block_key": "card", "title": "Post: Casting the block", "slot": "main", "sort_order": 1, "content": { "layout": "vertical", "title": "Casting off the block", "text": "<p>We cast the drop on the street it was cut on.</p>", "link": "/blog/casting-off-the-block", "linkLabel": "Read on" } },
|
|
{ "block_key": "card", "title": "Post: One colour", "slot": "main", "sort_order": 2, "content": { "layout": "vertical", "title": "One colour, all season", "text": "<p>Why the whole drop runs a single fluoro accent.</p>", "link": "/blog/one-colour-all-season", "linkLabel": "Read on" } },
|
|
{ "block_key": "card", "title": "Post: The offcut method again", "slot": "main", "sort_order": 3, "content": { "layout": "vertical", "title": "Numbering the run", "text": "<p>Every piece is numbered by hand. Here is why that matters.</p>", "link": "/blog/the-offcut-method", "linkLabel": "Read on" } }
|
|
]
|
|
},
|
|
{
|
|
"slug": "/blog/the-offcut-method",
|
|
"title": "The offcut method",
|
|
"template_key": "article",
|
|
"parent_slug": "/blog",
|
|
"blocks": [
|
|
{ "block_key": "text", "title": "Byline", "slot": "byline", "sort_order": 1, "content": { "text": "<p>By the OFFCUT studio. Drop 04.</p>" } },
|
|
{ "block_key": "text", "title": "Lead", "slot": "main", "sort_order": 1, "content": { "text": "<p>Most labels start with a colour card and a factory minimum. We start with a phone call about a roll of cloth that nobody wants. That is the whole method, and it shapes everything after it.</p>" } },
|
|
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>Mills end every season with rolls they cannot sell. Wrong shade, short length, last year's spec. We buy those rolls cheap and we buy them whole. Then we cut a drop around what we actually have.</p><p>That means the run is short. A roll makes forty jackets, not four hundred. When it is cut, the pattern retires. The next drop uses a different cloth and looks like a different label, because it is a different cloth.</p><p>People ask us to reorder. We cannot, and we would not. The limit is the point.</p>" } },
|
|
{ "block_key": "quote", "title": "Gutter quote", "slot": "marginalia", "sort_order": 1, "content": { "style": "pull", "align": "left", "quote": "A roll makes forty jackets, not four hundred.", "attribution": "Drop 04" } }
|
|
]
|
|
},
|
|
{
|
|
"slug": "/blog/casting-off-the-block",
|
|
"title": "Casting off the block",
|
|
"template_key": "article",
|
|
"parent_slug": "/blog",
|
|
"blocks": [
|
|
{ "block_key": "text", "title": "Byline", "slot": "byline", "sort_order": 1, "content": { "text": "<p>By the OFFCUT studio. Drop 04.</p>" } },
|
|
{ "block_key": "text", "title": "Lead", "slot": "main", "sort_order": 1, "content": { "text": "<p>We do not book models through an agency. We cast the drop on the street it was cut on, and we shoot the people who show up. Here is how the casting went.</p>" } },
|
|
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>We put up one poster outside the print works. It gave a date, a time, and nothing else. On the day, thirty people came by. Some knew the label. Most did not.</p><p>We shot everyone in the same set, in the same light, in one colour. No hair, no retouching past the basics. The clothes had to carry the frame, so we let them.</p><p>The cast in the lookbook are the people who came. That is the only rule we kept.</p>" } },
|
|
{ "block_key": "quote", "title": "Gutter quote", "slot": "marginalia", "sort_order": 1, "content": { "style": "pull", "align": "left", "quote": "We shoot the people who show up.", "attribution": "Casting" } }
|
|
]
|
|
},
|
|
{
|
|
"slug": "/blog/one-colour-all-season",
|
|
"title": "One colour, all season",
|
|
"template_key": "article",
|
|
"parent_slug": "/blog",
|
|
"blocks": [
|
|
{ "block_key": "text", "title": "Byline", "slot": "byline", "sort_order": 1, "content": { "text": "<p>By the OFFCUT studio. Drop 04.</p>" } },
|
|
{ "block_key": "text", "title": "Lead", "slot": "main", "sort_order": 1, "content": { "text": "<p>The whole drop runs one accent colour. It is on the labels, the site, the poster and the tape on the boxes. There is nothing else, and that is on purpose.</p>" } },
|
|
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>A single colour makes a small label look sure of itself. It also makes the work easy to spot in a feed full of noise. One fluoro hit, black ink, newsprint paper, and you know it is us before you read a word.</p><p>Next drop the colour changes. The system stays. One accent, held all the way through, then swapped clean for the next run.</p>" } },
|
|
{ "block_key": "quote", "title": "Gutter quote", "slot": "marginalia", "sort_order": 1, "content": { "style": "pull", "align": "left", "quote": "One fluoro hit, black ink, newsprint paper.", "attribution": "House style" } }
|
|
]
|
|
},
|
|
{
|
|
"slug": "/contact",
|
|
"title": "Studio",
|
|
"template_key": "contact",
|
|
"blocks": [
|
|
{
|
|
"block_key": "contact-form",
|
|
"title": "Write to the studio",
|
|
"slot": "main",
|
|
"sort_order": 1,
|
|
"content": {
|
|
"heading": "Write to the studio",
|
|
"description": "Stockist requests, press, or a question about a drop. We read everything.",
|
|
"submitLabel": "Send",
|
|
"successMessage": "Thank you. Your note reached the studio. We will write back.",
|
|
"fields": [
|
|
{ "name": "name", "label": "Your name", "type": "text", "required": true, "width": "half" },
|
|
{ "name": "email", "label": "Email", "type": "email", "required": true, "width": "half" },
|
|
{ "name": "subject", "label": "Subject", "type": "text", "required": false, "width": "full" },
|
|
{ "name": "message", "label": "Your note", "type": "textarea", "required": true, "width": "full" }
|
|
],
|
|
"formConfig": { "enabled": true, "captchaEnabled": false, "targetTable": "contact_submissions" }
|
|
}
|
|
},
|
|
{
|
|
"block_key": "contact-card",
|
|
"title": "Other ways to reach us",
|
|
"slot": "aside",
|
|
"sort_order": 1,
|
|
"content": {
|
|
"heading": "Elsewhere",
|
|
"description": "The studio inbox is best. These work too.",
|
|
"columns": 1,
|
|
"channels": [
|
|
{ "icon": "lucide:mail", "label": "Email", "value": "studio@offcut.example", "link": "mailto:studio@offcut.example" },
|
|
{ "icon": "lucide:map-pin", "label": "Studio", "value": "The Old Print Works", "link": "" }
|
|
]
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"slug": "/login",
|
|
"title": "Members",
|
|
"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>Members get the next drop before it goes public.</p>" } }
|
|
]
|
|
}
|
|
],
|
|
"menu_items": [
|
|
{ "menu": "main", "label": "Home", "page_slug": "/", "sort_order": 1 },
|
|
{ "menu": "main", "label": "Stories", "page_slug": "/blog", "sort_order": 2 },
|
|
{ "menu": "main", "label": "About", "page_slug": "/about", "sort_order": 3 },
|
|
{ "menu": "main", "label": "Studio", "page_slug": "/contact", "sort_order": 4 }
|
|
]
|
|
}
|