Claude-skill-registry email-template-rendering
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/email-template-rendering" ~/.claude/skills/majiayu000-claude-skill-registry-email-template-rendering && rm -rf "$T"
manifest:
skills/data/email-template-rendering/SKILL.mdsource content
Email Template Rendering Fixes
Problem
Handlebars templates for email notifications fail to render correctly, showing raw variables, missing helpers, or escaped HTML.
Trigger Conditions
- Error:
Missing helper: "formatDate" - Variables showing as
in sent emails{{variable}} - Error:
The partial X could not be found - HTML appearing escaped (
instead of<div>
)<div> - Working in
directoryapps/notifications/
Solution
Issue 1: Missing Helpers
Register custom helpers before compiling templates:
import Handlebars from 'handlebars'; // Register helpers BEFORE compiling templates Handlebars.registerHelper('formatDate', (date: Date, format: string) => { return dayjs(date).format(format); }); Handlebars.registerHelper('formatCurrency', (amount: number, currency: string) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency || 'USD', }).format(amount); }); // Now compile const template = Handlebars.compile(templateSource);
Issue 2: HTML Escaping
Use triple braces for unescaped HTML:
{{! WRONG - HTML will be escaped }} <div>{{htmlContent}}</div> {{! CORRECT - HTML renders as-is }} <div>{{{htmlContent}}}</div>
Or use
SafeString in helpers:
Handlebars.registerHelper('renderHtml', (html: string) => { return new Handlebars.SafeString(html); });
Issue 3: Partials Not Found
Register partials before use:
// Register partial Handlebars.registerPartial('header', headerTemplateSource); Handlebars.registerPartial('footer', footerTemplateSource); // Use in template // {{> header}} // ... content ... // {{> footer}}
Issue 4: Async Data in Templates
Handlebars is synchronous. Resolve all data before rendering:
// WRONG const template = Handlebars.compile(source); const html = template({ user: await getUser() }); // ❌ Promise in template // CORRECT const user = await getUser(); const orders = await getOrders(user.id); const template = Handlebars.compile(source); const html = template({ user, orders }); // ✅ Resolved data
Verification
- Compile template without errors
- Render with sample data
- Check output HTML is correct
- Send test email and verify in email client
Notes
- This skill only loads when working in
apps/notifications/ - Always precompile templates in production for performance
- Test emails in multiple clients (Gmail, Outlook, Apple Mail)
- Use inline CSS for email compatibility