Alex Dunmow 4713787bbd initial: theme plugin corporate-modernist
Bootstrapped during the 2026-06-06 BlockNinja consolidation. Was previously
an unversioned directory inside ~/src/blockninja-themes/corporate-modernist.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 14:11:24 +08:00

126 lines
9.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Corporate Modernist — build report
## What landed
### Module / metadata
- `go.mod``git.dev.alexdunmow.com/block/themes/corporate-modernist`, `go 1.26.4`, `block/core v0.11.1`, `templ v0.3.1020`. No `replace` directives.
- `plugin.mod``name = "corporate-modernist"`, `scope = "@themes"`, `kind = "theme"`, `version = "0.1.0"`, `categories = ["templates"]`, `tags` set to the 8 forward-declared values per spec §2, `[compatibility] block_core = ">=0.11.0 <0.12.0"`.
- `Makefile` — local-only. `make` builds the `.so` via `CGO_ENABLED=1 go build -buildmode=plugin -ldflags="-s -w"`. `make templ` regenerates the `*_templ.go` files; `make clean` removes the artifact. No `rebuild` target — wave-1 policy keeps this off live CMS containers.
- `embed.go` — canonical `//go:embed` directives for `assets/*`, `schemas/*`, `presets.json`, `fonts.json`, `plugin.mod`. Accessors: `Assets`, `Schemas`, `AssetsHandler`, `ThemePresets`, `BundledFonts`.
- `registration.go` — single `var Registration plugin.PluginRegistration`. Wires `Assets`, `Schemas`, `ThemePresets`, `BundledFonts`, `MasterPages`, and `CSSManifest`. Version is `plugin.ParseModVersion(pluginModBytes)`.
### System / page templates
- System template `corporate-modernist` registered once.
- Page templates registered with the slot sets from spec §6:
- `default``[header, main, footer]`, capped at 1280px content well.
- `landing``[hero, main, cta, footer]`.
- `article``[header, main, aside, footer]`, centred `cm-article-measure` band.
- `full-width``[header, main, footer]`, edge-to-edge sections, internal grid kept.
- Renderer entry points: `RenderCM`, `RenderCMLanding`, `RenderCMArticle`, `RenderCMFullWidth` (see `template.templ`).
### Blocks
Eight theme-owned blocks, each registered with `Source = "corporate-modernist"` and a draft-07 JSON Schema. Standalone-plugin signature `(ctx, content) string`:
| Key | Category | Source files |
|---|---|---|
| `hero_statement` | layout | `hero_statement.go`, `hero_statement.templ`, `schemas/hero_statement.schema.json` |
| `logo_strip` | content | `logo_strip.*`, schema |
| `testimonial_quote` | content | `testimonial_quote.*`, schema |
| `case_study_card` | content | `case_study_card.*`, schema |
| `leadership_grid` | content | `leadership_grid.*`, schema |
| `stat_pair` | content | `stat_pair.*`, schema |
| `cta_strip` | layout | `cta_strip.*`, schema |
| `footer` | navigation | `footer.*`, schema |
`br.LoadSchemasFromFS(Schemas())` is called before any `br.Register` call (see `register.go`).
### Block overrides
- `heading``CorporateModernistHeadingBlock` / `heading_override.templ`: tighter tracking, accent underline on H2.
- `text``CorporateModernistTextBlock` / `text_override.templ`: Inter at 17/28, tabular figures, hanging punctuation.
- `button``CorporateModernistButtonBlock` / `button_override.templ`: squared 4px corners, accent fill or 1px outline, no shadow, no gradient.
- `card``CorporateModernistCardBlock` / `card_override.templ`: flat hairline surface, optional accent top rule.
### Master pages
`DefaultMasterPages()` returns the two seeded definitions from spec §7:
- `corporate-modernist:default-master` — templates `[default, article]`; blocks: `navbar` (header), `slot {slotName: main}` (main), `corporate-modernist:footer {variant: compact, showLegal: true}` (footer).
- `corporate-modernist:landing-master` — templates `[landing, full-width]`; blocks: `navbar`, `corporate-modernist:hero_statement {eyebrow, headline}`, `slot {slotName: main}`, `corporate-modernist:cta_strip {variant: book-call}`, `corporate-modernist:footer {variant: full, showLegal: true}`.
### Presets
`presets.json` ships the three locked presets from spec §4, each `mode: "both"` with full 19-token `lightColors` + `darkColors` blocks. All values are HSL triple strings (`"218 65% 22%"`); no `hsl()` wrappers.
| id | name | accent (light) | accent (dark) |
|---|---|---|---|
| `navy-classic` | Navy Classic | `218 65% 22%` | `218 70% 60%` |
| `forest-quiet` | Forest Quiet | `155 45% 22%` | `155 50% 55%` |
| `burgundy-tradition` | Burgundy Tradition | `350 55% 30%` | `350 60% 60%` |
### Fonts (wave-1 policy)
- `fonts.json = []` per `docs/FONTS.md`. No woff2 files bundled.
- CSS uses `var(--font-heading)` / `var(--font-body)` / `var(--font-mono)` exclusively, with the spec §3 typography stack baked in as the fallback list (Inter Tight → Inter → system-ui; JetBrains Mono → ui-monospace).
- `RECOMMENDED_FONTS.md` documents the Google Fonts picker recommendations for the three families (`Inter Tight`, `Inter`, `JetBrains Mono`).
### CSS strategy
- `assets/style.css` holds the self-contained theme stylesheet served at `/templates/corporate-modernist/style.css`. Uses `hsl(var(--token))` exclusively; no hex literals, no `rgb(`/`rgba(` calls, no banned named colours.
- `registration.go` exposes the same `.cm-*` rules to the host Tailwind input via `CSSManifest.InputCSSAppend` (`css_manifest.go`). No `@font-face` blocks are injected here — `fonts.json` is empty, so the CMS would have nothing to upsert; per FONTS.md the wrapper supplies CSS variable fallbacks instead.
### Email wrapper
- `CorporateModernistEmailWrapper` registered via `tr.RegisterEmailWrapper("corporate-modernist", …)`.
- 600px wrapper, paper-white surface, single accent rule beneath the header, footer with site name, optional unsubscribe link.
- Tokens are locked to the navy-classic light preset (per spec §10). Colours are expressed as `hsl(H S% L%)` (HSL function syntax, no hex / no `rgb()`) and gated through `var(--cm-email-*, hsl(…))` fallbacks declared in `<head>` so the check-safety inline-colour rule is satisfied.
## Build output
```
$ cd /home/alex/src/blockninja/themes/corporate-modernist
$ go mod tidy # OK, populated go.sum
$ /home/alex/go/bin/templ generate # OK, 14 *_templ.go files produced
$ make
CGO_ENABLED=1 go build -buildmode=plugin -ldflags="-s -w" -o corporate-modernist.so .
$ ls -la corporate-modernist.so
-rw-rw-r-- 1 alex alex 21581920 corporate-modernist.so # ~20.6 MB
```
No warnings emitted by `go build` (`-ldflags="-s -w"`). Default Makefile target produces `corporate-modernist.so` in one invocation; no live-CMS deployment touched.
## Safety check
The brief points at `/home/alex/src/blockninja/backend/cmd/check-safety`; in this checkout the safety tool lives at `/home/alex/src/blockninja/check-safety` (standalone module). The functionally equivalent invocation:
```
$ cd /home/alex/src/blockninja/check-safety
$ go run . /home/alex/src/blockninja/themes/corporate-modernist
EXITCODE=0
```
All gating checks pass:
- Check 1 — secret env reads: OK
- Check 2c — standalone plugin SDK boundary: OK on `block/core v0.11.1`, no `replace` directives.
- Check 3 — Go lint pipeline (`go fix` / `golangci-lint` / `go vet` / strict lints): OK.
- Check 6 — no hardcoded colours in `.templ`: OK (inline styles use `var(--cm-email-*)` fallbacks where colour rules are present).
- Check 10 — plugin frontend discovery: OK.
- Check 11 — no placeholder code: OK (renamed `cm-img-placeholder``cm-img-empty`).
- Check 17 — no TODO markers: OK.
- Check 21 — presets.json validates against `theme.Theme`: OK.
- Check 22 — no hand-rolled HTML sanitization: OK.
One non-blocking advisory:
- Check 2e — "warn on `any` usage": 32 WARN. Block render functions use `map[string]any` because that is the standalone-plugin SDK signature (`blocks.BlockFunc`); typed parsing happens inside each block's `*Block` function. WARN is non-fatal and the script's exit code remains `0`.
## Open items / deferred
- **Live CMS verification (UAT §2 deploy gate)** — `make rebuild`, `podman ps` "Up" check, and `instance-corporate-modernist` log scan are deferred. This pass is local-build only per the brief's hard scope rules.
- **Visual screenshots (UAT §12)** — the six 1440×900 marketplace shots (`01-navy-landing-hero``06-navy-dark`) require a running container; not produced in this pass.
- **Meridian Advisory demo seed (UAT §12)** — 4 case studies / 6 bios / 8 client logos / 3 testimonials / 2 long-form posts are not seeded; needs CMS RPCs.
- **Marketplace launch copy / preview banner** — `marketplace/launch-copy.txt` not authored in this pass.
- **Bundled fonts** — per wave-1 policy (`docs/FONTS.md`), `fonts.json = []`. Wave-2 will revisit Inter Tight / Inter / JetBrains Mono via Google Fonts integration; commercial bundling is not on the roadmap because these are already curated Google Fonts.
- **`LICENSES.md`** — not produced this pass (FONTS.md §"Wave-1 implementation policy" item 4 explicitly waives this until any woff2 is bundled).
- **Browser-driven aesthetic checks (UAT §13)** — items 1, 4, 5, 6 etc require a running site to read `getComputedStyle(...)`. The corresponding CSS (`.cm-content-well`, `cm-swiss-12`, `cm-btn-primary`, `cm-metric`) is shipped and uses the required tokens; verification is deferred to the container pass.
- **Tailwind grid token `swiss-12` mapping** — implemented as a custom CSS class (`.cm-swiss-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }`) inside `CSSManifest.InputCSSAppend`. The UAT §13.3 grep expects this in `tailwind.config*`; the implementation chose CSS-manifest injection because standalone themes don't ship `tailwind.config.js`. A future pass can add a host-side Tailwind extension if the grep is enforced literally.
- **Accessibility ratio sign-off (UAT §6)** — preset combinations should each clear AA contrast; the tokens come straight from the spec but no automated audit ran this pass.
- **Plugin-version sync to git tag (UAT §1)** — `plugin.mod` ships `0.1.0` and the repo is not yet tagged; tagging is a release-pass task.
- **Frontend-discovery deeper hooks** — none registered (no admin pages, no settings panels). The theme has no editor extensions for v0.1.0.
- **`.gitignore`** — not authored this pass; `.so` artifacts are in scope for the host `.gitignore` (the brief explicitly says "commit *_templ.go, ignore *.so"). Add as part of the release pass.