# Use Claude Design to create an on-brand ad factory: runbook for agents

Give this file to your agent (Claude Code, Cursor, or anything that can read a
URL). It is the executable version of https://adside.ai/blog/create-ad-designs-claude-design:
the steps in order, the prompts verbatim, the platform specs as data, and a
checklist that says when you are done.

**Division of labor.** Sections 4, 5, 6 and 7.1 are clicks inside the Claude
Design UI (upload files, toggle Published, pick a design system, pin comments,
export). The agent writes the prompts and runs the checks; the human does the
clicks. The agent takes over at 7.2, when the project is imported through the
Claude Design MCP, and can then run every check in section 8 against files.

Source: https://adside.ai/blog/create-ad-designs-claude-design
Last updated: 2026-09-03

---

## 0. Outcome (definition of done)

One Claude Design project that contains:

1. A **design system** built from the brand's real files (fonts, logos, colors,
   textures, photos) plus written voice rules.
2. A **gallery page** that renders every ad concept in every required format
   from two authored layouts (Story 9:16 and Square 1:1) and shared
   primitives, with:
   - a Meta ad copy block per concept (primary text, headline, description,
     CTA) with live character counters, editable and persisted,
   - a safe-zone overlay per row (off / feed / reels) drawn from one registry,
   - a download button on every preview, a per-ad zip, and a header
     "By ratio" dropdown that exports one ratio for every ad as a single zip.
3. A review pass done with **comments on zones** and **global rules in chat**,
   so one instruction changes every ad.
4. An **export**: PNGs for upload today, and the project imported into Claude
   Code if the set will be regenerated or pushed to ad platforms by an agent.

If any of the four is missing, the job is not finished.

---

## 1. Inputs to collect from the human before starting

Ask for these once, up front. Do not generate an ad until you have them.

| Input | Format | Why it matters |
|---|---|---|
| Logo, every variant | SVG preferred (black, white, brand color), plus PNG mark and app icon | The model can only place a logo it has. Lookalike logos are not acceptable. |
| Fonts, the actual files | .otf / .ttf / .woff2, every weight in use | Type is what makes a set look like the brand instead of like "an AI ad". A named font without the file falls back to a substitute. |
| Colors | Hex values with a role for each (primary, ink, accent, backgrounds) | Prevents invented shades. |
| Decorative assets | Textures, scribbles, shapes, stickers as PNG with transparency | These carry the brand's visual idiom across formats. |
| Photos | Product shots, founder or team photos, screenshots, at the largest size available | Claude Design lays out; it does not photograph your product. Bring the photos. |
| Proof assets | Partner or platform logos, review badges (G2, Capterra), press marks | Proof elements appear in most performance ads. |
| Voice rules | A short list: words to use, words never to use, punctuation rules, claim rules | Written rules become global constraints on every headline. |
| Angles | 3 to 6 one-line concepts (the problem, the proof, the offer, the comparison…) | Each angle becomes one ad concept rendered in every format. |
| Target formats | The list from section 3, trimmed to the placements actually bought | Rendering formats nobody buys wastes review time. |
| Landing URL and CTA | The destination and the CTA button the media buyer will use | The copy block should default to the real CTA. |

---

## 2. Tooling

- **Claude Design (UI):** https://claude.ai/design, also in Claude Desktop.
  Included in Pro, Max, Team and Enterprise (off by default for Enterprise
  until an admin enables it). Projects hold files rendered live on a canvas;
  a chat sidebar with a design-system selector; Comment, Edit and Present
  modes; Share links scoped to your organization.
- **Export menu:** Download as .zip, Export as PDF, Export as PPTX, Export as
  standalone HTML, Send to Canva, Handoff to Claude Code. **There is no PNG
  export.** Ad creatives need per-format PNG files, so the gallery page must
  render its own download buttons (section 5). Do not plan on screenshots.
- **Claude Design MCP (for agents):** endpoint `https://api.anthropic.com/v1/design/mcp`.
  In Claude Code:
  `claude mcp add --scope user --transport http claude-design https://api.anthropic.com/v1/design/mcp`
  then `/design-login`. This lets an agent read a project's files and write
  files back. `/design-sync` pushes a local component library up as a design
  system.
