agentleFS
CosmoBlkCosmoBlk/email-design/SKILL.md

email-design

Skill3 starsChanged 6 months agoMITView on GitHub

Design distinctive, on-brand emails — newsletters, campaigns, welcome series, promo, post-purchase, win-back, transactional, announcements. Use when the user wants to draft, write, compose, design, redesign, critique, polish, or improve an email; or send a campaign / blast / broadcast through any ESP (Nitrosend, Klaviyo, Mailchimp, ActiveCampaign, etc.). Produces a structured design brief and translates it into the sending tool's section format. Bakes in anti-slop principles: own a colour, restrained palettes, real imagery with sourced or prompted image slots, distinctive voice, no category-reflex aesthetics, no orphan whitespace, single column ≤600px, mobile-first, real footers (verified mission only, plus socials + address + unsubscribe). Asks at most three questions to fill brand gaps; otherwise infers from connected ESP account settings or a project brand file. Self-contained — no other skills required. Skip for pure strategy, deliverability, copy-only, or platform-selection questions.

6 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions6 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 6

    1. ArnavPuri/designskills★ 17same name
    2. kingadow/email-design-md★ 12same name
    3. 808enzo/chappie★ 3same name
    4. AngelescuCiprian/claude-skills★ 0same name
    5. Biznomad/claude-skills★ 0same name
    6. nikunj812/claude-skill★ 0same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

The file

Show its rules and text

We split this skill into the rules it gives an agent

24 rules. 0 are common, 11 are distinctive, and 13 are very specific to this project.

  • 0

    Common

    Most of the 4 edited versions we read keep these.

  • 11

    Distinctive

    This author's own choices. Worth a look.

  • 13

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Pick an archetype, write the brief: Commit before composing.

    line 49
  2. Very specific:

    If Nitrosend MCP tools are available (nitro_*):

    line 59
  3. Very specific:

    Read the nitro://account resource for brand fields (company name, brand colour, logo, fonts, physical address, voice document if present).

    line 61
  4. Very specific:

    Call nitro_get_status for onboarding state and any obvious gaps.

    line 62
  5. Very specific:

    Call nitro_query({ entity: "templates", limit: 3 }) to see prior design language.

    line 63
  6. Very specific:

    If the connected ESP is something else, look for the equivalent — most ESPs expose a brand or settings endpoint.

    line 65
  7. Very specific:

    If three or more fields are missing, you can ask.

    line 75
  8. Distinctive:

    If the user has already answered these earlier in the session, do not re-ask.

    line 91
  9. Very specific:

    Never pure #000 or #fff. Tint every neutral toward the brand hue.

    line 120
  10. Distinctive:

    Category-reflex check: If someone could guess the palette from the category alone — fintech → navy + gold, wellness → white + sage, AI → …

    line 122
  11. Very specific:

    No gradient text. No background-clip: text.

    line 129
  12. Distinctive:

    No restated headings. No intro paragraphs that repeat the subject.

    line 162
  13. Very specific:

    No em dashes (—) or en dashes (–) in body.

    line 163
  14. Distinctive:

    Write the brief as JSON before composing sections.

    line 169
  15. Very specific:

    Already-uploaded brand assets: If Nitrosend is connected: nitro_query({ entity: "media" }).

    line 214
  16. Distinctive:

    Prefer images ≥1200px on the long edge.

    line 219
  17. Distinctive:

    Never fabricate or AI-generate a stock-style image.

    line 223
  18. Very specific:

    If you uploaded a new image and the brand uses Nitrosend: nitro_ingest_image({ url: "...", purpose: "hero" }).

    line 225
  19. Very specific:

    Default rule per section: padding_top: 0, padding_bottom: 32.

    line 260
  20. Distinctive:

    Always run a dry-run first and always show the preview URL before the user approves a real send.

    line 276
  21. Distinctive:

    After the dry-run preview, before any real send, ask:

    line 301
  22. Very specific:

    Default the recipient to the account's from_email or the saved test recipients, but accept any address the user names.

    line 305
  23. Distinctive:

    Run this mentally before composing.

    line 322
  24. Distinctive:

    When the user wants to iterate:

    line 340

