Compare commits
No commits in common. "9955f5f0020ede29006274cf3fdc3ac97600128c" and "dfe3bd780db3457f6f06ca7e0f0f4c19b726a710" have entirely different histories.
9955f5f002
...
dfe3bd780d
@ -1,74 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@ -4,11 +4,6 @@
|
|||||||
# codeless path (unlike the wasm/templ path). The qualified keys match the
|
# codeless path (unlike the wasm/templ path). The qualified keys match the
|
||||||
# master_pages.json references.
|
# master_pages.json references.
|
||||||
blocks:
|
blocks:
|
||||||
- key: gotham:hero
|
|
||||||
title: Hero Section
|
|
||||||
description: Large hero section with headline and optional CTA
|
|
||||||
schema: hero.schema.json
|
|
||||||
template: hero.ninjatpl
|
|
||||||
- key: gotham:stats
|
- key: gotham:stats
|
||||||
title: Stats Counter
|
title: Stats Counter
|
||||||
description: Display statistics with labels and values
|
description: Display statistics with labels and values
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
<section class="relative py-32 overflow-hidden">{% if background_url %}<div class="absolute inset-0 z-0"><img src="{{ background_url }}" alt="" class="w-full h-full object-cover opacity-20"><div class="absolute inset-0 bg-gradient-to-b from-background/80 via-background/60 to-background"></div></div>{% endif %}<div class="relative z-10 max-w-4xl mx-auto px-4 text-center"><h1 class="text-5xl md:text-6xl font-bold mb-6"><span class="gotham-accent">{{ headline }}</span></h1>{% if subheadline %}<p class="text-xl md:text-2xl text-muted-foreground mb-10 max-w-2xl mx-auto">{{ subheadline }}</p>{% endif %}{% if cta_text and cta_url %}<a href="{{ cta_url }}" class="inline-block px-8 py-4 gotham-accent-bg text-primary-foreground font-semibold rounded-lg transition-colors text-lg">{{ cta_text }}</a>{% endif %}</div></section>
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"title": "Hero Block",
|
|
||||||
"description": "Large hero section with headline and optional CTA",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"headline": {
|
|
||||||
"type": "string",
|
|
||||||
"title": "Headline",
|
|
||||||
"description": "Main headline text",
|
|
||||||
"x-editor": "text"
|
|
||||||
},
|
|
||||||
"subheadline": {
|
|
||||||
"type": "string",
|
|
||||||
"title": "Subheadline",
|
|
||||||
"description": "Supporting text below the headline",
|
|
||||||
"x-editor": "textarea"
|
|
||||||
},
|
|
||||||
"background_url": {
|
|
||||||
"type": "string",
|
|
||||||
"title": "Background Image URL",
|
|
||||||
"description": "URL for the background image",
|
|
||||||
"x-editor": "url"
|
|
||||||
},
|
|
||||||
"cta_text": {
|
|
||||||
"type": "string",
|
|
||||||
"title": "CTA Button Text",
|
|
||||||
"description": "Text for the call-to-action button",
|
|
||||||
"x-editor": "text"
|
|
||||||
},
|
|
||||||
"cta_url": {
|
|
||||||
"type": "string",
|
|
||||||
"title": "CTA Button URL",
|
|
||||||
"description": "Link for the call-to-action button",
|
|
||||||
"x-editor": "url"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["headline"]
|
|
||||||
}
|
|
||||||
@ -2,7 +2,7 @@
|
|||||||
name = "gotham"
|
name = "gotham"
|
||||||
display_name = "Gotham"
|
display_name = "Gotham"
|
||||||
scope = "@themes"
|
scope = "@themes"
|
||||||
version = "1.0.0"
|
version = "0.2.0"
|
||||||
description = "Dark, high-contrast BlockNinja theme with bold typography and modern accent panels."
|
description = "Dark, high-contrast BlockNinja theme with bold typography and modern accent panels."
|
||||||
kind = "theme"
|
kind = "theme"
|
||||||
categories = ["templates"]
|
categories = ["templates"]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user