- **Ad platforms from an agent:** Meta's own MCP (`https://mcp.facebook.com/ads`,
  OAuth through the claude.ai connector) can upload images and create ads; an
  authorized ad account, an ad set and a human approving the launch are still
  required. Works with Claude Code, Cursor, ChatGPT or any MCP-compatible assistant.
- **Naming of the server:** `claude mcp add` registers it as `claude-design`;
  the import prompt Claude Design generates calls it `claude_design`. Same server.

## 3. Specs (data)

### 3.1 Formats to render

Nine formats, resolved from an aspect name. Author only `story` and `square`;
every other format re-hosts the `square` layout (see section 5). Drop rows for
placements the media plan does not buy.

| Aspect | Canvas (px) | Placement | Reserved bottom band |
|---|---|---|---|
| `story` 9:16 | 1080 × 1920 | Facebook and Instagram Stories, Reels, Audience Network, Shorts | 20% |
| `square` 1:1 | 1080 × 1080 | Instagram Feed images, Marketplace, right column, carousel, LinkedIn, X | 20% |
| `portrait` 4:5 | 1080 × 1350 | Facebook Feed and Instagram Feed (Meta's recommended single-image Feed ratio), LinkedIn vertical (mobile only) | 20% |
| `landscape` 4:3 | 1440 × 1080 | Reddit desktop. Accepted in Meta Feed, recommended nowhere on Meta | 20% |
| `wide` 16:9 | 1920 × 1080 | Facebook in-stream, YouTube, LinkedIn desktop | 20% |
| `twitter` | 1600 × 900 | X image ad | 15% |
| `link` 1.91:1 | 1910 × 1000 | LinkedIn landscape (1200 × 628), Google Display, link previews. Accepted on Meta Feed, not recommended | 0 |
| `banner` | 2144 × 256 | Reddit community banner (1072 × 128 at 2×) | 0 |
| `cover` | 1640 × 720 | Facebook Page cover (820 × 360 at 2×) | 0 |

Meta's recommended resolutions are higher (1440 × 2560 for 9:16, 1440 × 1800
for 4:5); 1080-wide is accepted. Capture at `pixelRatio: 2` if the larger files
are wanted, and cap vertical exports for TikTok at 2340 × 1242.

File type: PNG or JPG, under 30 MB for Meta, under 5 MB for LinkedIn and X.

### 3.2 Safe zones

Meta publishes exact numbers only for 9:16. The others are house rules;
label them as such in the overlay. Overlay modes: `off`, `feed`, `reels`.

| Aspect · mode | Canvas | Top | Bottom | Sides | Status |
|---|---|---|---|---|---|
| 9:16 · reels | 1080 × 1920 | 270 px (14%) | 670 px (35%) | 65 px (6%) | Meta official. Same numbers apply to Stories now. |
| 9:16 · reels, with a disclaimer | 1080 × 1920 | 270 px | 768 px (40%) | 65 px | Meta official. |
| 9:16 · feed (Stories only) | 1080 × 1920 | 270 px | 380 px (20%) | 65 px | Meta's older Stories figure. Use `reels` unless the asset never runs in Reels. |
| 1:1 · feed | 1080 × 1080 | 100 px | 100 px | 100 px | House rule. Meta says "keep the bottom and side edges free" without numbers. |
| 4:5 · feed | 1080 × 1350 | 120 px | 120 px | 100 px | House rule. |
| other feed formats | as above | apply the 4:5 fractions | | | House rule. LinkedIn and X overlay no UI on feed images. |

Machine-readable, fractions of the canvas:

```json
{
  "story-reels":      { "top": 0.1406, "bottom": 0.349, "left": 0.06, "right": 0.06, "source": "meta-official" },
  "story-disclaimer": { "top": 0.1406, "bottom": 0.40,  "left": 0.06, "right": 0.06, "source": "meta-official" },
  "story-stories":    { "top": 0.1406, "bottom": 0.198, "left": 0.06, "right": 0.06, "source": "meta-legacy-stories" },
  "square":           { "top": 0.0926, "bottom": 0.0926, "left": 0.0926, "right": 0.0926, "source": "house-rule" },
  "portrait":         { "top": 0.0889, "bottom": 0.0889, "left": 0.0926, "right": 0.0926, "source": "house-rule" }
}
```

Two different protections, keep them apart:

- **Safe zone**: where the platform's UI sits on top of the image (caption,
  handle, engagement column). Above.
