2026 · EngineeringAbout 13 min readNovus Stream Solutions
Code-as-content: why our blog is hundreds of TypeScript objects, not a CMS
novusstreamsolutions.com runs no CMS and no database. Every blog post and doc is a typed TypeScript object compiled into the site. Here is why a solo operation chose code-as-content, what it buys, and the real tradeoffs.
Overview
The conventional way to run a content-heavy site is to stand up a content management system: a database, an admin interface, an API the front end calls at request time to fetch posts. It is the default for good reasons — non-technical editors can publish without touching code, and the content lives independently of the application. We went the other way entirely. novusstreamsolutions.com has no CMS and no database behind its blog or its docs. Every post is a typed TypeScript object that lives in the repository and is compiled into the site at build time. The blog you are reading is, quite literally, source code. This post is about why a solo operation made that choice, what it actually buys, and where it would be the wrong call.
The shorthand for the approach is "content-as-code": treat articles and documentation as first-class source files, version-controlled alongside the application, type-checked by the compiler, and deployed in the same pipeline as the code. It is an unusual choice in 2026, and it is a deliberate one. The benefits are not abstract — they fall directly out of the fact that the content is subject to the same tooling as the code, which turns a whole category of content problems into problems the build catches before anyone sees them.
What "no CMS, no database" actually means here
Concretely, the posts live in a set of TypeScript files in the repository — the product posts in one module, the field-notes collections in others — each exporting plain objects that conform to a shared type. There is no admin panel to log into, no database to query, no content API to call. When a post is added, it is added as code: a new object in a file, committed to version control. When the site builds, those objects are compiled into static pages. At request time there is no database round-trip to fetch the article, because the article was baked into the page when the site was built. The content and the code are one artifact.
That single fact — content compiled in rather than fetched at runtime — is the root of most of the advantages. It means the site has no content database to provision, secure, back up, scale, or pay for. It means there is no class of "the CMS is down so the blog is down" incident, because there is no separate CMS to be down. It means a post cannot be in an inconsistent state between the database and the code, because there is no separation between them. The architecture removes an entire moving part, and removing moving parts is the single highest-leverage thing a small operation can do for its own reliability.
The compiler is your editor
The most valuable benefit is that the TypeScript compiler reviews every post before it can ship. Because each post is a typed object, the compiler enforces that it has every required field — a slug, a title, a date, an excerpt, the structured body — and that every field has the right shape. A post missing a title does not render with a blank heading; it fails to compile. A post that links to a documentation page that does not exist is caught, because the field that holds that link is constrained to the set of pages that actually exist. The build is a gate that a malformed post cannot pass through, which means the failure modes that plague CMS-driven sites — published-but-broken pages, missing fields, dangling references — are largely designed out of existence.
This inverts the usual relationship between content and quality control. In a CMS, validation is something you have to build and maintain on top of the content system, and it is usually partial. In a code-as-content setup, validation is the type system you are already using for the application, applied to content for free. The same compiler that stops you from passing a string where a number belongs stops you from publishing a post without a date. You do not write that validation; you inherit it. For a solo operation with no editorial staff to catch mistakes, having the compiler act as the copy-desk-for-structure is a genuine multiplier.
Content gets the whole engineering toolchain
Because the content is code, it gets every tool that code gets, at no extra cost. It lives in version control, so every edit has a full history, every change is attributable, and reverting a bad edit is a routine operation rather than a database restore. It goes through the same review and deploy pipeline as the application, so a content change can be previewed on a real URL before it goes live and rolled back the same way a code change would be. It can be searched, refactored, and edited with the same editor and the same find-and-replace as the code — renaming a product across two hundred posts is a single operation, not two hundred manual edits in an admin panel. None of these are capabilities you have to add; they come from the content being in the repository.
There is a real compounding effect to this. Cross-linking posts, restructuring a topic cluster, fixing a recurring phrasing issue, updating a fact that appears in many places — all of these are mechanical operations on text files, which means they are fast, scriptable, and safe under version control. A CMS makes each of these a manual, per-item chore through a web interface. The code-as-content site treats them as what they are: edits to source, with all the leverage that implies. For a content property that is meant to grow into a dense, interlinked hub, that editing leverage is not a nicety; it is what makes maintaining the density sustainable.
Version history as an editorial record
A benefit of content living in version control that is easy to undervalue is that the entire editorial history comes for free and is genuinely useful. Every edit to every post is a commit, with a timestamp, an author, and a diff showing exactly what changed, which means the question "when did this fact change and what did it say before" is answerable by looking at the history rather than by hoping someone remembers. For a content property that makes factual claims about products, having an auditable record of every change to every claim is not just tidy; it is a form of accountability that a typical CMS, which often overwrites content in place, does not provide by default.
This editorial record also makes correcting and reverting safe operations rather than anxious ones. If an edit introduces an error, the previous version is right there in the history and reverting it is a routine operation, not a scramble to reconstruct what the text used to say. The same diffing that lets a developer review a code change lets the maintainer review a content change — seeing precisely what words were altered, added, or removed before it ships. For a solo operator with no separate editorial oversight, the version history is the oversight: a complete, reliable record of how the content evolved, with the ability to inspect any past state and return to it, which is a level of editorial control that comes automatically from treating content as code.
Refactoring prose like you refactor code
Because the content is text files in a repository, it is subject to the same bulk-editing and refactoring tools as code, which transforms what would be tedious manual chores into fast, safe operations. Renaming a product across hundreds of posts is a find-and-replace, not hundreds of trips through an admin interface. Updating a recurring phrasing, fixing a fact that appears in many places, or restructuring how a topic is cross-linked are all mechanical operations on text, performed with an editor's full power and verified by the build and version control. The leverage that developers take for granted when changing code applies directly to changing content, because the content is code.
This editing leverage is what makes maintaining a dense, interlinked content hub sustainable for one person rather than a slowly accumulating mess. A CMS makes each cross-cutting content change a per-item manual task, so the cost of maintaining consistency grows with the number of items until it becomes prohibitive and consistency quietly erodes. The code-as-content site treats those same changes as edits to source — scriptable, reviewable, reversible — so consistency across a large body of posts is maintainable rather than aspirational. For a content property designed to grow into hundreds of interlinked pages, the ability to refactor the whole corpus with code tools is not a minor convenience; it is what keeps the growing body of content coherent without a growing maintenance team.
Why static beats a runtime fetch for content
The decision to compile content into static pages rather than fetch it from a database at request time has consequences beyond removing the database, and they favor static for a content property specifically. A statically compiled page has no per-request data fetch, so it cannot be slow because the database is slow, cannot fail because the database is down, and cannot serve a half-loaded state — the page is fully formed at build time and served as-is. For content that does not change between builds, which is exactly what blog posts and docs are, paying a per-request cost to fetch unchanging data from a database is pure overhead that the static model eliminates entirely.
This also collapses a class of reliability concerns that runtime-fetched content carries. A CMS-driven site has a live dependency on its content backend for every page view, which means the content system's uptime, latency, and capacity all become the site's problem at request time. A statically compiled site has no such dependency: the content was resolved when the site was built, so serving it is just serving static files, which is about the most reliable and fastest thing a web server can do. For content that updates on the order of new posts rather than per-second changes, the static model matches the actual update frequency and removes the runtime machinery entirely, which is both faster for readers and far simpler to operate. Static is not a compromise for content; it is the better fit for how content actually changes.
Publishing is a commit, with all that implies
In a code-as-content setup, publishing a post is making a commit, and that framing carries more benefit than it first appears, because everything good about a commit-based workflow now applies to content. A new post goes through the same path as a code change: it can be developed on a branch, previewed as a real deployment before going live, reviewed as a diff, and merged when it is ready. There is no separate publishing concept to build or maintain — the publishing workflow is the development workflow, which the operator already has and already understands. The act of publishing inherits the safety and structure of shipping code.
This unification is a simplification rather than a complication for a technical operator. Instead of a content workflow and a code workflow that are separate systems with separate states, there is one workflow that handles both, which means one mental model, one set of tools, and one place where everything that ships is reviewed and recorded. A typo fix and a feature change are the same kind of operation; a new article and a new page are shipped the same way. For a solo operator who is already living in the commit-preview-promote loop for code, having content ride that same loop means publishing is not a context switch into a different system but a familiar action in a familiar workflow, which is exactly the kind of friction reduction that keeps a content cadence sustainable.
Why AI assistance fits content-as-code
A modern advantage of treating content as typed code is that AI-assisted development tools, which operate on a codebase, can assist with content the same way they assist with code, because the content is in the codebase. An agentic coding tool can be asked to draft a post conforming to the post type, to add a section across several posts, to refactor phrasing consistently, or to cross-link a cluster — all as operations on typed source files, with the type system catching anything malformed. The content being code means the same leverage that AI brings to writing and editing code applies directly to writing and editing content, which is a meaningful multiplier for a solo operator producing a lot of it.
This synergy is becoming more relevant as AI-assisted workflows mature, and it favors the content-as-code model specifically. Content trapped in a separate CMS is opaque to a coding assistant working on the application; content that lives as typed objects in the repository is directly accessible to the same tools, with the same review discipline applied to the output. The compiler still gates everything — an AI-drafted post that omits a required field or references a nonexistent doc fails the build just as a hand-written one would — so the type safety that protects against human mistakes protects against AI mistakes too. For an operation that uses AI assistance to move quickly, having content live where those tools can reach it, under the same guardrails as the code, is an increasingly valuable property of the architecture.
Plain data is portable data
A quieter long-term benefit of storing content as plain typed objects is portability: the content is just structured data, not entries locked inside a particular CMS's database and accessible only through that CMS's interfaces. Structured objects in source files can be read, transformed, migrated, or repurposed by any code, which means the content is not hostage to a single platform's continued existence or export capabilities. If the rendering approach ever needed to change, the content — being plain data with a known shape — would come along, because it is not entangled with the presentation system the way CMS content often is with its platform.
This portability is a hedge against a real risk that CMS-based content carries: lock-in to a platform that might change its pricing, deprecate features, or shut down, taking the convenient access to your content with it. Content as plain structured data has no such dependency — it is yours, in your repository, in a format any code can read, independent of any vendor. For a content property meant to be a durable, long-lived asset, that independence matters: the value accumulated in hundreds of posts stays accessible and transformable regardless of platform decisions, because it was never inside a platform to begin with. Plain, typed, version-controlled data is about as portable and durable a way to hold content as exists, which is a sound foundation for an asset intended to compound over years.
The honest tradeoffs
Code-as-content is not the right answer for everyone, and being clear about when it is wrong is part of taking it seriously. The biggest tradeoff is that publishing requires touching code and running a build. For a team with non-technical editors who need to publish independently, that is a dealbreaker — a CMS exists precisely so that a marketer can publish without a developer, and no amount of type safety replaces that. The approach also means there is no live editing: you cannot tweak a typo through a web UI and have it appear instantly; you commit a change and the site rebuilds. And it scales with build time rather than database queries, so a site with hundreds of thousands of posts would eventually find the all-at-build-time model strained in a way a runtime-fetched CMS would not.
The reason the tradeoff lands in favor of code-as-content here is the specific situation: a solo, technical operator running a content property in the hundreds-of-posts range, who is already in the codebase daily and for whom "publishing is a commit" is a feature rather than a barrier. In that situation, the things a CMS buys — independent non-technical publishing, live editing, runtime content — are things this operator does not need, while the things code-as-content buys — type-checked content, version control, no database to run, full editing leverage — are exactly the things that make a one-person content operation maintainable. The right architecture is the one that matches who is actually running it, and for this operation, the content is code because the person maintaining it is the person who writes the code.