Claude
Skills
Sign in
Back

canva-creator

Included with Lifetime
$97 forever

Takes an approved content brief and executes a campaign end-to-end: builds the posting calendar, generates Canva designs for social posts, drafts caption and email copy, and stages social sends in HubSpot. Canva is used for social posts only (Instagram, Facebook, X, LinkedIn) — email content is drafted as plain text and surfaced inline for the owner to send from their own tool. Every step requires explicit owner approval. Use when the user says "make the content," "generate the posts," "create the assets," "turn this into a campaign," or hands off an approved brief for execution.

Ads & Marketing

What this skill does


# Canva Creator

## Scope

This skill handles a campaign in five sequential stages, each gated by owner
approval:

```
brief → calendar → asset inventory → Canva designs → copy → HubSpot staging
```

| Path | Channels | What this skill produces |
|------|----------|--------------------------|
| Canva (social) | Instagram, Facebook, X/Twitter, LinkedIn | Canva design + caption + scheduled HubSpot post |
| Text-only | Email (newsletter, marketing, drip) | Subject + preheader + body, surfaced inline for the owner to send |

**Canva is not used for email rows under any circumstance** — no templates,
no autofill, no design copies, no asset uploads, no exports. The owner
explicitly descoped Canva from the email path because email-template
autofill produces placeholder graphics when image slots exceed available
photos, and variation thumbnails fail to render in chat previews. If the
owner asks for a Canva email design, see `reference/gotchas.md` for the
redirect language.

---

## Pre-flight

Before Stage 1, confirm:

1. **Brief.** The user has referenced or pasted an approved brief. If not:
   "I'll need the content brief before I can build the campaign. Do you
   have one from the content-strategy skill, or would you like to write
   one now?"

2. **Canva tier.** Pro/Teams require manual template selection from the
   user's library (no autofill API). Enterprise can autofill from brand
   templates.

3. **HubSpot tier.** Social staging requires Marketing Hub Professional.
   Starter or Free → skip Stage 5 and export a CSV instead
   (see [reference/hubspot-staging.md](reference/hubspot-staging.md)).

4. **Brand assets.** Confirm the path to product photos on disk or that
   the brand kit is live in Canva.

5. **Generation budget.** Estimate the campaign's Canva volume and surface
   it before Stage 1 begins. Default is 3 candidates per Canva-bound row;
   each design costs ~5 API calls (autofill + export + polling).

   ```
   Generation budget for this campaign:
     Canva (social) rows: 8
     Candidates per row:  3   (default — say "single candidate" to use 1)
     Total designs:       24
     API calls (approx):  ~120  (autofill + export + polling)

   Canva limit: 100 requests/minute. This will take ~2-3 minutes of
   generation, well within your tier limits. Proceed?
   ```

   If the projected total designs exceeds 30, recommend single-candidate
   mode upfront — large campaigns run out of headroom fast. The owner can
   override the default to 1, 2, or 3 candidates per row before Stage 1
   starts. Lock the chosen value for the entire session.

---

## Workflow

### Stage 1 — Posting calendar

Pull from the brief: content themes, channels, cadence, hard dates
(launches, sales, holidays).

Build a calendar table with a `Path` column that routes every row to either
Canva or text-only drafting:

| Date | Channel | Path | Theme | Asset type | Caption/Subject angle |
|------|---------|------|-------|------------|-----------------------|
| Jun 2 | Instagram feed | Canva (social) | Linen launch | Square post | "finally, a dress…" |
| Jun 5 | Email | Text-only | Linen launch | Email body | "Linen that actually breathes" |

Tag every email-channel row as `Text-only` before presenting. Cap at 30
days unless the brief specifies otherwise. Flag scheduling conflicts (two
posts same day for the same product) up front.

**Checkpoint 1.** Present the calendar. Ask: "Does this match the plan?
Any dates to shift, channels to add, or themes to swap?" Iterate until
approved, then restate the split out loud — "N rows go through Canva, M
rows go through text-only drafting" — before moving on. Catching a
miscategorization here is free; catching it after generating designs
isn't.