- **Reserved band** (section 3.1, last column): the space Feed placements use
  under the image for the headline and CTA. Render the ad at its authored
  height and scale it uniformly into the unreserved area, so a bleed is
  geometrically impossible. Point the CTA arrow down inside a reserved canvas.

Implementation rule: one registry file feeds the layout primitives, the
overlay and the export list. Copy that is positioned by the primitives is then
inside the safe zone by construction.

**Type floor:** nothing below 60 px on a 1080-wide canvas. If copy does not
fit at 60, cut the copy or drop the element; never shrink it. Exemptions that
must be stated, not silent: CTA button labels, sticker pills, logo lockups,
in-product mockup chrome.

### 3.3 Meta ad copy limits (recommended lengths, not hard maximums)

| Field | Recommended | Where it truncates |
|---|---|---|
| Primary text | 125 characters | Mobile Feed collapses behind "See more" after roughly 125 characters; Reels shows about 44. |
| Headline | 40 characters (soft limit 27) | Facebook Feed shows about 27 before cutting, so warn at 27 and turn red at 40. |
| Description | 25 characters (Meta's Marketplace spec says 30; our counter uses 30) | Often hidden entirely on mobile placements. |
| Display URL | 25 characters shown before truncation (Meta help 152143699744690) | |

Counters in the copy block: show `used/recommended`, turn red past the
recommended value, never block typing.

CTA dropdown from Meta's button inventory (Learn More, Sign Up, Book Now,
Shop Now, Get Quote, Contact Us, Download, Subscribe, Apply Now, Get Offer).
Keep the set actually used across one ad set to one to three buttons, not a
different verb per ad. Availability depends on the campaign objective.

### 3.4 LinkedIn and X text limits (if those formats are in the set)

- LinkedIn single image (help center a426534, mid-2026): intro text 150
  characters to avoid truncation (3,000 max), headline 70 (200 max),
  description 100 (300 max, only used on Audience Network). Vertical images
  serve on mobile only. Image under 5 MB.
- X: post copy 280 characters, each link costs 23. Website card headline 70
  max, keep to about 50. Image under 5 MB, PNG or JPEG.

---

## 4. Step 1: build the design system

1. At https://claude.ai/design, create a **design system**. The setup screen
   asks for a company name and blurb, then optional inputs: a GitHub repo, a
   folder of code, design files, screenshots, brand assets. Fill in the blurb,
   attach every file from section 1 (fonts and logos first), click Continue to
   generation. Anthropic's walkthrough:
   https://support.claude.com/en/articles/14604397-set-up-your-design-system-in-claude-design
   If the preview shows "Missing brand fonts", use the Upload fonts action
   (.woff2 is the safest format; .otf and .ttf work as assets). If the notice
   persists, convert to .woff2 and re-upload.
2. Paste this brief, filled in, as the first message:

```
Build our design system from the uploaded files.

Brand: {brand name}, {one-line description of what it does and for whom}.
Fonts: {display font} for headlines, {text font} for everything else. Use the uploaded font files, never a substitute.
Colors: {hex, role} … Backgrounds are {white / brand color}. Never invent new shades.
Logo rules: {which variant on which background}, minimum size {n}px, clear space {n}px.
Corner radius: {n}px maximum. Shadows: {none / minimal}.
Decorative assets: use the uploaded {textures / scribbles / stickers} for emphasis, never generic icons or clip art.

Voice:
- Full sentences, contractions, plain words.
- Never use em dashes. Use a colon, a period or parentheses instead.
- Never use these words: {leverage, streamline, empower, unlock, …}.
- Say "{preferred phrase}" instead of "{phrase to avoid}".
- No invented numbers, ROAS figures or testimonials. Only claims from this brief: {list of approved claims}.
- CTA vocabulary: {"Learn more", "Book a call", …}.

Produce: color tokens, type scale, logo usage, button and pill components, a sticker/label component, and a one-page "voice" reference. Keep everything in one CSS/tokens file so the ad gallery can import it.
```

3. Review the generated system (colors, typography, components, layout
   patterns). Fix in chat, or later with **Remix**, before moving on.
4. **One brand:** switch the **Published** toggle on. New projects created
   from the home screen while in this organization inherit it.
   **Several brands (agency):** leave every system unpublished and pick it
   explicitly from the design-system dropdown when creating each project, so
   one client's assets can never leak into another's. Name projects
   `{client}-{campaign}-{yyyymmdd}`.

