OG image from template
Use this skill when a post, page or case study is about to ship and it needs a social share image, and the firm already has a Figma template for them. Produces an exported OG image at the right dimensions, named and placed for the page's meta tags, with the title set to fit rather than truncated. Also use for "make the OG image", "social card for this post", "the preview looks broken when I share the link", "og:image".
Applies when a page is ready to publish and needs its share image. Produces one exported image, correctly sized and named, from the firm's existing template rather than a new design each time.
The play
- Open the firm's OG template in Figma and duplicate the frame. Never start from a blank frame. The template exists so that every share image looks like it came from the same company, and the second a one-off is designed, that stops being true.
- Fill the template's named layers only: title, optional eyebrow or category, optional author. The layer names and what each accepts are in references/template-contract.md. Any layer not in that list is structure, not content, and is not touched.
- Fit the title rather than truncating it. Count characters before pasting, and if it overruns, rewrite it shorter. An OG title is not the page title and does not have to match it. Character budgets per size are in references/template-contract.md.
- Branch by what the page is:
- Blog post or article: title plus category eyebrow. No author unless the firm's template includes one by default.
- Case study: client name as the eyebrow, result as the title. The result is the thing worth sharing, not the client's name.
- Landing or service page: the page's promise, not its heading. Headings are written for people already on the page.
- Any page with a strong existing image: use it as the template's background layer at the template's own treatment, never raw. A raw photo behind white text fails on half of all feeds.
- Export at 1200x630 as PNG, or JPG when the image is photographic and the PNG lands over 300KB. Dimensions, naming and the file-size ceiling are in references/export-settings.md.
- Name the file after the page slug, not the title, and place it where the site expects images for that page type.
- Check the render before shipping, not after. Paste the live URL into a share-preview checker and look at the actual card. The checklist for what to look at is in references/export-settings.md.
What good looks like
- First thing I check that most people skip: the image at thumbnail size, which is how most people will see it. If the title is unreadable at 25% zoom, the design is wrong no matter how it looks in the editor.
- The mediocre version: the page's H1 pasted into the template at whatever length it happens to be, auto-shrunk to fit, exported at the wrong ratio, and never looked at again. It technically has an OG image.
- I know it is right when the card is legible at thumbnail size, the title is a sentence someone would click, and it is visibly from the same family as the last ten.
- Red flag: someone has detached the template instance to make something fit. That is a template problem to fix once, not a one-off to work around.
Rules
- MUST duplicate the template frame. Never design a one-off.
- MUST fill only the named content layers.
- MUST rewrite an overlong title rather than shrink the text or truncate it.
- MUST export at 1200x630 and keep the file under 300KB.
- MUST look at the rendered card before the page ships.
- NEVER detach a template instance to make content fit.
- NEVER put text the template did not plan for into a frame, including logos, badges and dates.
references/export-settings.md
Export, naming and the pre-ship check
Dimensions
1200x630, which is 1.91:1. One size covers every platform that matters, because they all crop from this ratio rather than demanding their own.
| Platform | What it does with 1200x630 |
|---|---|
| Shows it close to full | |
| Shows it close to full | |
| X | Full width on summary_large_image |
| Slack, iMessage, WhatsApp | Scales it down hard. This is the thumbnail case that decides legibility. |
Do not ship a square variant unless something in the stack demands one. A second size is a second thing to keep in sync.
Safe area
Keep text inside the central 80%, so 120px of margin left and right, 63px top and bottom. Crops bite the edges, and a title that ends flush to the frame loses its last word somewhere.
Format and weight
| Content | Format | Ceiling |
|---|---|---|
| Type, flat color, vector shapes | PNG | 300KB |
| Photo or screenshot background | JPG at quality 80 | 300KB |
Over 300KB, some crawlers skip the fetch and the card renders with no image at all, which is worse than a plain one. If a PNG lands over the ceiling, it is photographic and should have been a JPG.
Naming
og-<page-slug>.png. After the slug, never the title.
Titles get rewritten; slugs do not. A file named after a title becomes a lie the first time someone edits the heading, and nobody renames the file.
The pre-ship check
Four things, in order, before the page goes live:
- The tag is right.
og:imagepoints at an absolute URL, not a relative path. This is the single most common failure and it produces a blank card. - The crawler can reach it. Not behind auth, not on a staging host, not blocked in robots.
- The card renders. Paste the live URL into a share-preview tool and look at the actual card, not the file.
- It reads at thumbnail. Zoom the preview to 25%, or just look at it on a phone. If the title is not readable, nothing else matters.
When a card will not update
Platforms cache aggressively. After replacing an image, the old one keeps showing. Re-scrape through the platform's own debugger rather than shipping a second file with a different name, because the second file leaves the first one live and cached somewhere forever.
references/template-contract.md
The template contract
A template works because everyone agrees on which layers hold content and which hold structure. This is that agreement. Adapt the layer names to the firm's own template, but keep the split.
Content layers
| Layer | Accepts | Budget | Notes |
|---|---|---|---|
title | One line of plain text | 55 to 65 characters | The only required layer. Written for the feed, not the page. |
eyebrow | A category, client name or series | 24 characters | Optional. Empty is better than vague. |
author | Name, no title, no credentials | 28 characters | Only if the firm's template ships with it. |
bg-image | A photo or screenshot | n/a | Placed into the existing mask with its existing treatment. |
Everything else in the frame is structure: logo, grid, background shapes, overlays, safe-area guides. Not touched, not moved, not recolored.
Character budgets
Measured, not guessed. Count before pasting.
| Title length | Result |
|---|---|
| Under 40 | Good. Reads at thumbnail size. |
| 40 to 65 | The working range. |
| 66 to 80 | Wraps to a third line. Rewrite. |
| Over 80 | Will be shrunk or truncated by whoever is in a hurry. Rewrite. |
If the template auto-shrinks text to fit, treat that as a warning rather than a feature. Auto-shrink is how a set of cards stops looking like a set.
Writing the title
The OG title is a different job from the page title. The page title is for search and for someone already reading. The OG title is for someone scrolling past a link a colleague shared.
| Page H1 | OG title |
|---|---|
| "How We Approach Brand Strategy Engagements" | "Brand strategy, in six weeks not six months" |
| "Case Study: Northwind Logistics" | "Northwind cut quote turnaround from 5 days to 4 hours" |
| "Our Services" | "What we actually do, and what we charge" |
Three tests: it says something, it is legible at thumbnail size, and it would survive being read with no logo attached.
When the template is the problem
Keep a short list of the times the template could not hold the content. When the same gap appears three times, fix the template once. Common ones: no room for a two-line title, no variant for case studies, no treatment for screenshots as opposed to photos, no dark variant.
Fixing the template is a design task with its own review. Detaching an instance on deadline is not a fix, it is the start of a second template nobody maintains.