Pre-send QA
DeliverabilityPre-send QA
A live audit that lints the design for the mistakes that hurt deliverability and rendering, before it's sent. The toolbar's Audit button carries a live badge with the current error/warning count, and opens a docked, non-blocking panel you can keep open while you fix issues, each finding jumps straight to the offending block.
Audit is a paid feature, the button appears only when the plan grants
qa.audit (part of the Deliverability suite with Inbox previews; see Plans & entitlements).What it checks#
| Property | Controls | Default |
|---|---|---|
Links | Empty/placeholder (#, example.com) and unsafe javascript: URLs | error / warning |
Alt text | Images & GIFs missing alt text | warning |
Heading order | A heading that skips a level (h1 straight to h3) | warning |
Link text | Links that say only click here or read more | info |
Button label | A button with no label | warning |
Small text | Text, headings and buttons under 12px | warning |
Table header | A table with the header row turned off | info |
Language | No document language set in Body settings | info |
Contrast | Button text vs background below WCAG 4.5:1 | warning |
Subject line | Missing, or longer than ~70 characters | warning / info |
Preheader | No preheader text set | info |
Unsubscribe | No unsubscribe link / {{unsubscribe_url}} found | warning |
Spam words | Classic spam-filter trigger phrases in subject/content | info |
Gmail clipping | HTML over about 102 KB (Gmail hides the rest), or over 90 KB (close). Linked images do not count. The toolbar shows a Gmail size badge from 90 KB | warning / info |
Programmatic#
The same audit is exported from the renderer, so you can gate your own send flow:
tsqa.ts
import { auditDesign } from "email-craft-sdk";
const findings = auditDesign(design);
// [{ id, severity: "error"|"warning"|"info", category, message, blockId?, hint? }]
const blockers = findings.filter((f) => f.severity === "error");
if (blockers.length) throw new Error("Fix QA errors before sending");Custom validators#
Register your own rules with config.qa.validators (or pass them to auditDesign(design, { validators })). They run alongside the built-in checks and their findings merge into the same live panel. A validator that throws is skipped, one bad rule never breaks the audit.
tscustomValidators.ts
const config = {
qa: {
validators: [
{
id: "brand", run: (design) => {
const hasLogo = design.body.rows.some((r) =>
r.columns.some((c) => c.blocks.some((b) => b.type === "image")));
return hasLogo ? [] : [{ severity: "error", message: "Add your logo before sending." }];
}
}
]
}
};