Acceptance: a token/CSS file exists in the project; the rendered specimen uses
the uploaded fonts; the voice page reproduces every rule from the brief.

## 5. Step 2: ask for the gallery, not for an ad

Start a new project with the design system selected in the chat sidebar. Send
this prompt, filled in, as one message. Then paste the same text into the
project's `CLAUDE.md` so every ad added later follows it.

```
Build an ad gallery page for {brand} using the {brand} design system.

Files: one thin HTML shell that imports small files. Never one big file.
  ad-primitives.jsx   Canvas, Display, CTA, logo lockup, proof row, sticker, texture. All shared primitives.
  ads-a.jsx / ads-b.jsx / ads-c.jsx   the ad objects, ~8 per file
  ad-copy.jsx         AD_COPY, platform copy fields keyed by ad id
  gallery.jsx         rows, previews, capture, zip, safe-zone overlays
  gallery.css         page chrome
Export every shared component with Object.assign(window, {...}) at the end of its file.

The ad object: { id, title, note (one sentence: angle and why it exists), Story: () => <Canvas aspect="story">…</Canvas>, Square: () => <Canvas aspect="square">…</Canvas> }.
Author only TWO layouts per ad: Story (9:16) and Square (1:1). Every other ratio re-hosts the Square layout through an aspect-override context. Never hand-author a third layout.

Concepts: {n}, one per angle:
{angle 1, one line}
{angle 2, one line}
{…}

Formats: nine per ad, resolved by Canvas from the aspect name:
  story 1080×1920 · square 1080×1080 · portrait 1080×1350 · landscape 1440×1080 · wide 1920×1080 · twitter 1600×900 · link 1910×1000 · banner 2144×256 · cover 1640×720

Reserved bands: RESERVE = { story: .2, square: .2, portrait: .2, landscape: .2, wide: .2, twitter: .15, link: 0, banner: 0, cover: 0 }. Render the ad at its authored height in an oversized box and scale it uniformly into the unreserved area: scale = (h * (1 - reserve)) / authoredH. Hoist background layers out of the scaled box so the reserved band is still painted. Turn the CTA arrow downward inside a reserved canvas.

Type floor: nothing below 60px on a 1080-wide canvas. If copy doesn't fit at 60, cut the copy or drop the element; never shrink it. State any exemption (CTA labels, sticker pills, logo lockups, mockup chrome) instead of leaving it silent.

Safe zones: a per-row toggle (off / feed / reels) drawing translucent red bands from one registry:
  9:16: top 270, bottom 670 (reels) or 380 (stories), sides 65 · 1:1: 100 all sides · 4:5: 100 sides, 120 top and bottom.
Layout primitives and the overlay read the same registry.

Copy: a collapsible "Meta ad copy" block per row with Primary text, Headline, Description, an optional Disclaimer, and a CTA dropdown from a fixed set ({"Learn More", "Sign Up", "Book Now"}). Counters at 125 / 40 / 30 (headline warns at 27) that turn red past the limit but never block typing. When Disclaimer is non-empty, render it as a shared primitive inside the safe area and switch the 9:16 bottom band to 40%. Fields editable in place and persisted to localStorage; "Copy all" and "Reset to default" buttons.

Downloads: a hover-reveal download button on every preview; "Download all (zip)" per ad; in the page header BOTH "Download all (N) as zip" and a "By ratio ▾" dropdown that exports one ratio for every ad as a single zip ({brand}-1x1.zip). One downloadFormats(formats, zipName, label) function driven by the FORMATS array. Always one zip, never a burst of files. Store-only zip (PNG is already compressed). Render with html-to-image at pixelRatio 1 (2 for Meta's recommended resolutions). Filenames: {brand}_{id}_{variant}_{suffix}_v{n}.png with suffixes 9x16, 1x1, 4x5, 4x3, 16x9, twitter-1600x900, link-1.91x1, reddit-1072x128, fb-cover-820x360; {variant} is a letter for headline variants of the same visual, v{n} increments on every approved round.

Advanced preview: a modal that renders each ad's Square and Story inside phone-shell mockups of Instagram Feed, Facebook Feed, Instagram Stories, Facebook Stories, Instagram Reels, Facebook Reels, Marketplace, Messenger Stories and Audience Network.

User slots: {k} drop zones per ratio for hand-made assets, persisted in IndexedDB, each with its own download button.

Copy rules: follow the voice page in the design system. Never use em dashes. Only approved claims. Headlines 3 to 7 words, one idea each.

Page layout: header with brand name, today's date, the two bulk-download controls. Then one row per ad: id + title, the nine previews, the note, the copy block, a feedback box (thumbs up/down + comment, persisted to localStorage).
```

