# Figure Design Guidelines — coded figures Design rules and conventions for **coded figures**: SVG/HTML sources rendered to PNG with `${CLAUDE_PLUGIN_ROOT}/render/build-figur.mjs`. Coded is the **primary route for data figures** (charts, diagrams, comparisons — anything whose content is real numbers or real structure): precision and reproducibility beat generative output, and the figure re-renders identically after a correction. Generative images (`mcp-image`) remain the route for **illustrative** work (cover art, mood, metaphor). Strategy-level guidance on *when* a post needs a visual at all lives in `linkedin-visual-style.md`. ## The three render targets | Target | Size | Use | |--------|------|-----| | `article` (default) | 1200 × content-driven height (aspect derived from the source's `viewBox`/dimensions; fallback 16:9) | inline figures in long-form articles | | `carousel` | 1080 × 1350 (4:5) | carousel/document-post slides | | `single` | 1200 × 1200 (1:1) | standalone feed-post image | `--width N` / `--height N` override any target. If an `article`-target source declares no dimensions, the renderer warns and falls back to 16:9 — set an explicit `viewBox` (SVG) or `--height`. ```bash node "${CLAUDE_PLUGIN_ROOT}/render/build-figur.mjs" figN.svg --target article --out figN.png ``` CLI and importable module (`renderFigure` is async). No npm dependencies; needs headless Chrome (auto-discovered: app bundle → PATH → error with install hint). No network access during render — sources must be local and self-contained. ## Design rules Enforced as **warn-only validation** by the renderer (never a hard fail); treat warnings as a review checklist, not noise: 1. **Text ≥ 24pt/px effective size.** Figures are read on a phone in the feed — smaller text is illegible at feed scale. (Same floor as the carousel rules in `linkedin-visual-style.md`.) 2. **Color budget: max 1 primary + 1 secondary beyond neutrals.** Grays, white, and black are free; every additional hue must earn its place. More colors read as noise, not information. 3. **≥ 40 % whitespace — an editorial rule, not machine-checked.** Density is the most common coded-figure failure. If the figure needs a legend to be parsed, it probably needs to be two figures. ## Brand-token convention The renderer injects design tokens as CSS variables (`--figur-*`) so figure sources stay brand-agnostic. Tokens are **user data**, read from the data root (see `data-path-convention.md`): ``` ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/brand-tokens.json ``` | Key | CSS variable | Neutral default | |-----|--------------|-----------------| | `background` | `--figur-background` | `#FFFFFF` | | `ink` | `--figur-ink` | `#1A1A1A` | | `muted` | `--figur-muted` | `#5B5B5B` | | `accent` | `--figur-accent` | `#2F6F9F` | | `rule` | `--figur-rule` | `#D9D9D9` | | `fontFamily` | `--figur-fontFamily` | `system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif` | Missing or unparsable file → neutral defaults with a warning. Partial files are merged over the defaults. The user's brand is **data, never hardcoded** — figure sources reference `var(--figur-accent)` etc. and render correctly for any user. **Authoring rule:** use the `--figur-*` variables for every color and font in a figure source. A hex value hardcoded in the source defeats the token seam and counts against the color budget.