How to let customers edit their own report templates
Handing over the layout is a product decision before it is an engineering one. The editor is the easy half; the half that decides whether this is a feature or a permanent support cost is everything around it.
Why this comes up
Nobody sets out to build a document editor. It arrives as a series of individually reasonable requests — a logo moved, a column added, a section reordered, a footer with somebody's regulatory wording in it — each of which is twenty minutes of work and a release.
The cost is not the twenty minutes. It is that the layout has become application state that only you can change, so every change requires your calendar. That is why the request eventually arrives as “can we just do it ourselves”, and why it usually arrives from your largest customer.
The decision is not “should customers be able to edit templates”. It is “how much control, to whom, with what protection” — and getting that wrong in either direction is expensive.
Three levels of control
These are genuinely different products with different costs. Most teams ask for the third and need the second.
Branding only
Logo, colours, typeface, company details in the footer. The layout is fixed and yours.
Costs: a settings screen and a theme applied at render time. Solves: perhaps sixty per cent of what customers actually ask for, because “can it look like us” is a more common request than “can we move this”. Fails when: a customer needs a section that does not exist, or needs one removed.
Content within a fixed layout
The structure is yours; customers choose what goes in it — which sections appear, which columns a table shows, the wording of their own headings and notes, the order within a section.
Costs: a configuration model and a screen to edit it, plus somewhere to store it per tenant. Solves: most of the rest. Fails when: the structure itself is the thing in dispute — and it is worth noticing that a configuration model rich enough to avoid that is a document model with a worse editor.
Full layout
Customers arrange the document. Blocks, tables, charts, page breaks, headers and footers, bound to the fields you declared.
Costs: a real designer, plus every guard rail below. Solves: the request permanently, and stops layout work reaching your backlog at all. Fails when: nobody actually wanted it, and you have added a surface to support for a feature two tenants use.
A useful test before committing to level three: look at the last twenty layout requests you received. If most of them are “make it look like us” and “turn that section off”, you need levels one and two, and you can build both in a fortnight. If a third of them are structural, level two will not hold, and building it first means building the wrong thing twice.
Four things that break
Everything below is what happens in month three, not week one. Week one is fine; week one is a demo.
The support queue moves rather than shrinking
“Can you move this” becomes “I moved it and now it looks wrong”. The tickets are cheaper — nobody is waiting for a release — but there are more of them, and they need someone who can open the customer's template and look. Budget for that, and make sure whoever answers support can see a tenant's design without a developer.
Customers save documents that cannot render
A binding to a field that no longer exists, a table bound to something that is not a list, a section that overflows a page. If the first thing that notices is the render on the last working day of the month, you have built a time bomb with a monthly fuse.
Your schema moves underneath them
This is the one that bites in year two. You rename a field, split one in two, retire one that was a mistake — and forty stored templates reference it. Nothing fails loudly. A document simply comes out with a space where a number used to be.
The preview lies
A customer approves a layout on screen and the PDF breaks somewhere else — usually because the preview is HTML and the file is produced by something that measures text differently, or because the brand's font is on screen and not in the file. Once that has happened twice, nobody trusts the editor, and they go back to asking you.
A preview that disagrees with the file is worse than no preview, because it converts a design tool into a lottery. This is the requirement people evaluate last and regret first.
The guard rails
Six, and they are cheap next to the editor itself.
- Validate before you store. A check that answers “is this design sound?” without any data — every binding resolves, every block is known, every expression type-checks — turns a broken template into a 422 at save time instead of a blank on a document. Do it at your API, not only in the editor, because the editor is a user interface and user interfaces are not enforcement.
- Keep revisions, and make restore non-destructive. A restore should write a new revision containing the old content, so the restore itself can be undone. The alternative is a customer who restored the wrong version and has now lost both.
- Always offer a reset. “Back to the standard design” must work from any state. It is also the sentence that lets your support team close a ticket in one reply.
- Separate designing from running. Editing templates is a distinct permission from producing documents, and most tenants should grant it to one or two people. Most products collapse these and regret it.
- Narrow the editor to the audience. An operations manager does not need page margins, raw expressions or a JSON view; an enterprise power user might want all three. Same editor, different flags — and every control you do not show is a support ticket you do not get.
- Make the preview true. Whatever paginates the preview must be what paginates the file, and the fonts the brand names must be embedded in both. If those two are not true, fix that before you ship the editor.
/**
* The three operations that make customer editing supportable. Nothing
* here is exotic; the mistake is shipping the editor without them.
*/
// 1. Refuse a design that cannot render, at the API, before it is stored.
const result = validateTemplate({ template, registry, dataSources });
if (!result.ok) return problem(422, result.errors);
// 2. Keep what it replaced. A restore writes a NEW revision holding the
// old content, so the restore itself can be undone.
await revisions.add({ templateId, content: previous, reason: "edit" });
// 3. Reset always works, because the default is not a copy that drifted —
// it is the design we ship, re-applied.
await templates.replace(templateId, defaults[kind]); How to roll it out
In this order. Each step is also a way to stop, which is the point of doing it in this order.
- Make the defaults excellent first. Most tenants will never change them, and a good default is the highest leverage work in this whole project. It is also what “reset” restores to.
- Ship branding. Levels one and two. Measure how many of your layout requests stop arriving. For a lot of products this is where it ends, and that is a success rather than a retreat.
- Open the designer to one customer. Ideally the one who asked loudest. Watch what they do; the surprising part is always which controls confuse them, not which are missing.
- Add the guard rails you just discovered you needed, then open it to the rest.
- Instrument it. How many tenants have edited a template at all, how many have reset, how many templates currently fail validation. Those three numbers tell you whether this was worth building.
What should never be editable
Be as clear about this as about the rest, because “customers can edit their documents” is exactly the kind of sentence that ends up applying to a document it should never have applied to.
- Statutory and regulatory documents. Anything whose wording or ordering is prescribed. Those belong in code, in version control, where a reviewer sees the change and an auditor can see who approved it.
- Anything with a legal signature block or a retention requirement, unless a compliance owner has explicitly agreed to the edit path.
- Documents that go to a third party under your name rather than the customer's — a platform statement, a trust confirmation. Your letterhead, your layout.
A product with both kinds is the normal outcome. Keep the prescribed documents in code and hand over the negotiable ones; the line is usually obvious once somebody asks where it is.
Where BroadPaper fits
BroadPaper is the level-three editor, with the guard rails built in rather than left to you. It embeds in a React or Angular application — or any other, through one framework-free mount call — and what your customers save is JSON you store.
- They only see what you declared. A typed schema of fields, with your labels. No table names, no query builder, no way to reach anything you did not describe.
- Validation without data, so your API can refuse a design that cannot render, and you can revalidate every stored template after a schema change.
- Feature flags that narrow the editor per audience, including white-labelling it entirely.
- Themes that keep branding on the tenant rather than baked into templates, so one design serves everybody.
- A paginator we own, so the preview and the file break in the same places — and the fonts a brand declares are embedded in both.
- No hosted component. Nothing phones home; rendering happens in your infrastructure or in your users' browsers.
The embedded designer page covers the product, and the architecture guide has the schema, storage, permissions and versioning in code. If you would rather look than read, the demo is the whole editor with no account.
Questions
- How do I let customers edit their own PDF templates?
- Decide the level of control first — branding only, content within a fixed layout, or full layout — then give them an editor bound to fields you declared, store what they save as data, validate it before you accept it, and keep revisions so a change can be undone. The editor is the smallest part; the guard rails are what make it survivable.
- What happens when a customer breaks their own template?
- Three things stop it becoming your problem: validation that refuses a design that cannot render, revision history with a restore, and a “reset to the default” that always works. With those, a broken template is a customer self-serving in ninety seconds; without them it is a support ticket and a manual database edit.
- Should every customer be able to edit, or only some?
- Only some, in our experience. Designing is a different right from running a report, and most tenants have one or two people who should hold it. Collapsing the two is how a support agent ends up able to change what every client's statement says.
- How do we stop support costs going up?
- Start with defaults that are genuinely good, because most tenants will never change them. Then constrain what an editor exposes to the audience using it — page margins and raw expressions are support tickets waiting to happen for an operations manager, and useful for a power user at an enterprise account.
- What should never be customer-editable?
- Anything whose content or ordering is prescribed by somebody else: statutory notices, regulatory forms, documents with legally required wording. Those belong in code, in version control, where a reviewer sees them change and an auditor can see who approved it.
- Can customers' changes break when we change our data model?
- They can, which is the main long-term risk. Treat your declared fields as a published API — add rather than rename — and run a check that revalidates every stored template against the current schema after any change, so you find the affected designs instead of a customer finding them at month end.
See what you would be handing over.
The designer, running in your own browser: bind a field, move a section, export a PDF. It is the same build a customer of yours would get.