Adopt your email templates
stet also manages the emails your product sends on its own — the welcome message when someone signs up, the receipt after they pay, the reminder before a trial ends. These are called transactional emails, and their words usually live inside template files only a developer can touch. Here is exactly what stet does with them:
- Takes the words — subjects, body lines, button labels — and makes them editable copy, in bulk
- Proves it changed nothing: every adopted email renders exactly as it did before
- Never touches the design — templates stay code, so an email can't break in an editor's hands
Adopt the email templates in this project. For each template: list its visible text as named slots in content/descriptor.json (turning ${…} into {{…}} variables), copy today's wording into content/defaults.json, and rewrite the template file into a shell that reads the slots. Record the template folders in stet.config.json's email-surface list. Show me every diff before applying, and tell me if any template file is untracked by git so I can commit it first. Finish with npx stet email verify. Reference: https://getstet.xyz/llms.txt
You need stet installed. The first extract names the folders your templates live in — after that, stet remembers them. Nothing is applied without your review.
01The first time: name the folders
Point extract at where your emails live and name what to adopt. stet doesn't guess — like init in the quickstart, where things live is declared once, on purpose. Applying is what saves the paths into stet.config.json, so the first run carries both.
$ npx stet email extract 'src/emails/**' --apply welcome
welcome (src/emails/welcome.tsx)
class: transactional — review
render: WelcomeEmail — sampleProps {"name":"sample-name"}
welcome__headline: "Welcome, {{name}}" — vars name
welcome__body: "You're in — here's your first step."
welcome__cta_label: "Get started"
⋮
email extract: run with --apply to write these declarations02After that: just run it
With the paths remembered, a bare extract walks every template it can read and writes a proposal per template: the visible text as named slots, interpolations as variables, and the rewrite that turns the file into a shell around them. Nothing is applied yet — the same look-before-you-touch rhythm as stet scan in the adopt chapter.
When to re-run it:
- Changing what an email says, or sending a different message — that's ordinary editing. Extract never runs.
- Someone built a new kind of email — a new template file landed in code. Re-run extract and its words join the registry with the rest.
$ npx stet email extract03Review and apply
Apply the proposals you accept — by name, or all at once. Two files take the result: content/descriptor.json records what exists — each template's slots and variables — and content/defaults.json holds today's wording for every slot. They're the same files the rest of your copy lives in.
A template extract couldn't read is skipped and reported; you write that entry by hand, and a hand-written entry counts exactly as much as a generated one.
$ npx stet email extract --apply welcome
wrote src/emails/welcome.tsx
wrote stet.config.json
email extract --apply: 1 template declared (3 slots)
⋮
next: stet email verify04Prove the design didn't change
Your git history already holds the original template file from before the rewrite. verify renders that original and the new shell with the same sample data, and compares the output byte for byte. One byte different and it fails, naming the template.
That before comes from git, so commit your template files before you adopt them. extract warns you when one isn't tracked — a template with no commit behind it has nothing to prove against.
$ npx stet email verify
welcome: PASS — 175 bytes, identical05Edit email copy like any other copy
The slots are keys now. Editors change the words, the template owns the markup, and every change goes through the same draft-and-publish flow as the rest of your copy — the edit chapter walks it.
$ npx stet draft welcome__headline --value "You're in — here's your first step"
$ npx stet publish welcome__headlineNext
- Check — the four checks, three of them fully offline
- Email slots — editors change email text without breaking the design
- Edit — the everyday draft-and-publish rhythm