Article
08
Category
Notes
Reading time
14 min read

Content as Code: The Most Underused Way to Build a Future-Proof Website

Why storing website content as open, version-controlled files can make publishing cheaper, more portable, more reliable, easier to automate, and far less dependent on proprietary CMS platforms.

At some point in the life of nearly every institutional website, a writer is asked to change a date. The task should take thirty seconds. Instead, the writer opens a browser, signs in through two-factor authentication, searches an administrative dashboard for a content item whose internal title no longer matches its public title, expands a row of nested components, finds the sentence, edits it, saves a draft, waits for a preview, discovers that the preview does not quite resemble the published page, submits the revision, and then sends a message to someone with publishing rights. A cache may need to clear. A scheduled deployment may need to run. The date, which began as twelve characters of public information, has acquired the ceremonial weight of a minor infrastructure project. Everyone involved calls this normal, because the system is an enterprise content management system and enterprise software has trained us to confuse complication with seriousness.

The same organization will usually describe that website as future-proof. It has a vendor, a service agreement, permissions, workflows, reusable components, APIs, a design system and, somewhere in a slide deck, a diagram containing several reassuring arrows. Yet the organization's actual knowledge (the pages, explanations, policies, definitions, warnings and instructions that people depend on) can be read and changed only through the current system's database, content model and interface. If the contract ends, the platform reaches end of life, the integrator disappears, the schema changes or the next redesign requires a migration, the supposedly future-proof content becomes a hostage negotiation. We have built a vault with a touchscreen on the door and congratulated ourselves because the touchscreen has rounded corners.

There is a simpler model, and it remains strangely underused outside software documentation and small publishing teams: content as code. The phrase sounds more technical than the practice. It does not mean that every policy writer must become a JavaScript developer or that a press officer should debug a build pipeline before lunch. It means that the canonical source of a website's editorial content is stored in ordinary text files (usually Markdown, often with a small block of structured metadata at the top) inside a version-controlled repository. A build process turns those files into web pages. Code handles presentation and behavior; content remains content. Forms, transactions, authentication and databases can still exist where they are genuinely needed. The point is not to turn an entire digital service into a static brochure. The point is to stop imprisoning durable public knowledge inside the temporary application used to publish it.

Markdown was designed for precisely this separation. John Gruber released it in 2004, with substantial input from Aaron Swartz, as both a plain-text writing syntax and a tool for converting that syntax into valid HTML. Its overriding design goal was readability: a Markdown document should remain understandable before any software renders it. Gruber explicitly distinguished a writing format from a publishing format. That distinction is the whole argument in miniature. A heading written as ## Eligibility is already a heading to a person, a script, a search index and an AI system. A link remains visibly a link. A list remains visibly a list. The source does not dissolve into a forest of tags, database fields or serialized blocks. It is not merely portable because a vendor promises an export button; it is portable because it begins in a form that can be opened with tools more primitive than the website itself.

The modern CMS reversed that relationship. It began as a way to spare writers from hand-authoring HTML, a reasonable objective, and gradually became an environment in which writers are spared from seeing almost everything that gives their content structure. The graphical interface presents a comforting simulation: a toolbar, a text box, perhaps a stack of draggable cards. But the web has not been what you see is what you get for years. What the writer sees on a laptop is not what a person sees on a phone, what a screen reader announces, what a search engine indexes, what an API returns or what an assistant extracts. The GUI does not remove complexity. It moves complexity out of sight and places the writer in a permanent state of dependence on whoever understands what the interface is hiding. That is not democratization. It is a division of labor designed around learned helplessness.

A graphical editor can still be useful, but it should be a lens over open files rather than the place where the organization's knowledge is held captive. Obsidian demonstrates the difference unusually well. It stores notes as Markdown-formatted plain-text files in an ordinary local folder, and those files can be edited by other text editors or managed with Git. Obsidian itself is proprietary software, which makes the example more instructive, not less: the application can be proprietary while the content remains structurally independent of it. The editor offers preview, links, navigation, search and a pleasant writing experience, but it does not require the user to surrender the underlying files. If Obsidian disappeared tomorrow, the notes would not become archaeological material. They would still be text. That is what a seamless interface should do: reduce friction without manufacturing captivity.

The second half of content as code is Git, and here organizations become unnecessarily timid. Every professional writer, editor and knowledge worker should know the basic concepts of version control: repository, commit, branch, diff, merge and revert. Not because everyone should enjoy the command line, and certainly not because the command line is morally superior, but because these concepts are now basic institutional literacy. We already expect writers to understand tracked changes, comments, document history, file naming and approval. Git provides a stricter, more reliable and more transferable version of the same ideas. It records exactly what changed, when, by whom and why. It allows an editor to compare versions line by line, test a change without overwriting the published source, review several related changes together and restore an earlier state without searching a shared drive for final_v7_really-final.docx.

