themes-gotham/PORT-NOTES.md
Alex Dunmow 9adbbb9199 feat(gotham): port hero block + PORT-NOTES; graduate to @ninja v1.0.0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 03:28:59 +08:00

5.2 KiB

Gotham — templ → codeless .bnp port notes

This theme was ported from the bundled Go/templ gotham plugin (source kept in port-source/ for reference) to a codeless .bnp (no Go, no plugin.wasm), matching the art-deco reference theme's structure. Every block, page template, override and the email wrapper is now a host-rendered .ninjatpl.

What maps 1:1 (faithful, no behavior change)

Source (templ) Codeless equivalent Notes
RenderGotham (default) templates/gotham/default.ninjatpl bn.Head/bn.BodyEnd/bn.AdminBypassBanner replaced by host-injected {{ head_html }} / {{ body_end_html }} / {{ admin_banner_html }}. <html class="dark"> hardcoded exactly as source (Gotham is always dark).
RenderGothamLanding templates/gotham/landing.ninjatpl hero/main/cta/footer slots preserved.
RenderGothamFullWidth templates/gotham/full-width.ninjatpl
RenderGothamCentered templates/gotham/centered.ninjatpl
FeaturesBlock + featuresComponent blocks/features.ninjatpl Inline icon SVG switch (chart/users/clock/star/default) ported verbatim as {% if %} chains. columns grid logic preserved.
FooterBlock + footerComponent blocks/footer.ninjatpl Column grid + link-URL logic preserved (see PageID note below).
StatsBlock + statsComponent / statsEmptyComponent blocks/stats.ninjatpl Uses the items content array (the only path StatsBlock ever took). Empty-state placeholder preserved.
GothamHeadingBlock override templates/overrides/gotham/heading.ninjatpl Per-level base classes + text-accent preserved.
GothamTextBlock override templates/overrides/gotham/text.ninjatpl prose prose-invert prose-amber preserved.
GothamEmailWrapper templates/email/gotham.ninjatpl Var names (site_name, site_url, colors.background/card/foreground/muted/mutedForeground/border/primary, preview_text, logo_url, unsubscribe_url) match the host email-context contract — identical to the art-deco reference wrapper.
assets/style.css assets/style.css Byte-identical (gotham-accent, gotham-accent-bg, gotham-card, gotham-glow, …). Host serves it as a static and links it via head_html.
DefaultMasterPages() master_pages.json gotham:default-master with navbar / slot / gotham:footer.
presets.json, fonts.json unchanged Carried over as manifest JSON refs.

Behavior gaps / decisions the parent should review

  1. hero block was NOT registered in the source. port-source/hero.go / hero.templ / schemas/hero.schema.json exist, but register.go never calls br.Register(HeroBlockMeta, ...), and HeroBlock has the CMS-internal builtin signature (ctx, content, _ []string) — it was dead code. Because the task explicitly asked for a hero port and the landing template exposes a hero slot, I ported it faithfully to blocks/hero.ninjatpl + hero.schema.json and registered it as gotham:hero. If the parent wants to match the original registered surface exactly, delete those two files and the gotham:hero entry in blocks/blocks.yaml — nothing else references it.

  2. stat_item block dropped (intentionally). port-source/stat_item.go (StatItemBlockMeta, Hidden: true) and statItemComponent were also never registered in register.go, and StatsBlock renders its items inline (never via a stat_item child block). The child-block container path (statsContainerComponent / gridCols(childCount)) was likewise unused. No codeless equivalent was created; the inline stats rendering is fully preserved.

  3. Footer internal-page links are a placeholder, same as source. The templ getLinkURL emitted /pages/<page_id> for a link with page_id set, with a source comment "In production, this would be resolved to the actual page slug." The codeless template reproduces /pages/{{ link.page_id }} verbatim — it does not resolve page_id → real slug (the codeless block declares no data providers, and the source didn't resolve it either). Behavior is identical to the original; flagging only because it was already a known limitation.

  4. No computing logic required code. All templ helper functions (gridCols, featureGridCols, footerGridCols, gothamHeadingBaseClass, parseHeadingLevel, the email gotham*Color fallbacks) are pure presentational branching and were fully expressed with {% if %} / |default: in ninjatpl. Nothing in the source needed a wasm guest, so the artifact is genuinely codeless.

Not ported (obsolete)

port-source/ also contains embed.go, registration.go, register.go, text_override.go, heading_override.go — Go glue for the bundled/.so era. None have a codeless equivalent (their concerns are now declarations in manifest.yaml / blocks.yaml / master_pages.json). Delete port-source/ once the port is verified.

Scope / version

  • version starts at 1.0.0 (graduation from bundled).
  • scope set to @ninja per the port task. NOTE: the sibling reference themes (art-deco, brutalist) use @themes, and the dev registry has both scopes. Change plugin.mod if @themes is preferred.