“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Email Design Skill

Distinctive, on-brand emails. Produces a structured brief, then hands it to the connected sending tool. Self-contained.

When to use

Triggered for:

  • "draft / write / compose / design / build an email" (newsletter, campaign, blast, broadcast, announcement, welcome, win-back, post-purchase, abandoned cart, promo, transactional)
  • "make this email less generic / less plain / more on brand"
  • "redesign / critique / polish this email"
  • "send a campaign through Nitrosend / Klaviyo / etc."

Skip for:

  • Strategy-only ("what frequency should I send at?")
  • Deliverability-only ("why am I in spam?")
  • Platform selection ("Klaviyo vs Mailchimp?")
  • Copywriting in isolation, no design

The flow (five steps)

  1. Context check — pull brand state from the connected ESP and project files. No questions yet.
  2. Ask up to three questions — only the highest-leverage gaps. Bundle into one message.
  3. Pick an archetype, write the brief. Commit before composing.
  4. Resolve image slots — fetch from brand site, brand assets, or prompt the user.
  5. Translate the brief into the sending tool's format and run a dry-run preview before approval.

Step 1 — Context check (silent)

Pull what is already known. Do not ask the user yet.

If Nitrosend MCP tools are available (nitro_*):

  • Read the nitro://account resource for brand fields (company name, brand colour, logo, fonts, physical address, voice document if present).
  • Call nitro_get_status for onboarding state and any obvious gaps.
  • Call nitro_query({ entity: "templates", limit: 3 }) to see prior design language. Look at the actual sections, colours, typography, and tone.

If the connected ESP is something else, look for the equivalent — most ESPs expose a brand or settings endpoint. If the ESP is unknown, fall back to project files: BRAND.md, email-brand.md, PRODUCT.md, or a top-level README.md for tone clues.

Build a brand profile in your head with these fields, marking each as known, inferable, or missing:

  • Company name, from-name, from-email, mission/tagline
  • Primary brand colour (hex), secondary if any
  • Logo URL
  • Voice descriptors (e.g. founder-personal, editorial, cheeky, technical, premium-restrained)
  • Footer essentials: physical address, social handles, unsubscribe handler

If three or more fields are missing, you can ask. Otherwise default to inferred values and note them in the brief.


Step 2 — Up to three questions (only if needed)

Hard cap: three questions, in one message, as a numbered list. If more fields are missing, fill with sensible defaults and note them in the brief — do not interrogate.

Priority order — pick the top three that are missing and matter for this specific email:

  1. Email purpose — what does this specific email need to do? (Drive a click? Tell a story? Confirm an action? Re-engage a lapsed user? Tease a launch?) Almost always worth asking on first email of a session.
  2. Tone register — editorial, bold-mono, minimal-lux, founder-letter, punk/character, or lookbook? Ask only if voice is unclear from prior templates.
  3. Primary brand colour — hex preferred. Ask only if missing AND no logo to extract from.
  4. Mission line — one sentence on why the company exists (not what it sells). Ask only if footer-critical and absent.
  5. Socials + physical address — handles + one mailing address for footer / CAN-SPAM. Ask only if footer would otherwise be incomplete.

If the user has already answered these earlier in the session, do not re-ask.


Step 3 — Pick an archetype, then write the brief

Anti-slop wins. Commit to an archetype before drafting. The most common failure mode is defaulting to "minimal-lux" because it feels safe — it is the right answer maybe 30% of the time. For the rest, pick deliberately.

Archetypes

ArchetypeWhenHallmarksReference brands
EditorialNewsletters, brand stories, long-formSerif heads, full-bleed photo, generous leading, single column, voice-richPatagonia, Tracksmith, Lucy Folk
Bold monoPromo, launches, statementsOne saturated colour drenches the surface, big punchy type, minimal copyAbsolut, Liquid Death, Fly By Jing
Minimal luxPremium, transactional, restraint as positioningTinted neutrals, narrow width 472–520px, one accent, lots of breath, never discount-ledStripe, Aesop, Apple, MoMA
Founder letterWelcome, win-back, milestones, reply-driverPlain-text feel, first-person, short paragraphs, signed off, no template chromeUgmonk, Superhuman, Tracksmith CEO
Punk / characterBrand voice carriers, retentionHeavy personality, mascot or character, irreverent copy, custom imageryFrank Body, Duolingo, Liquor Loot, Chubbies
LookbookProduct, fashion, food, paint, anything where the product is the designEditorial photo > copy, gallery layout, full-bleed heroDior, Clare Paint, Starbucks seasonal

Shared visual laws

Apply to every archetype. Implementation should match the aesthetic — bold needs committed; minimal needs precision.

Colour

  • Pick a strategy before picking colours:
    • Restrained — tinted neutrals + one accent ≤10% of the surface. Default for transactional and minimal-lux only.
    • Committed — one saturated colour carries 30–60% of the surface. Default for brand-identity emails.
    • Drenched — the surface IS the colour. For heroes and statement emails.
  • Never pure #000 or #fff. Tint every neutral toward the brand hue.
  • High chroma at extreme lightness looks garish; pull saturation back as you approach black or white.
  • Category-reflex check. If someone could guess the palette from the category alone — fintech → navy + gold, wellness → white + sage, AI → black + neon, ecommerce → millennial pink + cream — rework it. Training-data reflexes make emails forgettable.

Typography

  • One typeface family per email. Add a second only with a clear functional reason.
  • Body 14–16px. Headline 22–34px. Hierarchy ratio ≥1.25 between steps.
  • Cap line length 50–65 characters.
  • No gradient text. No background-clip: text. Emphasis through weight or size, not effects.

Layout

  • Single column. Width 472–600px. Wider feels desktopy and breaks on mobile.
  • Vary spacing for rhythm. Same padding everywhere reads as wireframe.
  • Cards are the lazy answer. Use only when truly the best affordance. Nested cards are always wrong.
  • Touch targets ≥44×44px.

Whitespace (this is where most AI-drafted emails fail)

The default LLM behaviour is to over-pad — every section gets generous top and bottom padding, plus standalone spacer rows. The result is a moonscape. Counteract:

  • No orphan spacers. Two spacer sections in a row, ever, is wrong. Collapse.
  • Asymmetric padding. Most sections: padding_top: 0, padding_bottom: 32. Let the next section's top padding (or its lack) own the rhythm.
  • Hero hugs. Hero image sits flush to header (≤8px gap), generous space below the hero, not both sides.
  • End rule. Final content section before footer: padding_bottom: 32–48px, never more. Footer has its own top padding.
  • Never: two consecutive empty paragraphs, double <br> between blocks, margin AND padding on the same side, an empty text section used as a spacer.

This applies regardless of platform whitespace-trimming passes — belt and braces.

Imagery

  • Real photography or commissioned illustration only. No stock, no AI slop, no flat geometric shapes as decoration.
  • Hero must serve a purpose: product, person, place, or moment. Decoration is not enough.
  • Each image ≤200KB; total payload ≤800KB.
  • Alt text on every image. Treat as fallback for the ~33% who block images.
  • Dark mode: transparent PNGs for logos and icons; off-white (not pure white) backgrounds.

Copy

  • Inverted pyramid. Lead with the answer.
  • Short paragraphs. Every word earns its place.
  • No restated headings. No intro paragraphs that repeat the subject.
  • No em dashes (—) or en dashes (–) in body. Use commas, colons, semicolons, periods, parentheses. No --.
  • One CTA above the fold. A second CTA at the bottom is fine. More than two is dilution.
  • Subject ≤45 chars. Preheader ≤90 chars. Both must add information; never restate the subject.

The brief (structured)

Write the brief as JSON before composing sections. This is what feeds the sending tool. Treat it as the contract.

{
  "name": "Campaign or template name",
  "subject": "subject line ≤45 chars",
  "preheader": "preheader ≤90 chars adding new info",
  "archetype": "editorial | bold-mono | minimal-lux | founder-letter | punk-character | lookbook",
  "color_strategy": "restrained | committed | drenched",
  "primary_color": "#hex",
  "secondary_color": "#hex or null",
  "voice_descriptors": ["e.g. founder-personal", "wry", "concrete"],
  "structure": [
    { "kind": "header",         "logo": true, "padding": "compact" },
    { "kind": "hero",           "image_slot": "<slot-id>" },
    { "kind": "headline",       "content": "..." },
    { "kind": "body",           "content": "..." },
    { "kind": "cta",            "label": "...", "url": "..." },
    { "kind": "secondary_body", "content": "..." },
    { "kind": "footer" }
  ],
  "image_slots": [
    {
      "slot_id": "hero",
      "purpose": "what it must convey",
      "candidate_url": "<url-from-brand-site or null>",
      "user_prompt": "<text to show user if no candidate>"
    }
  ],
  "footer": {
    "mission_line": "exact verified copy from brand fields or brand site, or null — never invent",
    "socials": [{ "name": "instagram", "url": "..." }],
    "physical_address": "one line",
    "unsubscribe": "{{unsubscribe_url}}"
  },
  "anti_slop_checks": ["no category-reflex palette", "real imagery", "distinctive voice"]
}

Step 4 — Resolve image slots

Each image_slot must end with a real candidate URL or an explicit prompt to the user. Sources, in priority order:

  1. Already-uploaded brand assets. If Nitrosend is connected: nitro_query({ entity: "media" }). Use what's there before fetching anything new.
  2. Brand site. Fetch https://<brand-domain>/ with WebFetch and look for:
    • <meta property="og:image">
    • hero image on the homepage (look for <section class="hero"> img, <header> img, [data-hero] img, banner-y filenames)
    • /press, /about, or /blog page imagery for portraits and lifestyle
    • Prefer images ≥1200px on the long edge.
  3. Brand social profiles. Instagram or X profile images for portraits and lifestyle moments.
  4. Prompt the user — once. Concrete description, options included: "For the hero I'm picturing [X]. Got an image for that, or want me to leave a placeholder so you can drop one in via the media uploader?"

Never fabricate or AI-generate a stock-style image. A clearly-marked placeholder is better than visual slop.

If you uploaded a new image and the brand uses Nitrosend: nitro_ingest_image({ url: "...", purpose: "hero" }).


Step 5 — Translate the brief and hand off

Map the brief's structure array to the sending tool's section types. For Nitrosend nitro_compose_campaign:

Brief kindNitrosend sectionNotes
headeromit if logo lives in theme.logo_url; otherwise imageLogo height 32–48px
heroimageFull-width, no side padding, set link_url only if it's clickable
headlinetext with <h1> or <h2> markupDon't add a separate spacer above; let the next section's top padding handle rhythm
bodytextShort paragraphs
ctabuttonSingle CTA, full-width on mobile
secondary_bodytextOptional
dividerdividerOnce per email max
footerfooterAuto-rendered if account footer is configured; otherwise build explicitly

Whitespace overrides on the call

Override the platform's default padding when composing. Do this even if the platform has a whitespace-trimming pass.

{
  "type": "image",
  "props": {
    "src": "...",
    "alt": "...",
    "padding_top": 0,
    "padding_bottom": 24
  }
}

Default rule per section: padding_top: 0, padding_bottom: 32. Override only with reason.

Footer — the part most AI emails get wrong

A great footer, in this order:

  1. Mission line. One sentence. Why the company exists, not what it sells. ("Made for runners. Made in Boston." beats "Premium athletic apparel since 2014.") Do not guess or invent this. Pull verbatim from one of: the connected ESP's brand fields (Nitrosend: company_description on the brand, also visible in the Brand settings), or the brand's homepage / about page (hero subhead, footer tagline, "we believe…" copy). If neither yields an exact, verified line, omit the mission line entirely — a missing mission is better than a fabricated one.
  2. Social icons. 3–5 max. Real handles, real URLs. 24–32px icons.
  3. Physical address. Required for CAN-SPAM. Single line.
  4. Unsubscribe link. Visible, not microscopic. The word "unsubscribe", not a buried "preferences" euphemism. Required for CAN-SPAM and Gmail/Yahoo bulk-sender rules.
  5. Optional: tagline, contact email, "you're getting this because…" reason.

Visual: smaller type (12–13px), tinted neutral text at 60–70% of body contrast, generous internal padding, no extra spacer above.

The handoff

Always run a dry-run first and always show the preview URL before the user approves a real send. Ask if they want a test email.

nitro_compose_campaign({
  name: brief.name,
  subject: brief.subject,
  preheader: brief.preheader,
  sections: <translated from brief.structure with explicit padding>,
  theme: {
    brand_color: brief.primary_color,
    bg_color: ...,
    text_color: ...,
    font_body: ...,
    font_heading: ...,
    logo_url: ...
  },
  audience: { audience_type: "lists", contact_list_ids: [...] },
  dry_run: true
})

Then surface the preview URL from the response. Only proceed to a real send after the user confirms.

Offer a test send

After the dry-run preview, before any real send, ask:

"Want me to send you a test email first? I can send to [from_email from account] or another address — let me know."

Default the recipient to the account's from_email or the saved test recipients, but accept any address the user names. If they say yes, send via the platform's test endpoint and surface the result.

For Nitrosend:

nitro_send_test_message({
  template_id: <id from compose response>,
  email: "<recipient>"
})

For other ESPs, use the equivalent (POST /v1/my/templates/{id}/send_test on the Nitrosend REST API; analogous endpoints elsewhere). After the test lands, ask if any final tweaks are needed before the real send.


Pre-handoff checklist

Run this mentally before composing. If three or more fail, redraft.

  • Subject ≤45 chars, adds information
  • Preheader ≤90 chars, doesn't restate subject
  • One archetype, applied consistently
  • Colour strategy committed (not "neutrals + accent" by reflex unless minimal-lux)
  • No category-reflex palette
  • At least one real image, sourced or explicitly prompted
  • Single CTA above the fold; ≤2 total
  • Footer has socials + physical address + unsubscribe (mission line only if verified — never invented)
  • No double spacers, no <br><br>, no margin+padding combos
  • No em dashes in body
  • Single column ≤600px; touch targets ≥44px
  • Voice is recognisable as the brand, not a template
  • Offered a test send to the user before any real send

Pushback patterns

