Bootstrapped during the 2026-06-06 BlockNinja consolidation. Was previously an unversioned directory inside ~/src/blockninja-themes/y2k. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
174 lines
5.7 KiB
Go
174 lines
5.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/a-h/templ"
|
|
|
|
"git.dev.alexdunmow.com/block/core/blocks"
|
|
"git.dev.alexdunmow.com/block/core/plugin"
|
|
"git.dev.alexdunmow.com/block/core/templates"
|
|
)
|
|
|
|
// wrap adapts a templ-returning render function to templates.TemplateFunc.
|
|
// templ.Component already implements templates.HTMLComponent via Render.
|
|
func wrap(f func(ctx context.Context, doc map[string]any) templ.Component) templates.TemplateFunc {
|
|
return func(ctx context.Context, doc map[string]any) templates.HTMLComponent {
|
|
return f(ctx, doc)
|
|
}
|
|
}
|
|
|
|
// Register registers the y2k system template, its four page templates, all
|
|
// theme-specific blocks, the four built-in overrides, and the email wrapper.
|
|
//
|
|
// Call order: page templates can be registered any time, but schemas MUST load
|
|
// before any block Register call.
|
|
func Register(tr templates.TemplateRegistry, br blocks.BlockRegistry) error {
|
|
// 1. System template
|
|
tr.RegisterSystemTemplate(templates.SystemTemplateMeta{
|
|
Key: "y2k",
|
|
Title: "Y2K",
|
|
Description: "Liquid-chrome Y2K revival theme for indie musicians, zines, and merch shops.",
|
|
})
|
|
|
|
// 2. Page templates (slots match the spec verbatim)
|
|
if err := tr.RegisterPageTemplate("y2k", templates.PageTemplateMeta{
|
|
Key: "default",
|
|
Title: "Default",
|
|
Description: "Chrome navbar + content + footer.",
|
|
Slots: []string{"header", "main", "footer"},
|
|
}, wrap(RenderY2K)); err != nil {
|
|
return err
|
|
}
|
|
if err := tr.RegisterPageTemplate("y2k", templates.PageTemplateMeta{
|
|
Key: "landing",
|
|
Title: "Landing",
|
|
Description: "Hero metaball + marquee + CTAs.",
|
|
Slots: []string{"hero", "marquee", "main", "cta", "footer"},
|
|
}, wrap(RenderY2KLanding)); err != nil {
|
|
return err
|
|
}
|
|
if err := tr.RegisterPageTemplate("y2k", templates.PageTemplateMeta{
|
|
Key: "article",
|
|
Title: "Article / Zine Page",
|
|
Description: "Narrow column with sidebar tracklist.",
|
|
Slots: []string{"header", "main", "aside", "footer"},
|
|
}, wrap(RenderY2KArticle)); err != nil {
|
|
return err
|
|
}
|
|
if err := tr.RegisterPageTemplate("y2k", templates.PageTemplateMeta{
|
|
Key: "full-width",
|
|
Title: "Full Width",
|
|
Description: "Edge-to-edge gradient mesh canvas.",
|
|
Slots: []string{"header", "main", "footer"},
|
|
}, wrap(RenderY2KFullWidth)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// 3. Schemas first — must precede br.Register so they bind.
|
|
if err := br.LoadSchemasFromFS(Schemas()); err != nil {
|
|
return err
|
|
}
|
|
|
|
// 4. Theme-specific blocks (10 total per spec §11).
|
|
br.Register(ChromeNavbarBlockMeta, ChromeNavbarBlock)
|
|
br.Register(MetaballHeroBlockMeta, MetaballHeroBlock)
|
|
br.Register(WaveformPlayerBlockMeta, WaveformPlayerBlock)
|
|
br.Register(MarqueeBlockMeta, MarqueeBlock)
|
|
br.Register(TracklistBlockMeta, TracklistBlock)
|
|
br.Register(MerchCardBlockMeta, MerchCardBlock)
|
|
br.Register(WebringBadgeBlockMeta, WebringBadgeBlock)
|
|
br.Register(GlitterDividerBlockMeta, GlitterDividerBlock)
|
|
br.Register(FooterChromeBlockMeta, FooterChromeBlock)
|
|
br.Register(NFTGalleryBlockMeta, NFTGalleryBlock)
|
|
|
|
// 5. Built-in overrides (only apply when y2k is the active theme).
|
|
br.RegisterTemplateOverride("y2k", "heading", Y2KHeadingBlock)
|
|
br.RegisterTemplateOverride("y2k", "text", Y2KTextBlock)
|
|
br.RegisterTemplateOverride("y2k", "button", Y2KButtonBlock)
|
|
br.RegisterTemplateOverride("y2k", "image", Y2KImageBlock)
|
|
|
|
// 6. Email wrapper for branded transactional mail.
|
|
tr.RegisterEmailWrapper("y2k", Y2KEmailWrapper)
|
|
|
|
return nil
|
|
}
|
|
|
|
// DefaultMasterPages returns the master pages that y2k seeds on first load.
|
|
// Block keys reference theme-owned blocks as "y2k:<key>"; the built-in slot
|
|
// block uses {"slotName":"main"} per CLAUDE.md.
|
|
func DefaultMasterPages() []plugin.MasterPageDefinition {
|
|
return []plugin.MasterPageDefinition{
|
|
{
|
|
Key: "y2k:default-master",
|
|
Title: "Y2K Default Master",
|
|
PageTemplates: []string{"default", "article"},
|
|
Blocks: []plugin.MasterPageBlock{
|
|
{
|
|
BlockKey: "y2k:chrome_navbar",
|
|
Title: "Chrome Navbar",
|
|
Content: map[string]any{"menuName": "main", "logoText": "y2k.fm"},
|
|
Slot: "header",
|
|
SortOrder: 0,
|
|
},
|
|
{
|
|
BlockKey: "y2k:marquee",
|
|
Title: "Top Marquee",
|
|
Content: map[string]any{"items": []any{"new drop friday", "listen on bandcamp", "subscribe to the zine"}, "speed": "medium"},
|
|
Slot: "header",
|
|
SortOrder: 1,
|
|
},
|
|
{
|
|
BlockKey: "slot",
|
|
Title: "Main Slot",
|
|
Content: map[string]any{"slotName": "main"},
|
|
Slot: "main",
|
|
SortOrder: 0,
|
|
},
|
|
{
|
|
BlockKey: "y2k:footer_chrome",
|
|
Title: "Chrome Footer",
|
|
Content: map[string]any{"showWebring": true, "copyright": "(c) y2k.fm"},
|
|
Slot: "footer",
|
|
SortOrder: 0,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Key: "y2k:landing-master",
|
|
Title: "Y2K Landing Master",
|
|
PageTemplates: []string{"landing", "full-width"},
|
|
Blocks: []plugin.MasterPageBlock{
|
|
{
|
|
BlockKey: "y2k:metaball_hero",
|
|
Title: "Metaball Hero",
|
|
Content: map[string]any{"headline": "new EP out now", "sub": "liquid chrome dreams", "ctaLabel": "listen"},
|
|
Slot: "hero",
|
|
SortOrder: 0,
|
|
},
|
|
{
|
|
BlockKey: "y2k:marquee",
|
|
Title: "Marquee",
|
|
Content: map[string]any{"items": []any{"* new * new * new"}, "speed": "fast"},
|
|
Slot: "marquee",
|
|
SortOrder: 0,
|
|
},
|
|
{
|
|
BlockKey: "slot",
|
|
Title: "Main Slot",
|
|
Content: map[string]any{"slotName": "main"},
|
|
Slot: "main",
|
|
SortOrder: 0,
|
|
},
|
|
{
|
|
BlockKey: "y2k:footer_chrome",
|
|
Title: "Chrome Footer",
|
|
Content: map[string]any{"showWebring": true},
|
|
Slot: "footer",
|
|
SortOrder: 0,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|