What to check on the first render, in this order:

1. Fonts and colors are the brand's (open one 9:16 at 100%).
2. With the toggle on `reels`, nothing sits in a red band on any 9:16; with
   `feed`, nothing sits in a band on any square or portrait.
3. No CTA or headline sits inside the reserved bottom band on any feed format.
4. No text below 60 px at 1080 wide except stated exemptions.
5. Counters read correctly and the CTA defaults to the real CTA.
6. The 9:16 PNG download is 1080 × 1920 and matches the artboard; the
   "By ratio" zip for 1:1 contains one file per ad with the right suffix.

Do not review copy quality yet. Structure first.

**When a check fails:**

- Substitute font in the render: the design system is missing the file or the
  gallery's tokens CSS lacks the `@font-face`. Re-upload as .woff2 and ask for
  the `@font-face` rule to be inlined in `colors_and_type.css`.
- PNG downloads blank, wrong font, or 2× the expected size: html-to-image is
  not embedding the fonts or images. Ask for fonts as data URIs in the capture
  and for `pixelRatio` to be set explicitly; re-test one 9:16.
- Gallery times out or the tab crashes with 20+ rows: ask for lazy rendering
  of previews (render a row when it scrolls into view) and render the bulk zip
  in batches of 10 files.
- Zip button does nothing: check the browser console for a blocked image
  (CORS) in a texture or photo; move the asset into the project `assets/`.
- Comments sent but not acted on: the chat should acknowledge the count of
  notes; if it does not, paste the notes into the chat.

## 6. Step 3: review with comments, fix with rules

Two mechanisms, used for two different things:

- **Comment on a zone** (Comment mode, click the element, pin the note, tick
  "Select for Send to Claude" and send the batch) for anything local: "logo too small here", "this photo crops badly at
  9:16", "swap this sticker for the coil texture". Local fixes go in comments
  so they stay attached to the artboard.
- **Rules in chat** for anything that should apply everywhere. Because the copy
  lives in one file and the ads share primitives, one message updates every
  concept in every format. Examples of the form to use:

```
Never use em dashes anywhere. Replace the ones you used with a colon or a period.
```
```
Don't say "we can do it for you". Say "we run it for you". Apply everywhere.
```
```
Every headline must fit on two lines at 9:16. Shorten the ones that wrap to three.
```
```
Move the logo lockup into the top safe band on every 9:16, never in the bottom 35%.
```

Cadence (house rule): three internal rounds before anyone outside the team
sees it. Round one is structure and safe zones, round two is copy, round three
is polish (alignment, sticker placement, photo crops). Then stop; a new concept
is a better use of a fourth round. To kill a concept: "Replace concept {n} with
a new angle: {one line}" regenerates that one ad object.

**Client review.** Share links are scoped to your Claude organization, so a
client outside it cannot comment on the canvas. Send the PDF export or the
by-ratio zip plus the copy block text, get sign-off on that exact file, and
freeze it by bumping `v{n}` in the filenames. Approved copy is never touched
by a later polish round; a change after approval is a new version.

Do not accept: invented statistics, testimonials that were not supplied,
platform logos the brand has no relationship with, text inside the unsafe
bands, a substitute font.

---

## 7. Step 4: export

### 7.1 PNGs for today's upload

Use the per-format buttons or the zip. Check the delivered file, not the
artboard: open the 9:16 PNG, confirm 1080 × 1920 (1440 × 2560 if captured at
pixelRatio 2), confirm the headline font matches the artboard and textures
rendered, confirm no text in the bottom 670 px. Upload to Ads Manager (or a
bulk-launch tool) with the copy from the copy block.

### 7.2 The project into Claude Code

In Claude Design, Export → Handoff to Claude Code → Send to local coding agent.
It gives you an import prompt. In Claude Code (with the MCP added and
`/design-login` done), paste it. Its shape is:

```
Use the claude_design MCP (https://api.anthropic.com/v1/design/mcp, auth via /design-login) to import this project:
https://claude.ai/design/p/{project-id}?file={Gallery}.html

Focus on these files (the whole project is readable):
• {Gallery}.html
• assets/… (fonts, logos, textures, photos)

Also read these files the selection imports:
• ad-copy.jsx  • ad-primitives.jsx  • ads-*.jsx  • placements.jsx  • gallery.jsx  • colors_and_type.css  • gallery.css

Implement: the selected files
```

Once local, the agent can: regenerate the set for a new client by swapping
the tokens file and copy file; render PNGs headlessly for every format; push
creatives to Meta through Meta's MCP. **After the import, the repo is the
source of truth**: later changes go into the code and the Claude Design
project is archived, otherwise the two fork.

The same 9:16 safe-zone fractions (0.14 / 0.35 / 0.06) drive our video ads;
the video registry is in https://adside.ai/blog/remotion-video-ads.md section
6. The feed house rules differ between the two (100 px margins in this gallery,
6% / 10% / 5% in the video registry); pick one for your shop and keep it in
one file.

Reference implementation: the Adside gallery at
https://claude.ai/design/p/5ffe496d-8124-4d65-b0d9-1ce7be20390b?file=Adside+Ads.html
(requires access to the Adside organization; if you get a login wall, skip it
and use the file layout below as the target structure, do not guess contents).
Its file layout: `Adside Ads.html` (shell), `gallery.jsx` (rows, FORMATS registry,
safe-zone overlay, capture and zip), `placements.jsx` (the nine placement
mockups behind Advanced preview), `ad-copy.jsx` (all copy in one place, plus
the CTA set), `ad-primitives.jsx` (shared components), `ads-a.jsx` /
`ads-b.jsx` / `ads-c.jsx` / `ads-banners.jsx` / `ads-videos.jsx` (22 static
and 2 animated concepts), `colors_and_type.css`, `gallery.css`, `CLAUDE.md`
(the standing gallery spec), and `assets/` with fonts, logos, textures and photos.

---

## 8. Acceptance checklist

- [ ] Design system uses the uploaded font files (inspect: in the exported standalone HTML the `@font-face` src names the uploaded file, or DevTools computed font-family on the specimen headline matches it).
- [ ] Every concept has exactly two authored layouts (Story, Square) and renders in every required format through the aspect override.
- [ ] Safe-zone toggle exists; with it on, no text or logo touches a red band on any artboard.
- [ ] 9:16 reels bands are 270 / 670 / 65 px on 1080 × 1920 (14% / 35% / 6%); no CTA inside a reserved bottom band on feed formats; no text under 60 px at 1080 wide.
- [ ] Copy block present per concept with counters at 125 / 40 / 30, a CTA dropdown from a fixed set, persistence and Reset to default.
- [ ] No em dashes, no unapproved claims, no invented numbers anywhere in the copy file.
- [ ] Per-preview PNG downloads produce files at canvas resolution with the agreed suffixes; the per-ad zip and the header "By ratio" zips each arrive as ONE file.
- [ ] One global rule sent in chat changed every concept (test it with a harmless rule, then revert).
- [ ] Project imported into Claude Code if the set will be regenerated or pushed by an agent, and the Claude Design project archived.
- [ ] Client-facing artifact (PDF or by-ratio zip + copy) versioned; approved copy unchanged after sign-off.

---

## 9. Sources

- Meta, text overlays and the safe zone for Stories and Reels (14% / 35% / 6%; 40% with disclaimers): https://www.facebook.com/business/help/980593475366490
- Meta, Instagram Reels image ad specs (1440 × 2560, safe-zone wording): https://www.facebook.com/business/ads-guide/update/image/instagram-reels
- Meta, Facebook Feed image ad specs (4:5, 1440 × 1800): https://www.facebook.com/business/ads-guide/update/image/facebook-feed
- Meta, aspect ratios supported by placement: https://www.facebook.com/business/help/682655495435254
- Meta, creative best practices for text (125 / 40 / 25): https://www.facebook.com/business/help/223409425500940
- Meta, available call-to-action buttons: https://www.facebook.com/business/help/410873986524407
- Meta, image best practices (no text-amount limit): https://www.facebook.com/business/help/388369961318508
- LinkedIn, single image ad specifications: https://www.linkedin.com/help/lms/answer/a426534/single-image-ads-advertising-specifications?lang=en
- X, creative ad specifications: https://business.x.com/en/help/campaign-setup/creative-ad-specifications
