Skip to content

feat(marketing/assets): renderCard() + branded card templates#561

Merged
blove merged 16 commits into
mainfrom
marketing-brand-assets
Jun 8, 2026
Merged

feat(marketing/assets): renderCard() + branded card templates#561
blove merged 16 commits into
mainfrom
marketing-brand-assets

Conversation

@blove

@blove blove commented May 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Sub-spec 1 of the marketing umbrella. Replaces the @threadplane/marketing-assets skeleton with real card rendering.

  • renderCard(input) → PNG via satori (JSX→SVG) + @resvg/resvg-js (SVG→PNG). No Next.js dependency.
  • Two templates sharing one CardShell: x-card (1200×675), og-card (1200×630).
  • Brand tokens lifted from the website OG card; bundled static fonts (Garamond 700 + Inter 400/600), no runtime fetch.
  • Plane logo (brand/plane.png) rendered as an <img> data-URI (satori can't render the 🛩️ glyph).
  • Fonts + logo copied into dist/ via the Nx build assets array.
  • scripts/preview.ts writes sample PNGs for eyeballing.

Immediate consumer: the X channel adapter (embeds card.png in Draft.media). Website OG-route migration deferred per the spec.

10 tests passing. Build green; fonts + plane.png confirmed in dist.

Known visual nits (controller flagged for review)

  • Plane logo reads small/soft at 28×28 — candidate to bump to ~34px.
  • Author byline renders "Name· Role" (satori trims the leading space before the middot) — needs a non-breaking space or flex gap.

Spec: `docs/superpowers/specs/marketing/2026-05-17-brand-assets-design.md`
Plan: `docs/superpowers/plans/marketing/2026-05-17-brand-assets.md`

Test plan

  • `npx nx run marketing-assets:build` green; fonts + plane.png in dist
  • `npx nx run marketing-assets:test` green (10 tests)
  • preview script renders 4 sample PNGs
  • Brian eyeballs preview cards + decides on the two visual nits

🤖 Generated with Claude Code

blove and others added 13 commits May 28, 2026 14:12
Replaces @ngaf/marketing-assets skeleton with renderCard() built on
satori + @resvg/resvg-js (standalone, no Next dependency). Two
templates (x-card 1200x675, og-card 1200x630) sharing one CardShell
and brand tokens lifted from the website OG card. Bundled fonts, no
runtime fetch. Website OG-route migration deferred. Immediate consumer
is the X adapter (PNG bytes in Draft.media).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lyph

satori can't render the 🛩️ emoji glyph, so the card footer wordmark
uses the real Cacheplane plane logo (160×160 RGBA PNG) loaded as a
base64 data-URI via a new logo.ts module and rendered as an <img>.
Bundles marketing/assets/brand/plane.png, copied into dist via the
build assets array alongside fonts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 tasks across 6 phases: deps + JSX/vitest config, bundle fonts,
types + brand tokens, fonts loader (TDD), logo data-URI loader (TDD),
CardShell + x-card/og-card templates, renderCard() satori+resvg
pipeline (TDD), index rewrite, preview script + README, build/test
verification, PR with visual-review gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented May 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
threadplane Ready Ready Preview, Comment Jun 8, 2026 8:00pm

Request Review

- Bump footer plane logo 28→34px for crisper rendering at card scale
- Author byline uses a flex gap + leading-middot token instead of a
  leading-space text node (satori trims leading whitespace, which
  collapsed "Name · Role" to "Name· Role")

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@blove blove merged commit 71b488b into main Jun 8, 2026
19 checks passed
blove added a commit that referenced this pull request Jun 9, 2026
* docs(marketing/assets): spec for brand-assets sub-spec

Replaces @ngaf/marketing-assets skeleton with renderCard() built on
satori + @resvg/resvg-js (standalone, no Next dependency). Two
templates (x-card 1200x675, og-card 1200x630) sharing one CardShell
and brand tokens lifted from the website OG card. Bundled fonts, no
runtime fetch. Website OG-route migration deferred. Immediate consumer
is the X adapter (PNG bytes in Draft.media).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(marketing/assets): use bundled plane.png logo instead of emoji glyph

satori can't render the 🛩️ emoji glyph, so the card footer wordmark
uses the real Cacheplane plane logo (160×160 RGBA PNG) loaded as a
base64 data-URI via a new logo.ts module and rendered as an <img>.
Bundles marketing/assets/brand/plane.png, copied into dist via the
build assets array alongside fonts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(marketing/assets): plan for brand-assets sub-spec

12 tasks across 6 phases: deps + JSX/vitest config, bundle fonts,
types + brand tokens, fonts loader (TDD), logo data-URI loader (TDD),
CardShell + x-card/og-card templates, renderCard() satori+resvg
pipeline (TDD), index rewrite, preview script + README, build/test
verification, PR with visual-review gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(marketing/assets): add satori + resvg deps, JSX config, vitest target

* feat(marketing/assets): bundle Garamond + Inter static TTFs

* feat(marketing/assets): add types + brand tokens

* feat(marketing/assets): memoized font loader

* feat(marketing/assets): memoized plane logo data-URI loader

* feat(marketing/assets): CardShell layout + pill badges

* feat(marketing/assets): x-card + og-card templates + registry

* feat(marketing/assets): renderCard() satori + resvg pipeline

* feat(marketing/assets): public API surface

* docs(marketing/assets): preview script + README

* fix(marketing/assets): larger plane logo + author byline spacing

- Bump footer plane logo 28→34px for crisper rendering at card scale
- Author byline uses a flex gap + leading-middot token instead of a
  leading-space text node (satori trims leading whitespace, which
  collapsed "Name · Role" to "Name· Role")

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant