From templatical-email
Generates and validates Templatical email templates as JSON (content blocks + settings) that load into the Templatical drag-and-drop editor. Supports build mode (offline JSON generation) and live mode (browser preview with real-time updates).
How this skill is triggered — by the user, by Claude, or both
Slash command
/templatical-email:templatical-emailThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate and validate email templates for the [Templatical](https://templatical.com)
README.mdevals/README.mdevals/evals.jsonlive/index.htmlpackage.jsonreference/block-guide.mdreference/examples/event-invite.jsonreference/examples/newsletter.jsonreference/examples/product-sale.jsonreference/examples/receipt.jsonreference/examples/welcome.jsonreference/schema.jsonscripts/generate-schema.mjsscripts/import.mjsscripts/live-server.mjsscripts/sync-editor-version.mjsscripts/validate.mjstests/block-type-coverage.test.tstests/cdn-pin.test.tstests/import.test.tsGenerate and validate email templates for the Templatical editor. A template is a single JSON document — an array of content blocks plus global settings — that loads straight into the editor for a human to refine.
The workflow is simple: read the brief, emit valid template JSON, validate it with the bundled script, then hand it back. No API key or server is involved — the agent running this skill is the inference.
This skill has two modes, one install:
ajv. This is everything below up to "Live mode".Within a session both modes operate on one working template file in the
user's .templatical/ folder — so building in JSON and then saying "show it
live" picks up the current template seamlessly. Each template gets its own
uniquely named file and each new session starts a new template by default —
see Working files.
Communicate about the email, not the machinery. The mechanical steps — reading
the references, picking an example, validating, generating file names, managing
.templatical/ — are for you, not the user; do them silently.
ajv), file paths, example filenames, or "reading the
schema / validating" — keep those out of user-facing messages.From this skill's folder, install the validator's dependencies:
npm install ajv @templatical/quality
ajv is required (structural validation). @templatical/quality is
optional but highly recommended — it layers accessibility / structure / link
linting on top, catching issues structural validation alone can't. If you skip
it, validation still works; the quality layer just doesn't run.
If the validator ever reports a missing dependency, it prints the exact
npm install to run — run that in the skill folder, then re-run the validator.
reference/:
reference/schema.json — the authoritative JSON Schema for the whole
document. When unsure about a field, this is the source of truth.reference/block-guide.md — a concise description of every block type and
its fields.reference/examples/*.json — complete, valid templates to model your
output on.{ "blocks": [...], "settings": {...} }
document, following the schema exactly (see Rules)..templatical/<name>.json (see Working files — generate a
fresh three-word name for a new template; create the folder if needed) and run:
node scripts/validate.mjs .templatical/<name>.json
Fix every structural error reported and re-run until it passes. When
@templatical/quality is installed, also resolve reported accessibility /
structure / link warnings. Writing to that file is what lets a later "show it
live" pick up the current template with no extra step.editor.setContent(json)); many others just want a finished email — for them,
preview it live and export MJML/HTML to send (see Live mode)
through any provider (SES, Postmark, …), no integration needed. Frame the
hand-off for what they're actually doing.Every template lives in the user's .templatical/ folder as its own file with a
random three-word name, like a Claude plan file — e.g.
.templatical/misty-copper-otter.json. This keeps finished work around as a
browsable history instead of one file that silently carries state between
unrelated sessions.
.templatical/ (regenerate if it does —
never overwrite an existing template), and write there. A fresh session thus
starts a fresh template; never silently resume an earlier one..templatical/*.json — using each file's first title/heading block as a hint —
and use the one they mean..templatical/ folder is a working area;
it's fine to leave old templates there (suggest the user gitignore it), and the
user can clear it whenever they like.If the user has a template from another editor in their project — Unlayer,
BeeFree, or an HTML email — convert it to Templatical instead of building
from scratch. scripts/import.mjs runs the matching @templatical/import-*
converter:
node <skill>/scripts/import.mjs <source-file> [--format unlayer|beefree|html]
It auto-detects the format (Unlayer / BeeFree JSON, or .html), writes the
result to a working file .templatical/<name>.json (same as a generated
template — --out <name> overrides the default, which is the source file's
name), and prints a conversion report: how many blocks converted cleanly vs.
fell back to html vs. were skipped, plus warnings.
npm install @templatical/import-<format> if it's
missing. Build mode stays ajv-only.html blocks or get dropped.
So after importing: validate, then open it in live mode and refine the
html-fallback / skipped blocks into native blocks. That convert → preview →
refine loop is the whole point of importing through the skill rather than using
the converter package raw.section, title, paragraph, image,
button, divider, spacer, social, video, menu, table, html.
Prefer native blocks — reach for html only when nothing else fits, since raw
HTML is not visually editable afterward.countdown or custom blocks (even though the schema allows
them): countdown needs the Templatical Cloud backend to render its
animated GIF — the open-source renderer can't, so it would break — and custom
blocks are consumer-registered runtime extensions that can't be produced from a
prompt. If the user asks for a countdown, say it's a Cloud feature and offer a
static stand-in instead — a title/paragraph with the date/time, or a "X days
to go" line (optionally a {{merge_tag}}).id (unique, e.g. "title_1"), type, and
styles.padding ({ top, right, bottom, left } in px).section has children: an array of
columns, each column an array of blocks. columns is "1", "2", "3",
"2-1", or "1-2", and the column count in children must match. Don't nest
a section inside another section — MJML has no equivalent, so the renderer
drops it on export.title.content, paragraph.content) is HTML — use inline tags
(<b>, <i>, <a href>, <br>, <ul>). Use blocks, not HTML, for layout.
Table cell content is the exception — plain text, no inline HTML (tags
render literally); for emphasis use hasHeaderRow, or a 2-column section of
paragraph blocks for a label/value layout.{{contact.field_name}} (e.g.
{{contact.first_name}}); they're substituted when the email is sent.reference/schema.json."#4CBB17"). Images: use a real URL when
given, else a placeholder like https://placehold.co/600x300, and always write
meaningful alt text.width (usually 600), backgroundColor,
textColor, fontFamily, linkUnderline, and locale (BCP-47, e.g. "en").Layer the user's own context on top of these rules — brand guidelines, a house system prompt, tone of voice, preferred fonts/palette, a mandatory footer or links. When brand settings are provided, use them for colors, fonts, and copy voice instead of generic defaults. This skill defines the format; the user's context defines the taste.
Live mode opens the template in the real Templatical editor in a browser and keeps it in sync as the user prompts, so they watch the email take shape and can also drag-edit it directly. It's optional.
Where it runs. Live mode runs on the user's own machine — it keeps a
background process (the bridge) alive across turns and reaches localhost. If
your environment can't do that (e.g. a hosted or server-side sandbox with no
local filesystem or reachable port), tell the user live mode isn't available here
and stay in build mode. Build mode itself is unchanged.
It adds no npm dependencies. The bridge (scripts/live-server.mjs) uses only
Node built-ins; the editor and mjml-browser load from the CDN. These assets are
inert until live mode is started.
Enter it whenever the user expresses the intent — "show it live", "preview it
live", "open it in the editor", "build this in live mode", or similar — mid-session
is fine. Natural-language intent is the portable trigger and works on every
harness. (In Claude Code you can also pass it as an argument with a space:
/templatical-email live — use a space, not a colon; /templatical-email:live is
plugin-command-namespace syntax that silently starts build mode instead.)
Live mode serves the session's working template (.templatical/<name>.json, see
Working files); if the user hasn't built one yet, create a new
template first. A mid-session switch just points the bridge at that file.
Working directory matters. The working file and the server's pidfile live under the user's project directory (
<project>/.templatical/), not this skill's folder. Run every command below —live-server.mjs(start/reload/stop) andvalidate.mjs— with the project as the current directory, referencing the skill script by its path (node <skill>/scripts/live-server.mjs). If you can't control the cwd, pass--cwd <project>(and optionally--file <path>) sostart/reload/stopall agree on the same location.
.templatical/<name>.json exists and is valid (run the
validator; build a new template first if there isn't one yet).--file:
node <skill>/scripts/live-server.mjs --file .templatical/<name>.json
It prints the URL it's serving, opens it in the user's default browser,
and prints the working-file path. It prefers port 4747 but falls back to a free
port if that's taken, so read the actual URL from its output (the port is
also recorded in .templatical/live-server.pid as port) — don't assume a
fixed port. It is single-instance via the pidfile guard; a second start just
reports the running one. Other flags: --port <n>, --cwd <project>,
--no-open (skip the auto-open).When the user asks for a change:
GET /content endpoint (at the URL from step 2) → { divergent, content }.
divergent: false → no in-browser hand-edits since your last write. Proceed.divergent: true → the user hand-edited in the browser. Ask before
overwriting: "You've edited the template in the browser since I last
updated it. Build on your browser version, or replace it with what I have?"
content as your new base, apply
the requested change on top of it, and continue.node <skill>/scripts/validate.mjs .templatical/<name>.json
(write your candidate first). Never push invalid content to the editor..templatical/<name>.json, then push it:
node <skill>/scripts/live-server.mjs reload
The page updates live (over Server-Sent Events) — no refresh.The page's Export button opens a modal with JSON / MJML / HTML tabs (HTML
compiles in-browser via mjml-browser, loaded on demand). You can also hand the
user JSON directly, or MJML/HTML via @templatical/renderer in build mode.
Stop the bridge when the user is done (or the session ends) so no process or port is orphaned:
node <skill>/scripts/live-server.mjs stop
.templatical/ is a working directory — it holds the shared template and
the bridge's pidfile. Suggest the user add .templatical/ to their project's
.gitignore (don't edit their .gitignore without asking).html blocks run as-is in the preview (the editor sanitizes rich text, but
raw html blocks are not sanitized). It's the user's own local content, but be
aware the preview executes it.reference/schema.json.Guides collaborative design exploration before implementation: explores context, asks clarifying questions, proposes approaches, and writes a design doc for user approval.
Creates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.
Resolves in-progress git merge or rebase conflicts by analyzing history, understanding intent, and preserving both changes where possible. Runs automated checks after resolution.
npx claudepluginhub templatical/sdk --plugin templatical-email