When the user wants to iterate:

  • "Make it bolder" → escalate colour strategy (restrained → committed → drenched), increase type contrast, shrink line lengths, swap to bold-mono or punk-character archetype.
  • "Make it quieter" → de-escalate colour, increase whitespace selectively (not uniformly — that's the moonscape failure mode), strip secondary CTAs, swap to minimal-lux or editorial.
  • "Add personality" → swap to founder-letter or punk-character; rewrite copy first-person; add one unexpected element (handwritten asset, mascot, ridiculous subject line).
  • "Too plain" → almost always means the archetype is wrong. If you defaulted to minimal-lux, ask once whether they want bold-mono or lookbook instead.
  • "Looks like AI made it" → category-reflex palette, stock-feeling imagery, or no voice. Diagnose which one and fix only that.

Examples

Brief — SaaS welcome email (founder-letter)

{
  "name": "Welcome 1 — Founder Hello",
  "subject": "you're in",
  "preheader": "a quick note from the founder, plus what to expect this week",
  "archetype": "founder-letter",
  "color_strategy": "restrained",
  "primary_color": "#1f2933",
  "voice_descriptors": ["first-person", "concrete", "warm", "no marketing fluff"],
  "structure": [
    { "kind": "header", "logo": true, "padding": "compact" },
    { "kind": "headline", "content": "Hey, I'm [name]." },
    { "kind": "body", "content": "Three short paragraphs. What we built, why we built it, what to do this week." },
    { "kind": "cta", "label": "Reply with one thing you're trying to do", "url": "mailto:..." },
    { "kind": "footer" }
  ],
  "image_slots": [],
  "footer": {
    "mission_line": "Building [thing] so [who] can [outcome].",
    "socials": [{ "name": "linkedin", "url": "..." }],
    "physical_address": "...",
    "unsubscribe": "{{unsubscribe_url}}"
  },
  "anti_slop_checks": ["plain-text feel keeps it personal", "no stock imagery", "single CTA is a reply, not a click"]
}

Brief — D2C product launch (bold-mono, drenched)

{
  "name": "Launch — Nitro Blue Drop",
  "subject": "blue.",
  "preheader": "the new colorway. limited run. tomorrow 9am.",
  "archetype": "bold-mono",
  "color_strategy": "drenched",
  "primary_color": "#1d4ed8",
  "voice_descriptors": ["punchy", "confident", "few words"],
  "structure": [
    { "kind": "hero", "image_slot": "hero" },
    { "kind": "headline", "content": "Blue." },
    { "kind": "body", "content": "Limited to 200. 9am tomorrow." },
    { "kind": "cta", "label": "Set a reminder", "url": "..." },
    { "kind": "footer" }
  ],
  "image_slots": [
    {
      "slot_id": "hero",
      "purpose": "Single product shot on solid background. Same blue as primary_color. No text overlay.",
      "candidate_url": "https://brand.com/og-image.jpg",
      "user_prompt": "Got the product photo of the blue colorway? Drop the URL or upload via the media uploader."
    }
  ],
  "footer": {
    "mission_line": "Made for runners. Made in [city].",
    "socials": [
      { "name": "instagram", "url": "..." },
      { "name": "tiktok", "url": "..." }
    ],
    "physical_address": "...",
    "unsubscribe": "{{unsubscribe_url}}"
  },
  "anti_slop_checks": ["committed to one colour", "real product photo, not stock", "no double-padding"]
}

Brief — Editorial newsletter (Patagonia-style)

{
  "name": "Newsletter — Running gear for winter's worst",
  "subject": "running gear for winter's worst",
  "preheader": "what we wear when it's brutal out there",
  "archetype": "editorial",
  "color_strategy": "committed",
  "primary_color": "#0a3d2e",
  "voice_descriptors": ["earnest", "specific", "outdoorsy", "sells the weather, not the product"],
  "structure": [
    { "kind": "header", "logo": true, "padding": "compact" },
    { "kind": "hero", "image_slot": "winter-trail" },
    { "kind": "headline", "content": "When the weather wins, you don't." },
    { "kind": "body", "content": "Short essay — 120 words on running in horizontal sleet. No product names yet." },
    { "kind": "cta", "label": "See the kit", "url": "..." },
    { "kind": "secondary_body", "content": "Three pieces, briefly. Photo above each, not in a grid card." },
    { "kind": "footer" }
  ],
  "image_slots": [
    {
      "slot_id": "winter-trail",
      "purpose": "Editorial landscape — runner small in frame, weather doing the talking. No product close-ups in the hero.",
      "candidate_url": null,
      "user_prompt": "Have a winter trail / weather shot? Or shall I leave a placeholder?"
    }
  ],
  "footer": {
    "mission_line": "We're in business to save our home planet.",
    "socials": [{ "name": "instagram", "url": "..." }],
    "physical_address": "...",
    "unsubscribe": "{{unsubscribe_url}}"
  },
  "anti_slop_checks": ["no category-reflex green-and-brown palette", "hero sells the moment, not the product", "voice carries the email, not the design chrome"]
}

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.