Product

We built our own CMS, because clients should be able to fix a typo

Today we are launching the website CMS inside the MPP Portal: an editor our clients use to change their own sites, on top of a deployment pipeline our developers still trust.

Those two requirements are usually in tension. Resolving that tension is the entire product.

The economics of a typo

A client emails: the phone number in the footer is wrong.

In the traditional arrangement, that email becomes a ticket. The ticket is triaged, assigned, scheduled. A developer pulls the repository, makes a one-character change, opens a pull request, waits for review, merges, watches the deploy. Someone updates the ticket. Someone replies to the client. Somewhere in there, a project manager reports on it.

Elapsed time: two days. Billable value: none anyone is comfortable charging. Multiply by forty clients and the "small requests" queue quietly becomes a full-time job that generates no revenue and, worse, makes clients feel like a nuisance for wanting their phone number correct.

The obvious fix is to give clients access to their site. The reason agencies resist is equally obvious: we have all seen what happens when someone with no HTML experience is handed the raw template and a save button.

What we built

A visual editor over a real Git workflow.

The client sees their actual homepage, rendered as it appears live. They click a headline and type. They drag a section above another section. They describe a change in plain English and Claude applies it. When they are happy, they publish.

Underneath, none of the safety was removed:

  • Edits load the site's genuine index.html from its GitHub repository, not a copy, not an approximation.
  • Saving commits to a staging branch, which the host builds into a preview at a separate URL. The live site does not move.
  • Publishing merges staging into the production branch, which triggers the real deploy.
  • Every change is a commit, by a known author, with a message and a diff. If something breaks, git revert still works, because this is still Git.

The client experiences a friendly editor. The repository experiences a normal, reviewable contribution. Nobody has to compromise.

Getting sites into it

The unglamorous half of a CMS is onboarding, and it is where most of them lose.

We import sites directly from our host: list every site on the account, pick the ones to bring in, and the portal records the live URL, the connected repository, and the production branch. Then it finds the site's actual entry file, because real client sites are not uniformly index.html at the root. Some build to public/, some to dist/, some live in a subfolder from a previous agency's structure. The editor tries the likely paths, then asks the repository where its HTML actually is, and remembers the answer so the next open is instant.

That discovery logic is unremarkable to describe and was most of the engineering.

Letting clients in without letting everyone in

Clients do not want another login. We do not want to create portal accounts for people who need to change a sentence twice a year.

So we mint a signed edit link scoped to one site, valid for a set number of days. The client clicks it and edits their site: no account, no password. The token authorizes exactly one repository, and the publish endpoint verifies the token matches the site before it will commit anything. A link for one client's site is useless against another's.

Client edits land on staging by design. They can change their copy freely; pushing to production stays with us.

The AI part, described precisely

There is an "AI Edit" box. You type "make the hero headline shorter and lead with the outcome", and the page changes.

What is actually happening: the current HTML and the instruction go to Claude, which returns modified HTML that gets loaded back into the editor. You see the result before anything is committed. Reject it and nothing happened.

It is genuinely useful for the class of edit that is easy to describe and tedious to perform: rewording six cards consistently, restructuring a section, fixing the spacing everywhere at once. It is not a replacement for a designer, and we do not pretend it is. It is a faster path from intent to a reviewable diff.

What this changed for us

The small-requests queue stopped existing. Clients change their own copy the moment they think of it.

Turnaround stopped being a differentiator we had to defend. "Two days for a typo" is indefensible; "you can do it yourself in thirty seconds, and we will handle anything structural" is a better answer than any SLA.

Developer time went back to development. The people who can build things stopped spending afternoons on content edits.

Trust went up in an unexpected direction. Clients who can see and touch their own site ask better questions about it. Involvement turns out to correlate with retention more than polish does.

The principle underneath

Most agency processes exist to protect against a risk that better tooling could eliminate. Gatekeeping client edits protects against breakage. Staging branches, previews, and reversible commits protect against breakage too, and they do it without making the client wait, or making a developer do work beneath their capability.

Ask of any process you defend: is this preventing a real failure, or is it compensating for tooling we never built?

Next up in this series: the workspace and the chat app we replaced. If you want a partner who removes friction rather than billing for it, apply for partnership.