An approved brief is not yet a campaign: posts won't draw themselves or queue themselves up. The skill takes the brief through to finished creatives for VK, Telegram, Zen, and Odnoklassniki, writes captions and email texts, and queues up the publications — step by step, with your approval at every gate, without surprises with limits or empty placeholders.
Design service: Canva is blocked in Russia. The main path is
~~дизайн: VistaCreate (formerly Crello), Supa, Polykraft, Sberografika. Names Canva-specific commands in this file are generalized API templates~~дизайна. If the owner has access to Canva (VPN/foreign account) — the same steps apply to the Canva Connect API directly.
Scope
The skill runs a campaign through five sequential stages, each behind an owner approval gate:
бриф → календарь → инвентаризация ассетов → макеты (~~дизайн) → тексты → постановка в очередь (~~crm)
| Path | Channels | What the skill produces |
|---|---|---|
| Layout (social media) | Telegram, VK, Yandex Zen, Odnoklassniki, RuTube | Layout ~~дизайна + caption + scheduled publication in ~~crm |
| Text only | Email newsletter (news, marketing, sequence) | Subject + preheader + email body, given to the owner inline for sending |
If the client explicitly works for a foreign audience, Instagram/Facebook/X can be added to the channel list — but by default in Russia these are not the main platforms (Meta is recognized as extremist and banned in Russia). ⚠️
~~дизайн is not used for emails under any circumstances — no
templates, autofill, design copies, asset uploads, exports. The owner
explicitly removed emails from the design path because email template
autofill produces placeholder images when there are more image slots than
photos, and variant previews do not render in chat. If the owner asks for an
email layout — see
reference/gotchas.md, redirect text.
Preflight check
Before Stage 1, confirm:
-
Brief. The owner referenced an approved brief or pasted it. If not: "I need a content brief before assembling a campaign. Do you have a brief from the content-strategy skill, or shall we create one now?"
-
Plan
~~дизайна. The Free/Basic plan requires manual selection of a template from the owner's library (no API autofill). A paid/team plan (where the API is available) can autofill from branded templates. -
Access to
~~crm. Queuing posts requires a plan~~crmwith a post scheduling module (for example, CRM marketing in Bitrix24). If the module is not available → skip Stage 5 and export a CSV (see reference/hubspot-staging.md). -
Branded assets. Confirm the path to product photos on disk or that the brand kit is uploaded to
~~дизайн. -
Generation budget. Estimate the volume of campaign layouts and show it before Stage 1. By default — 3 candidates for each layout row; each layout costs ~5 API calls (autofill + export + status polling).
Бюджет генерации для этой кампании: Строк под макет (соцсети): 8 Кандидатов на строку: 3 (по умолчанию — скажите «один кандидат» для 1) Всего макетов: 24 Вызовов API (примерно): ~120 (автозаполнение + экспорт + опрос) Лимит ~~дизайна: см. тариф. Генерация займёт ~2–3 минуты, в пределах лимитов вашего тарифа. Продолжаем?If the estimated number of layouts exceeds 30, immediately recommend single- candidate mode — large campaigns quickly hit the limit. The owner can override the value to 1, 2, or 3 candidates per row before the start of Stage 1. Record the chosen value for the entire session.
Workflow
Stage 1 — Publishing calendar
Take from the brief: content topics, channels, frequency, hard dates (launches, promotions, holidays).
Build a calendar table with a column Путь, which routes each line either to ~~дизайн, or to the text set:
| Date | Channel | Path | Topic | Asset type | Signature/topic angle |
|---|---|---|---|---|---|
| 02.06 | Telegram | Layout (social media) | Linen line launch | Square post | "finally a dress..." |
| 05.06 | Text only | Linen line launch | Email body | "Linen that breathes" |
Tag each email channel line as Только текст before showing. Limit to 30 days unless the brief specifies otherwise. Flag schedule conflicts in advance (two posts on the same day about the same product).
Checkpoint 1. Show the calendar. Ask: "Does this match the plan?
Which dates should be shifted, channels added, topics changed?" Refine until
approved, then repeat the breakdown aloud — "N lines go through ~~дизайн,
M lines go through the text set" — before moving on. Catching
incorrect categorization here is free; after generating layouts, it is not.
Stage 2 — Asset inventory (layout lines only)
Email lines skip this stage entirely. For each line Макет (соцсети) assemble a manifest: what the template needs and what already exists.
-
List every image slot by name. Square posts typically have 1–2 slots; carousels and product grids — 5+. List them by name (
Header_Image,Product1_Image,Product2_Image, …), never collapse into "product photos".- With the branded templates API: read field names from the template metadata.
- Without the API (basic plan): count each separate image rectangle in the template.
-
Inventory the available assets. Texts from the brief (product names, promo texts, slogans, prices in ₽), product photos already uploaded to
~~дизайн, or on the owner's disk, brand kit colors and fonts. -
Build a gap table by slot. One line per slot per layout — not per layout.
Date Slot name Slot type Available asset Status 02.06 Hero_Image image bloom_summer.jpg → asset_id expected upload 02.06 Headline text “Flax, at last” done 09.06 Product1_Image image — MISSING -
Resolve slot/asset mismatches with the owner. If there are more image slots than photos in the brief, stop and ask:
В шаблоне «Летняя карусель» 5 слотов под изображения. Бриф дал мне 1 фото (bloom_summer.jpg). Чем заполнить остальные 4? 1. Повторить то же фото во всех 5 слотах 2. Вы пришлёте ещё 4 фото (пути к файлам) 3. Выбрать шаблон попроще с меньшим числом слотовNo generation calls until the owner chooses. Generation with empty slots produces layouts with default placeholder landscapes
~~дизайна. -
Upload the missing photos and record the confirmed asset IDs. Upload the file, wait for the status
successof the upload task. Recordasset.idfrom the response — only this value works in the image field during autofill. An empty string, URL, file path, or stale ID will silently render the default landscape image instead of the photo. -
Confirm the manifest. Show the owner the completed table by slots: every slot is resolved, every
asset.idof the image is confirmed. This is the last stop before API calls~~дизайна.
Stage 3 — Layout generation
Before any API call ~~дизайна reread the calendar and discard every row whose Путь is not Макет (соцсети). Email rows do not pass through this stage.
Generate layouts one calendar row at a time, 3 candidates per row (or the value chosen at preflight). Each row goes through one cycle: generate candidates → check → export → visually check → regenerate failures → show → wait for owner's choice → next row. 30-second pause between rows. This keeps the burst at 3 generations + 3 exports per ~30 s — with headroom under the request rate limit ~~дизайна. Do not parallelize multiple rows; one row at a time is the safeguard that keeps the owner from hitting the quota mid-campaign.
Polling frequency. Poll the task status every 3–5 seconds, no more often. More frequent polling burns quota without speeding up completion.
Preview URL — embed only one type safely. Autofill responses return temporary previews that expire within minutes; embedding them as markdown images produces broken "Show image" placeholders. Permanent export URLs do not expire. Native Cowork carousels render the autofill result directly through the connector's authenticated session — let them render themselves, do not re-embed.
Per-row cycle
-
Identify the template. (Once per session — the same template across all rows, if the calendar does not mix asset types.)
- With the branded templates API: a list of templates filtered by asset type.
- Without the API (base plan): find designs by template name, show the top 3 to the owner, confirm one before generation.
-
Generate the row's candidates in parallel. Launch the row's 3 candidates simultaneously (or N from preflight).
- With the autofill API: an autofill request for each candidate with the template ID and field values. Poll all tasks in parallel.
- Without the API: create design copies. Describe the text and image edits that the owner applies in
~~дизайне; collect the design IDs back.
-
Check the task status. For each candidate, confirm that the task returned
status == "success"and a finished design ID is present. Errors — for each design:-
JOB_FAILED→ read the error message, fix the field values or asset IDs, retry once. -
RATE_LIMIT_EXCEEDED(first time in the session) → wait 60 s, retry this one candidate once. This covers temporary spikes. -
RATE_LIMIT_EXCEEDED(second time in the session) or any errorquota_exceeded/ daily limit → stop generation immediately. Do not retry. Show progress and ask:~~дизайн ограничивает кампанию по частоте запросов. Статус: ✓ Сгенерировано: посты 1–4 (12 макетов) ⏸ Осталось: посты 5–8 (12 макетов не сгенерированы) Как продолжить? 1. Перейти на 1 кандидата на оставшуюся строку (4 макета) — закончим сейчас 2. Пауза — продолжим через 60 минут, когда квота восстановится 3. Остановить генерацию — работаем с тем, что есть, переходим к текстамWait for the owner's choice. Do not get stuck in retries.
-
-
Export each successful candidate to a permanent PNG. Run the row's exports in parallel.
- Export to format
png, poll the task until success, capture the permanent URL. - Permanent URLs are what get embedded in the preview and attached to the post in
~~crmlater. The preview from the autofill response is not used further down the pipeline.
- Export to format
-
Visually check each export. Look at the image and reject any of these — they all indicate an unfilled slot or an invalid asset:
- A generic landscape with clouds and green hills (the default placeholder)
- Solid gray rectangles where a photo should be
- Lorem ipsum or the template's default text
- The subject does not match the brief (wrong product, wrong brand)
If a candidate failed the check: recheck the manifest for the failed slot, fix
asset.id, regenerate only this candidate, re-export, recheck. -
Retry one candidate at a time on partial failure. If 1 of the N row candidates fails at Step 3 or 5, regenerate only that one — do not redo the entire row and do not show a partially broken carousel. If the second attempt also fails:
Третий кандидат для поста 09.06 продолжает сбоить — ~~дизайн вернул [ошибка / отрендерил заглушку]. Как продолжить? 1. Пропустить — показать остальные 2 и идти дальше 2. Сменить на шаблон попроще для этого кандидата 3. Попробовать ещё раз с другим фото -
Show the row candidates. Let Cowork's native carousel render the autofill result. Below it, add hint text:
Кандидаты на 09.06 готовы — пролистайте карусель выше. Какой использовать для поста 09.06?If the carousel does not render or one position is broken, embed the permanent PNG export URLs from Step 4. Final fallback: a link to the design edit URL. Never re-embed temporary preview URLs.
-
Pause 30 seconds, then the next row.
Checkpoint 2. Done when the owner has selected one layout for each calendar row. If they ask for regeneration — regenerate only that candidate.
Stage 4 — Writing Copy
For each calendar row, write the copy. Social posts get a caption; email rows get a full email.
Captions for social media — Telegram, VK, Zen, Odnoklassniki:
- Length: per channel (a Telegram post — a long-form piece is acceptable, but keep the hook at the beginning; VK ≤ ~1000 characters is recommended for the feed; short posts are OK).
- Structure: hook → one product benefit → call to action → 3–5 hashtags (not 30).
- Voice: follow the brief's tone markers. If the brief says “friendly, informal” — do not write corporate copy.
- No fluff. No “Great news!” or “We're excited to announce.” Open with value.
Emails — Claude writes the entire email; without ~~дизайна:
- Subject: ≤ 50 characters, specific, no clickbait. “Spring spots are running out” is better than “Don't miss out!”.
- Preheader: ≤ 90 characters, complements the subject, does not repeat it.
- Body: regular prose, 100–250 words. An opening line that makes them read on → 1–2 paragraphs of substance → one clear call to action → signature.
- Voice: same tone markers as in social media. Owners want emails to sound like them, not like a template newsletter.
- No references to images. Do not write "see image above." If the owner needs visuals, they will add them in their own mailing service.
- One call to action per email. Choose the main action and lead to it.
Show captions inline under each social media line. Show emails in full inline under each email line:
Тема: <тема письма>
Прехедер: <текст прехедера>
<тело письма>
Analyzed examples — reference/examples/boutique-brief-campaign.md.
Checkpoint 3. "Which captions or emails should be rewritten? Specify the date and what to change." Refine until approved.
Ad labeling: captions and creatives for paid placement (Yandex Direct, VK Ads, Telegram Ads, paid placements in third-party channels) require labeling — an ORD token and data transfer to ERIR (mandatory in Russia since 2022). Organic posts in the owner's own channels do not require labeling. Clarify the placement status with the owner. ⚠️
Stage 5 — Queuing ~~crm + email delivery
Queue social media posts via ~~crm (Bitrix24, amoCRM). Emails are not queued — they are provided to the owner inline for copying into their mailing service. For API field reference, see reference/hubspot-staging.md.
-
Create a campaign. Create a campaign in
~~crmwith the name and start/end dates from the calendar. -
Queue each social media post. One publication per line
Макет (соцсети):- channel: match the channel from the calendar to a connected account in
~~crm - publication time: future date-time — check that it has not already passed before queuing
- body: approved caption
- attachment: permanent PNG URL of the export from Stage 3
- status:
ЗАПЛАНИРОВАНО(neverОПУБЛИКОВАНО)
- channel: match the channel from the calendar to a connected account in
-
Confirm the queue. Request the list of scheduled publications, display it, give a direct link to the campaign in
~~crm. -
Output the letters for handoff. For each email row, show the approved subject + preheader + body inline, grouped by send date. The owner copies them into their mailing service (
~~почта, Unisender, Sendsay, DashaMail).
Final checkpoint.
Ваши посты для соцсетей поставлены в очередь в ~~crm: [ссылка]
Они выйдут по расписанию — любой пост можно отменить или отредактировать в ~~crm.
Письма готовы ниже — скопируйте каждое в свой сервис рассылки, когда будете
готовы отправить:
05.06 — «Места на весну заканчиваются»
15.07 — «Окна летнего обслуживания заполняются»
Что поправить, прежде чем закончим?
Approval gates
- No calls
~~дизайнаfor email rows. Recheck the columnПутьbefore every API call. - No publications. Each post in
~~crmis set asЗАПЛАНИРОВАНО; the owner controls the live exit. - Always show the generation budget at the preflight. The owner sees the total number of layouts and approves before Stage 1 starts.
- One row at a time in Stage 3. Candidates within a row run in parallel, but rows are sequential with a 30 s pause — this protects against quota exhaustion.
- On the second quota error — pause and ask. Never loop on retries.
- Always export to a permanent PNG before showing. Task success does not mean the layout rendered correctly.
- Never embed temporary preview URLs again. They expire.
- Never regenerate the entire row when a single candidate fails. Only retry by candidate.
- Never select a template automatically on the base plan. Always confirm.
- Never skip the inventory by slots. Multi-slot templates render placeholder landscapes when any slot is empty.
- Never skip Checkpoint 1. Generation before calendar approval is the largest source of wasted work in this skill.
- Ad labeling for paid placements. Do not queue paid creative without a confirmed labeling status (ORD/ERIR). ⚠️
Reference materials
- reference/canva-api.md — API
~~дизайна(VistaCreate/Supa): endpoints, asset uploads, export formats - reference/hubspot-staging.md — scheduling posts via
~~crmand a CSV fallback for plans without a scheduler - reference/gotchas.md — good/bad patterns for each failure mode the skill has encountered in practice
- reference/examples/boutique-brief-campaign.md — complete worked examples (single-slot social post, multi-slot template)