---

### Stage 2 — Asset inventory (Canva rows only)

Email rows skip this stage entirely. For each `Canva (social)` row, build
a manifest of what the template needs and what's already available.

1. **Enumerate every image slot by name.** Square Instagram posts usually
   have 1-2 image slots; carousels and product grids can have 5+. List
   them individually (`Header_Image`, `Product1_Image`, `Product2_Image`,
   …) — never roll them up as "product images."
   - Enterprise: read field names from `dataset[].label` on the brand
     template (`GET /v1/brand-templates/{id}`).
   - Pro/Teams: count every distinct image rectangle in the template.

2. **Inventory available assets.** Text content from the brief (product
   names, offer copy, taglines, pricing), product photos already uploaded
   to Canva (`GET /v1/assets`) or on the owner's disk, brand kit colors
   and fonts (Enterprise).

3. **Build the slot-by-slot gap table.** One row per slot per design — not
   per design.

   | Date | Slot name | Slot kind | Available asset | Status |
   |------|-----------|-----------|-----------------|--------|
   | Jun 2 | Hero_Image | image | bloom_summer.jpg → asset_id pending | upload |
   | Jun 2 | Headline | text | "Summer linen, finally" | ready |
   | Jun 9 | Product1_Image | image | — | **MISSING** |

4. **Resolve slot/asset mismatches with the owner.** If the template has
   more image slots than the brief provides photos, pause and ask:

   ```
   The "Summer Carousel" template has 5 image slots. The brief gave me 1
   photo (bloom_summer.jpg). How should I fill the other 4?

     1. Reuse the same photo across all 5 slots
     2. You send me 4 more photos (file paths)
     3. Pick a simpler template with fewer slots
   ```

   No generation calls until the owner picks. Generating with empty slots
   produces designs full of Canva's default landscape placeholders.

5. **Upload missing photos and capture verified asset IDs.** Upload via
   `POST /v1/asset-uploads`, then poll `GET /v1/asset-uploads/{job_id}`
   until `status == "success"`. Record `asset.id` from the response — this
   is the only value that works in an autofill image field. Passing an
   empty string, a URL, a file path, or a stale ID silently renders
   Canva's stock landscape graphic instead of the photo.

6. **Confirm the manifest.** Show the owner the completed slot-by-slot
   table with every slot resolved and every image `asset.id` confirmed.
   This is the last stop before Canva API calls.

---

### Stage 3 — Canva design generation

Before any Canva API call, re-read the calendar and drop any row whose
`Path` is not `Canva (social)`. Email rows do not pass through this
stage.

Generate designs **one calendar row at a time**, with 3 candidates per row
(or the value chosen at pre-flight). Each row follows the same loop:
generate candidates → verify → export → visually check → retry failures
→ present → wait for owner pick → next row. Pause 30 seconds between
rows. This caps the burst at 3 generations + 3 exports per ~30s — well
under Canva's 100 req/min rate limit. Do not parallelize multiple rows;
one row at a time is the protection that keeps the owner from hitting
quota mid-campaign.

**Polling cadence.** Poll job status every 3-5 seconds, not faster.
Tighter intervals burn quota without speeding up completion.

**Preview URLs — only one type is safe to embed.** Autofill responses
return `design.canva.ai` thumbnails that expire within minutes; embedding
them as markdown images produces broken "Show Image" placeholders.
Permanent export URLs (`export-download.canva.com` or the `export-design`
MCP tool) do not expire. Native Cowork carousels render the autofill
result directly using the connector's authenticated session — let them
render on their own, don't re-embed.

#### Row loop

1. **Resolve template.** (Once per session — same template across rows
   unless the calendar mixes asset types.)
   - Enterprise: `GET /v1/brand-templates` filtered by asset type.
   - Pro/Teams: `GET /v1/designs?ownership=any&query={template name}`,
     surface top 3 to the owner, confirm one before generating.

2. **Generate the row's candidates in parallel.** Fire the row's 3
   candidates simultaneously (or N from pre-flight).
   - Enter

Related in Ads & Marketing