Files
supabase/apps/og-generator
ShaneandClaude Opus 4.8 4e5ce33c59 fix(og-generator): match WCAG: label styling to Headline:, narrow preview to 65%
- Split "WCAG:" into its own font-medium text-foreground span, matching
  "Headline:" (previously the whole segment, including the label, was
  colored by pass/fail state)
- Preview row: w-full -> w-[65%], with the wrapper's horizontal centering
  made unconditional (was @4xl-only) so the narrower row stays centered in
  both stacked and side-by-side layouts. Verified via getBoundingClientRect:
  exactly 65.0% of the canvas's usable width, with equal left/right margins
  (225.4px each) at 1700px.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 20:03:10 -05:00
..

OG Image Generator

Internal, self-serve tool to generate two on-brand images for every supabase.com/blog post — without opening Figma:

  • OG image — 1200×630, dark mode, abbreviated headline (≤2 lines). The social share preview.
  • Thumb image — same canvas & illustration system, no headline text.

Both are drawn programmatically (SVG → PNG via satori/resvg, through Next's next/og) so output is pixel-exact and on-brand by construction.

Status: v1 editor. Full sidebar editor at / — AI art direction, 4 templates, an icon library, background patterns, OG + Thumb output, WCAG contrast checks, and 1×/2× export. Uploadable assets + team auth land with the Supabase backend.

Running it locally

From the repo root (supabase/):

pnpm install            # once, to register this app in the workspace
pnpm dev --filter=og-generator

Then open http://localhost:3030.

The rendered image endpoint is at:

http://localhost:3030/api/og?headline=Your%20headline%20here

AI art direction (optional)

The Describe this post → Generate panel suggests an on-brand icon, template, and background for a post.

  • With a Claude API key it reasons over the icon/template library and the featured examples (lib/ai/examples.ts) and picks the strongest composition.
  • Self-hosted (no paid API): run a local Ollama model (ollama pull llama3.1) and set OLLAMA_URL in .env.local — same reasoning, nothing leaves your infrastructure. Engine order is Claude → Ollama → keyword.
  • Neither configured: it still works — a keyword match over the icon library, so the app is never blocked.

To turn on the Claude-backed suggestions:

  1. Create a key at https://console.anthropic.com → Settings → API keys → Create key (it starts with sk-ant-).
  2. cp .env.local.example .env.local and paste the key after ANTHROPIC_API_KEY=.
  3. Restart pnpm dev. Good suggestions now show a ✨ AI suggestion label.

.env.local is git-ignored — the key stays on your machine and is only read server-side (in app/api/suggest), never shipped to the browser.

Supabase (optional backend)

The shared asset library, saved posts, and the editable featured-examples corpus live in a Supabase project (brief §3). The app runs fully without it — bundled seed data + local rendering — so this is opt-in.

To connect a project:

  1. In .env.local set NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, and (for server-side writes) SUPABASE_SECRET_KEY — from the dashboard → Project Settings → API.
  2. Apply the schema: dashboard → SQL Editor, paste the contents of supabase/migrations/0001_init.sql, and Run. It creates the featured_examples, assets, and posts tables (+ RLS), the og-assets Storage bucket, and seeds the featured examples.
  3. Restart pnpm dev. The suggester now reads featured examples from the DB, falling back to the bundled corpus if the table is empty or unreachable.

Only the URL + publishable key are needed for reads; the secret key is for server-side writes (uploads) and never reaches the browser.

Architecture notes

  • Design is data, not pixels. A "post" is a structured recipe; the PNG is a derived artifact regenerated on demand (brief §6.5). All colors/fonts resolve from lib/design/tokens.ts (the future design_tokens DB row) — never hardcoded hex.
  • Dark mode only for these images (brief §4).
  • The app chrome uses the shared Supabase design system (config + ui); the generated image uses our own independent token module.

Not built yet (later phases)

Uploadable/shared asset library, persistence, and team auth — these need the dedicated Supabase project (brief §3). The featured-examples corpus in lib/ai/examples.ts becomes the featured_examples table there, read by the same Claude-backed suggester as Design-approved precedent.