All writing
Jun 12, 20267 min read

Small content sites do not always need a CMS

Local MDX can be the clearest publishing system when the team is small and the content changes deliberately.

Next.jsMDX

A CMS is often treated as a standard item on the website checklist. Sometimes it is exactly the right choice. Other times, it adds an admin interface, database, credentials, and maintenance workflow to a site maintained by one technical person a few times a month.

For a portfolio, documentation site, or small publication, local Markdown can be a more comfortable place to start. The important distinction is not whether a CMS is modern or excessive. It is whether the publishing workflow needs what a CMS provides.

The file can be the interface

This site keeps projects and articles in MDX files. Each file contains a short frontmatter block and the body of the page. The filename becomes the URL, Git records every change, and the content travels with the application.

That workflow would be a poor fit for a nontechnical editorial team. For a developer maintaining a personal site, it is direct. There is no second system to log into, no API connection to keep alive, and no question about whether code and content are out of sync.

The editing interface is whichever text editor I already use. Search and bulk updates work across the repository, while drafts can follow the same review process as component changes.

This is not the absence of a content system. The repository, schema, preview environment, and deployment pipeline are the content system. It is simply assembled from tools that already exist in the project.

Treat content like structured data

Local files should not mean unstructured files. Titles, summaries, dates, tags, draft status, and cover images can be checked during the build.

const postSchema = z.object({
  title: z.string().min(1),
  publishedAt: z.string().date(),
  draft: z.boolean().default(false),
});

The important part is not Zod specifically. It is having one explicit contract. A missing title or malformed date should fail while I am working, not quietly create a broken card in production.

The schema also defines which fields are required or optional. That makes later migration easier because the content shape is explicit rather than implied by a collection of templates.

I also prefer keeping presentation out of frontmatter. A field such as featured: true describes editorial intent. A field such as marginTop: 72 leaks one layout decision into every article. The content model should explain what something is, while components decide how it looks.

Publishing is still a workflow

Choosing files over a CMS does not remove publishing work. It changes where that work happens.

A typical update means editing an MDX file, checking the route locally, and committing the result. A preview deployment can provide a shareable version before the content ships with the application.

That process makes every publication reviewable and build-checked, but a typo cannot be corrected from a phone through a browser dashboard. It works when updates are deliberate and the maintainer knows Git. It becomes expensive when publishing must be spontaneous, delegated, or frequent.

Keep routes and deployments predictable

Deriving slugs from filenames creates an obvious relationship:

content/blog/designing-better-forms.mdx
→ /blog/designing-better-forms

That predictability makes the system easy to inspect. Static generation can build article pages ahead of time, which avoids adding runtime content infrastructure just to display text.

The deployment is also self-contained: each application version includes the content shape it expects. The trade-off is that publishing requires a new build, and drafts depend on a local or hosted preview. That cost is reasonable only when the deployment pipeline is dependable.

Ownership is an advantage and a constraint

For a solo developer, repository access can be simpler than managing another set of users, roles, and permissions. The same arrangement becomes a bottleneck when a writer must understand branches and merge conflicts just to correct a sentence.

Collaboration is the clearest test. One occasional contributor can use a pull request or send a document to the maintainer. Several independent editors need drafts, previews, approvals, and permissions designed around editorial work. Recreating those features inside a repository is usually a sign that the simpler system is no longer simple.

If only one person understands how content reaches production, the preview, validation, and publishing steps should also be documented for the next maintainer.

Do not romanticise simplicity

Markdown has edges. Image management is manual. Scheduling, permissions, media libraries, and multi-author review are not built in. Rich relationships between authors, categories, products, and reusable blocks need additional modelling.

MDX can also allow components inside content. That is useful for a genuine interactive element, but it raises the knowledge required to edit safely. I would keep the available components small and documented rather than turning every article into an unconstrained application page.

When a publishing team needs the missing features, these limitations are signals that the workflow has outgrown the tool.

Know when the site needs a CMS

I would reconsider local files when editors need a browser interface, several people publish independently, approvals or scheduled releases matter, content relationships become complex, or updates must happen without a deployment.

Volume alone is not the deciding factor. A site can hold hundreds of stable documents comfortably in files, while a ten-page site can urgently need a CMS because several people update it every day. The pressure comes from workflow and ownership more than page count.

Other migration triggers include repeated merge conflicts in content, developers becoming a publishing help desk, media becoming difficult to organise, and nontechnical editors avoiding necessary updates because the process feels risky. At that point, a CMS removes friction rather than adding ceremony.

Make a later migration boring

Starting without a CMS should not make one difficult to add. Clear frontmatter, ordinary Markdown, stable slugs, and consistently stored media create a portable foundation.

I would also keep content loading behind one application boundary. Pages should request a post through a content function rather than reading files throughout the component tree. If the source changes later, the mapping work stays concentrated in one place and migration remains a structured conversion rather than a recovery exercise.

Use a practical decision checklist

Before adding a CMS, I would ask:

  • Who will write, review, and publish the content?
  • Are those people comfortable working in the repository?
  • Does publishing need to happen without a deployment?
  • Are scheduling, permissions, media management, or approvals required now?
  • How often does content change, and how quickly must corrections go live?
  • Can the current workflow be documented clearly enough for another maintainer?

If the answers point toward one technical owner, deliberate updates, and an existing deployment workflow, local MDX is a strong starting point. If they point toward independent editors and operational publishing needs, a CMS is likely the simpler choice despite its additional infrastructure.

Start with the workflow you have

Architecture is often planned around a future organisation that never arrives. I would rather begin with the smallest system that serves the current team, while keeping the content model portable enough to change later.

A CMS is valuable when it solves a real publishing problem. Until that problem exists, a folder of validated text files, a trustworthy preview, and a predictable deployment can form a durable content system. The goal is not to avoid a CMS. It is to introduce one at the moment it makes publishing easier rather than merely making the architecture look complete.

Continue the conversation

Get the next field note.

Occasional writing about development, systems, and better web decisions.