Git is also open-source software, released under the GPLv2, and its origin story should be required reading for anyone who considers vendor dependence an abstract concern. The Linux kernel project had used a proprietary distributed version-control system called BitKeeper. In 2005, the relationship between the Linux community and BitKeeper's commercial developer broke down, and the tool's free-of-charge status was revoked. Linus Torvalds and the community responded by creating Git, with goals that included speed, simple design, distributed operation, support for thousands of parallel branches and the ability to handle a project as large as the Linux kernel. One of the most universal collaboration tools in modern computing exists because a critical project discovered that access granted by a company is not the same thing as control. The lesson could hardly be less subtle.

For editorial work, Git changes collaboration from a sequence of documents into a history of decisions. A writer proposes a revision. A subject expert comments on a specific line. A legal reviewer approves one part and questions another. A developer can see that a content change requires a template adjustment. Automated checks can flag a broken link, missing metadata, invalid heading order or expired review date before publication. The discussion remains attached to the change instead of being scattered across email, chat and meeting notes. The published version and the reason it became the published version share the same institutional memory. This is better collaboration not because software engineers invented it, but because the method is explicit. Most office collaboration tools are very good at helping people talk around a document. Version control is good at preserving what they decided to do to it.

This is not a theoretical workflow. GitLab treats documentation as part of the product: documentation changes move through issues and merge requests, writers and engineers review them together, and documentation is expected to ship with relevant product changes. Its documentation source lives in repositories alongside product code, and the public documentation site is generated with Hugo and deployed as a static site. The important part is not GitLab or Hugo as brands. Both can be replaced. The important part is that the editorial source, review history, software behavior and publication process share a common system of record. The documentation does not wait in a separate CMS for someone to remember that the product changed last Tuesday.

Once content is stored as files, it becomes genuinely modular. A page can be one file. A reusable warning can be another. Metadata can state the title, owner, canonical URL, language, review interval, publication status and topic. A folder can reflect an information architecture without pretending that a folder tree alone is the information architecture. Links can be checked. Related content can be generated. Translations can be paired. A content inventory can be produced without commissioning a database export from the supplier. Classic CMS platforms claim modularity, but usually mean that content has been decomposed into entities understood by that CMS: nodes, blocks, fields, widgets, paragraphs, taxonomies, relations and internal identifiers. An API does not remove this dependence. It merely gives you a documented doorway into someone else's abstraction. A headless CMS removes the head; it does not remove the lock-in.

Files also invite useful automation because their structure is visible. A short script can find every page containing an outdated year, list all content without an owner, calculate which pages are due for review, identify broken internal links, compare canonical URLs, create a spreadsheet for editors, or produce a clean corpus for search and AI retrieval. These are not exotic machine-learning projects. They are routine operations in Python, shell scripts or any of dozens of widely taught languages. I would rather teach a colleague Markdown and five Git operations once than teach the same colleague the peculiar logic of Drupal, then WordPress, then a proprietary headless platform, each with its own vocabulary and migration drama. And yes, I would rather more employees learned Python too; R is perfectly respectable, Excel is useful, and Power BI has a purpose, but none offers the same general leverage as a language that can inspect, transform and publish the organization's actual source files.

The cost difference is not merely the price of a license. A database-backed CMS requires a running application, a database, updates, security patches, plugin management, environment management, specialist knowledge, backups, monitoring and periodic upgrades whose official description often sounds suspiciously unlike the eventual invoice. An agency may be needed to change the content model because the content model has become infrastructure. A second agency may be needed to migrate the first agency's interpretation of the first platform into the second platform. Content as code does not abolish engineering or governance, but it sharply reduces the amount of machinery required to publish text. A build can transform files into static HTML and assets that are cheap to host, easy to cache and difficult to break at runtime. The expensive work moves toward things worth paying for: information architecture, accessibility, writing, design, search and actual services.

Reliability follows from the same reduction in moving parts. A static page does not need to query a content database each time someone asks to read it. A failed build can fail before publication rather than after a visitor arrives. Every deployed version can correspond to a commit, and rollback can mean redeploying a known state rather than restoring a database and hoping that uploaded assets, configuration and plugins agree about history. The concepts are old, boring and universal: files, hashes, text, directories, transformations, copies. That boredom is a strategic asset. Git's own design was intended to support a project the size and speed of the Linux kernel. A method that can coordinate changes across that environment is not too fragile for an institutional website.

