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 a 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 installs the Brutalist system template, its four page templates, // theme-specific blocks, block overrides, and the email wrapper. func Register(tr templates.TemplateRegistry, br blocks.BlockRegistry) error { tr.RegisterSystemTemplate(templates.SystemTemplateMeta{ Key: "brutalist", Title: "Brutalist", Description: "Concrete, oversized type, hard 12-col grid theme for design studios, architecture firms and art galleries.", }) if err := tr.RegisterPageTemplate("brutalist", templates.PageTemplateMeta{ Key: "default", Title: "Default", Description: "Standard masthead + 12-col body + footer", Slots: []string{"header", "main", "footer"}, }, wrap(RenderBrutalist)); err != nil { return err } if err := tr.RegisterPageTemplate("brutalist", templates.PageTemplateMeta{ Key: "landing", Title: "Index Sheet", Description: "Oversized headline + project ledger", Slots: []string{"hero", "ledger", "footer"}, }, wrap(RenderBrutalistLanding)); err != nil { return err } if err := tr.RegisterPageTemplate("brutalist", templates.PageTemplateMeta{ Key: "article", Title: "Case Study", Description: "Long-form project page with metadata strip", Slots: []string{"header", "meta", "main", "footer"}, }, wrap(RenderBrutalistArticle)); err != nil { return err } if err := tr.RegisterPageTemplate("brutalist", templates.PageTemplateMeta{ Key: "full-width", Title: "Full Bleed", Description: "Edge-to-edge gallery layout", Slots: []string{"header", "main", "footer"}, }, wrap(RenderBrutalistFullWidth)); err != nil { return err } // Load schemas BEFORE any block registration so the registry can bind // content shapes to the block keys. if err := br.LoadSchemasFromFS(Schemas()); err != nil { return err } br.Register(MastheadBlockMeta, MastheadBlock) br.Register(ProjectLedgerBlockMeta, ProjectLedgerBlock) br.Register(ConcreteHeroBlockMeta, ConcreteHeroBlock) br.Register(MetaStripBlockMeta, MetaStripBlock) br.Register(CaptionImageBlockMeta, CaptionImageBlock) br.Register(PullQuoteBlockMeta, PullQuoteBlock) br.Register(ColophonBlockMeta, ColophonBlock) br.RegisterTemplateOverride("brutalist", "heading", BrutalistHeadingBlock) br.RegisterTemplateOverride("brutalist", "text", BrutalistTextBlock) br.RegisterTemplateOverride("brutalist", "button", BrutalistButtonBlock) br.RegisterTemplateOverride("brutalist", "image", BrutalistImageBlock) tr.RegisterEmailWrapper("brutalist", BrutalistEmailWrapper) return nil } // DefaultMasterPages provisions the Brutalist default master pages on first // theme activation. Three masters cover the four page templates per // spec section 7. func DefaultMasterPages() []plugin.MasterPageDefinition { return []plugin.MasterPageDefinition{ { Key: "brutalist:default-master", Title: "Brutalist Default Master", PageTemplates: []string{"default", "article"}, Blocks: []plugin.MasterPageBlock{ { BlockKey: "navbar", Title: "Masthead Nav", Content: map[string]any{"menuName": "main"}, Slot: "header", SortOrder: 0, }, { BlockKey: "brutalist:masthead", Title: "Studio Masthead", Content: map[string]any{"studioName": "STUDIO"}, Slot: "header", SortOrder: 1, }, { BlockKey: "slot", Title: "Main Content", Content: map[string]any{"slotName": "main"}, Slot: "main", SortOrder: 0, }, { BlockKey: "brutalist:colophon", Title: "Colophon Footer", Content: map[string]any{"showAddress": true}, Slot: "footer", SortOrder: 0, }, }, }, { Key: "brutalist:index-master", Title: "Brutalist Index Master", PageTemplates: []string{"landing"}, Blocks: []plugin.MasterPageBlock{ { BlockKey: "brutalist:masthead", Title: "Studio Masthead", Content: map[string]any{"studioName": "STUDIO"}, Slot: "hero", SortOrder: 0, }, { BlockKey: "slot", Title: "Ledger Slot", Content: map[string]any{"slotName": "ledger"}, Slot: "ledger", SortOrder: 0, }, { BlockKey: "brutalist:colophon", Title: "Colophon Footer", Content: map[string]any{"showAddress": true}, Slot: "footer", SortOrder: 0, }, }, }, { Key: "brutalist:fullbleed-master", Title: "Brutalist Full Bleed Master", PageTemplates: []string{"full-width"}, Blocks: []plugin.MasterPageBlock{ { BlockKey: "navbar", Title: "Masthead Nav", Content: map[string]any{"menuName": "main"}, Slot: "header", SortOrder: 0, }, { BlockKey: "slot", Title: "Full Bleed Slot", Content: map[string]any{"slotName": "main"}, Slot: "main", SortOrder: 0, }, { BlockKey: "brutalist:colophon", Title: "Colophon Footer", Content: map[string]any{"showAddress": false}, Slot: "footer", SortOrder: 0, }, }, }, } }