case studies

Email Templates Customers Rewrite: One Conflict Settled Once, and Legal Text the Product Owns

Email templates are the reference data customers change most. A self-hosted product ships a welcome email, a password reset and an invoice notice. Each customer’s admin rebrands the subject lines, switches off what they don’t use and sometimes edits the small print. Then the product team fixes a typo in a subject the admin already rewrote, and updates the legal footer every email must carry.

The templates example gives the columns three different owners. The subject and body are merged, so an admin’s edit stays unless the seed changes the same value. enabled is local: on when shipped, the customer’s after that. And the footer belongs to the product.

[columns]
footer = "seed"
enabled = "local"

The plan for release 2 as a pull request comment: blocked by a conflict over the welcome subject, with footer and body updates and a new login alert template The plan as a pull request comment; two more footer updates are left out to fit.

The Conflict

Release 1 ships three templates. A clinic’s admin changes the welcome subject to “Welcome to the Riverside Clinic portal”, turns the invoice email off, and writes their own footer on the password email. Release 2 changes the welcome subject to “Welcome aboard!”, shortens the reset link’s lifetime in the password email’s body, updates the footer everywhere and adds a login alert.

The subject changed on both sides, differently. Bootstrapping won’t pick a winner, so the apply stops and writes nothing at all, not even the parts that didn’t conflict. The example shows the plan first as bst plan -markdown prints it, the comment a CI step posts on the release’s pull request, then the blocked apply, then the decision: keep the clinic’s subject, for that one value only.

bst apply -db app.db -seeds seeds -take templates/welcome/subject=local

What Each Owner Gets

After the apply the clinic’s subject is still theirs, and the ledger now records the seed’s “Welcome aboard!” as applied. So the next plan sees the clinic’s subject as an ordinary local edit, and the conflict doesn’t come back. The invoice email stays off. The password email gets the new body, since the admin never touched it. And all four footers carry the new legal text, the clinic’s own footer included. That’s what seed ownership is for: a value the product must control, written every time, with the plan showing exactly which local edit it replaces before anyone applies it.

Run it with go run ./examples/templates from a clone of the repository. The reference covers -take and on_conflict, and the other case studies show plans, countries and workflow states.