When people say a website must scale, they usually mean traffic, because traffic produces diagrams and procurement language. Content as code scales well in that conventional sense: prebuilt pages can be distributed through caches and content-delivery networks without a publishing database becoming the public website's pulse. But the more important forms of scale are organizational and temporal. Can a hundred contributors work without overwriting one another? Can five languages share structure without becoming five unrelated sites? Can content be reused in a website, email, printed guide, search index, dataset and assistant? Can a new supplier rebuild the presentation layer without first reverse-engineering a decade of database conventions? Can the material still be opened after the current framework, vendor and domain strategy are gone? A system that serves ten million page views but requires a six-month migration to change platforms has scaled in only the least interesting direction.

This is where the AI question becomes concrete rather than fashionable. Organizations are rushing to make their information legible to assistants while continuing to store the canonical version in systems optimized for visual page assembly. They then scrape their own rendered HTML, remove navigation, cookie notices, duplicated components and layout debris, infer headings, reconstruct metadata and call the result an AI-ready knowledge base. It is an absurd loop. Markdown and similarly clean text formats already separate meaning from presentation. Headings, lists, links, quotations, code, metadata and relationships are explicit. The same source can be rendered for a person, indexed for search, chunked for retrieval or inspected by an assistant without first pretending that a webpage is a screenshot. AI is not the reason to adopt content as code. It merely exposes how wasteful our existing content architecture has become.

For European institutions and governments, the argument is also political. The European Union's Open Source Strategy places open source at the center of technological sovereignty, linking it to reduced dependence on non-European proprietary technology, greater control, interoperability, reusable public digital assets and public administrations acting as users and contributors. A government that stores public knowledge in open text formats and manages it with open version-control standards retains choices about hosting, suppliers, jurisdictions and future reuse. GitHub is not Git. An organization can use GitHub, GitLab, Forgejo, another provider or its own server. The repository can move. The files do not need permission from a foreign platform to remain files.

There is a cultural benefit that is harder to quantify and more important than another feature comparison. Content as code narrows the artificial distance between the business, content and technology. Writers learn that a page has source, metadata, dependencies and a publication history. Developers encounter content as a first-class part of the system rather than filler inserted after the component library is finished. Analysts can inspect the same material without requesting a special export. Designers can understand which variations are real and which were improvised through a rich-text field. The frontend and backend stop feeling like separate planets connected by tickets. Not everyone becomes a developer, but more people understand how the product actually works. Systems become durable when knowledge about them is distributed; they become sluggish when every ordinary change must cross a professional border.

The strongest objection is real: Git can be unpleasant. Its terminology is historically accreted, merge conflicts are intimidating, command-line errors have the bedside manner of a disappointed mathematician, and many content-as-code advocates explain the workflow with the serene confidence of people who have forgotten what rebase sounds like to a normal person. Real-time co-editing is often easier in Google Docs or Microsoft 365. Large media libraries, granular permissions, localization workflows and embargoes require deliberate design. A repository can become disorderly. Markdown can be abused. A bad information architecture remains bad when stored in beautifully versioned files. None of this should be waved away. Forcing every occasional editor into a terminal and calling the resulting frustration empowerment would reproduce the same mistake as the CMS, only with darker color schemes.

But that objection is an argument for better editorial interfaces, not for proprietary storage. The great design opportunity is to separate the editing experience from the canonical format. Give writers an Obsidian-like application, a browser editor, a form for metadata, a preview button, comments, permissions and a large reassuring Publish button. Hide commands where commands add no value. Keep the source visible when visibility teaches. Let a merge request be called a review if that helps. Allow teams to draft collaboratively in familiar tools when simultaneity matters, then move approved content into the repository. The non-negotiable point is that the GUI must write to open, inspectable files and preserve a standard history. Convenience should be replaceable. The content should not be.

Adoption does not require a constitutional convention. Begin with one durable section of a site: guidance, documentation, policy explanations, a knowledge base, project pages or long-lived campaign material. Store each page in Markdown with a small, strict metadata schema. Put the repository in Git. Add automated checks for links, headings, metadata and review dates. Generate a preview for every proposed change. Train editors in the handful of Git concepts they actually need. Keep transactional applications where transactions belong, but make their explanatory content linkable, testable and independent. After the first redesign, the benefit becomes obvious: the frontend can be replaced while the content remains. After the first bulk correction, the benefit becomes embarrassing: a script changes in minutes what the old system turned into weeks of coordinated clicking.

Years after that first writer changed the date, the organization will redesign the website again. The current CMS will have become a legacy platform, as current platforms reliably do. The design system will look dated. A vendor will propose a migration assessment. In the content-as-code version of this future, someone opens the repository, reads the files, changes the templates and builds the new site. The old interface can disappear without taking the institution's memory with it. Somewhere in the source, the date is still twelve characters long. It is still legible. It is still waiting to be changed.

Next article

Next article

All articles

The Internet Is About to Lose Its Memory