Format was a small pill row buried alongside Brand — promoted it to full-width stacked rows (label + dimensions) since it's the decision that determines everything downstream (canvas size, available templates, content rules). Layout picker moves out of the sidebar entirely into a horizontally scrollable thumbnail carousel floating above the bottom toolbar, so browsing layouts feels like flipping through visual samples instead of scanning a static sidebar grid. Still uses the existing CSS-diagram LayoutThumb visuals for now — swapping in real rendered examples is a deferred polish pass, not blocking this reorg. Sidebar now reads Brand -> Format -> Content, with Content's fields already gated on a layout being selected (showContentControls), so the flow reads as sequential steps rather than three parallel groups. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Supaimage
Internal, self-serve tool to generate on-brand social images — without opening Figma — for Supabase and its sub-brands (Multigres so far), across multiple formats:
- OG image — 1200×630, dark mode, abbreviated headline (≤2 lines). The social share preview.
- Thumb image — same canvas & illustration system, no headline text.
- Twitter / X post — 1200×675, same layout system, sized for X's link-card preview.
Both Brand and Format are explicit, code-defined dimensions (lib/design/brands/,
lib/design/formats.ts) — adding a new sub-brand or platform format doesn't
touch the render/layout logic.
Every image is 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
/— Brand + Format selectors, AI art direction, 4 templates, an icon library, background patterns, OG + Thumb output, WCAG contrast checks, and 1×/2× export. Uploadable assets are scoped per brand.
Running it locally
From the repo root (supabase/):
pnpm install # once, to register this app in the workspace
pnpm dev --filter=supaimage
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 setOLLAMA_URLin.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:
- Create a key at https://console.anthropic.com → Settings → API keys →
Create key (it starts with
sk-ant-). cp .env.local.example .env.localand paste the key afterANTHROPIC_API_KEY=.- 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:
- In
.env.localsetNEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, and (for server-side writes)SUPABASE_SECRET_KEY— from the dashboard → Project Settings → API. - Apply the schema: dashboard → SQL Editor, paste the contents of
supabase/migrations/0001_init.sql, and Run. It creates thefeatured_examples,assets, andpoststables (+ RLS), theog-assetsStorage bucket, and seeds the featured examples. - 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 futuredesign_tokensDB 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.