Notes

How to let a client edit website copy without giving them a CMS

July 28, 2026 · 8 min read

You built the site. It launched. It was good. And then the messages started arriving:

“Can we change ‘Get started’ to ‘Start free’?”
“The pricing subhead should say monthly, not per month.”
“Sorry, one more, can the hero say ‘teams’ instead of ‘companies’?”

Each one is a thirty-second edit that costs you twenty minutes: read the message, find the string, change it, commit, wait for the deploy, check it, reply. Multiply by a week and you have lost an afternoon to work that required none of your skills.

The instinct is to reach for a CMS. That is usually the most expensive possible answer to the question. Here are the five real options, in the order teams normally try them.

Option 1: move the site into a full CMS

WordPress, Webflow, Squarespace. The client gets a login and can edit everything.

What it costs: you rebuild the site. You inherit a templating language, a plugin ecosystem, and a hosting story you did not choose. Your React components, your design system, and your deployment pipeline all go in the bin. You will also spend the next two years fielding “the layout broke” messages, because a CMS that can edit anything can break anything.

When it is right: the client genuinely needs to publish new pages on their own — a blog, a careers section, a product catalogue. If they need structure, not just words, a CMS earns its keep.

Option 2: a headless CMS

Contentful, Sanity, Storyblok, Payload. You keep your frontend; the copy lives in an API.

What it costs: more than people expect. Every string on the page has to become a field in a schema. Someone has to model that schema, keep it in sync with the components, and maintain it as the design changes. You add a network call, a caching strategy, a preview environment, and a webhook to rebuild on publish. Then there is the monthly bill, which for the paid tiers of the popular options lands somewhere between a modest subscription and a real line item.

The subtler cost is conceptual. A headless CMS asks you to decide, up front, which text is content and which text is design. That boundary is never clean. The button label is content until it needs to fit in 80 pixels, and then it is design.

When it is right: multiple content types, multiple locales, multiple people publishing on a schedule. If you are running a content operation, run it on a content platform.

Option 3: the Google Sheet

A sheet of key-value pairs, pulled at build time. Cheap, and more common than anyone admits.

What it costs: the client edits blind. They are looking at hero.subhead.line2 in a spreadsheet cell, not at the page. They cannot see that their new sentence wraps onto three lines and pushes the button below the fold. You still have to redeploy, and you still get the “did it work?” message. Somebody eventually renames a key and a page ships with a blank heading.

When it is right: genuinely structured, repetitive data — a pricing table, a list of locations, an FAQ. Rows and columns for things that really are rows and columns.

Option 4: teach the client to edit the code

Give them access to the repo, or a web editor, and let them change strings on a branch.

What it costs: your evenings. You have converted a copy problem into a git problem, and git problems escalate. The best case is that they are careful and slow. The realistic case is a merge conflict at 11pm and a message that starts “I think I broke something.”

When it is right: the “client” is a technical colleague who already lives in the repo.

Option 5: in-place editing on the live site

The copywriter opens the real page, clicks the actual text, types, and clicks away. The change is live. No login to a separate system, no schema, no redeploy.

This is the option most teams do not know exists, because it sits between “hardcoded” and “CMS” and nobody sells it loudly. Mechanically it is simpler than any of the above:

  • Every editable string in your components is marked with a stable id.
  • The in-code text stays exactly where it is — it is the default, and it is what ships if everything else fails.
  • Edits are stored as a sparse override layer: a small key-value map of only the strings that were actually changed.
  • The page renders the override if one exists, otherwise the in-code default.

The consequences of that design are the interesting part. Because the overrides are sparse, deleting the store returns the site to the copy in your repo — the code is always a working fallback. Because the default lives in the component, a developer reading the JSX still sees real words, not {t('hero.title')}. And because editing happens on the live page, the editor sees the line wrap, the truncation, and the button width as they type.

What to watch for

In-place editing is not free of trade-offs. Three things matter:

Who can edit

Editing has to be behind something. A shared password gate is usually right for a small team — no user accounts to manage, one secret to rotate — but it must be a real server-side check, not a hidden button. Anything that only hides the UI is not access control.

What happens to the words

Text typed into a live page must be treated as untrusted input. Store and render it as plain text; never inject it as HTML. This is the single most common way a well-meaning inline editor turns into a cross-site scripting hole.

Getting the copy back into the repo

If overrides only ever live in a database, your repo slowly drifts into fiction. You want a way to pull production copy back down and fold it into the code, so the defaults stay honest.

Picking one

A rough rule: if the client needs to create pages, give them a CMS. If they only need to change words, do not.

Most of the requests that interrupt your week are the second kind. They are not a content-management problem. They are a “the word is wrong and I can see it right there” problem, and the fix should take the person who noticed about four seconds.

Copy Edit Mode is that fifth option, packaged as a Claude Code skill: Claude wires the ?edit mode into your existing app, and your copywriter edits the live site from the browser. One-time $7.99, no subscription, no per-seat pricing, and it does not own your content.