Building a CMS Around Markdown Instead of a Database
Most CMS platforms start with a database. Ink starts with a folder of Markdown files. Here's why that changes everything.
The usual CMS architecture
Every mainstream CMS follows the same pattern: content goes into a database, an admin panel provides the editing UI, a template engine pulls data at request time (or build time, if you're lucky), and the result is served to visitors. WordPress, Ghost, Strapi, Payload — the stack varies, but the flow is the same.
This architecture makes sense when you need dynamic content, user accounts, real-time collaboration, or complex access control. But for the vast majority of sites I've built over the past decade — small business marketing sites, portfolios, documentation, personal blogs — none of that is necessary. The database is overhead that delivers no value.
What you actually need
Most sites need exactly this:
- A way to write content with structure (headings, images, metadata)
- A way to organize that content into types (blog posts, services, team members)
- A design system that applies consistently
- A build step that turns it all into HTML
- A place to host it
That's it. You don't need a login page. You don't need a rich text editor. You don't need MySQL. You need a text editor and a build tool.
Starting with files
Ink flips the CMS model. Content is Markdown files with YAML frontmatter:
---
title: "Building Better Websites"
date: 2026-02-24
author: "Nick McInnis"
excerpt: "A short description for the archive page."
published: true
---
The actual content goes here, written in Markdown.
These files live in directories organized by type — content/blog/, content/services/, content/docs/. A JSON file (contentTypes.json) maps each directory to an Eleventy collection. The build system reads the directories, applies layouts, and outputs static HTML.
There's no schema migration. No ORM. No query language. You want a new field? Add it to the frontmatter. You want a new content type? Run ink add portfolio and the CLI creates the directory, frontmatter template, layout, and archive page.
What you gain
Version control is free. Every edit is a Git commit. You get full history, branching, and rollback without any CMS plugin. Your "database backup" is git push.
Content is portable. If you want to switch tools, your content is already in a universally readable format. No export step. No proprietary JSON blobs. Just .md files.
Performance is trivial. Static HTML served from a CDN loads in milliseconds. No cold starts, no database connections, no caching layer to configure. The hosting cost for most Ink sites is zero.
The editing experience is your choice. Use VS Code, Vim, or Obsidian — Ink's content directory works as an Obsidian vault out of the box. You're not locked into a browser-based editor.
Security surface is minimal. No admin panel means no admin panel to exploit. No database means no SQL injection. No server-side code means no server to patch.
What you give up
Honesty matters here. Ink is not for everyone.
No real-time collaboration. Two people can't edit the same post simultaneously (though Git handles merge conflicts). If your team needs Google Docs-style collaboration, use a different tool.
No non-technical editing. You need to be comfortable with a text editor and a terminal, or at least willing to learn. The desktop app lowers this bar, but it's not WordPress's admin panel.
No dynamic content. Comments, user accounts, search — anything that requires server-side processing needs an external service. Ink sites are static by design.
No visual page builder. You're working with templates and components, not dragging blocks around. The design token system makes styling flexible, but it's CSS variables, not a GUI.
For the sites I typically build, these tradeoffs are worth it. The simplicity payoff is enormous.
The CLI as the interface
Instead of an admin panel, Ink has a CLI. The commands map directly to what you'd do in a CMS dashboard:
ink init my-site # "Create new site"
ink add blog # "Enable blog section"
ink add blog "My First Post" # "New blog post"
ink add component pricing # "Add pricing table"
ink serve # "Preview"
ink build # "Publish"
Each command generates files with the correct structure. ink add blog "My First Post" creates content/blog/my-first-post.md with the full frontmatter schema pre-filled. You open it, write your content, and build. No guessing what fields are available or how the file should be named.
Design tokens over themes
Traditional CMS themes are monolithic. You install one, customize it within its constraints, and hope the next update doesn't break your changes.
Ink uses a design token system — a single CSS file with custom properties that control the entire visual identity:
:root {
--color-primary: #2563eb;
--color-background: #ffffff;
--font-body: 'Inter', sans-serif;
--font-heading: 'Inter', sans-serif;
--spacing-md: 1.5rem;
--radius-default: 0.5rem;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
}
Change --color-primary and every button, link, and accent color updates. Change --font-body and every paragraph follows. The components reference these tokens, so the design stays consistent regardless of which components you use.
This isn't a new idea — design systems have worked this way for years. But most CMS platforms bury this behind a theme settings page. In Ink, it's one file you can read in five seconds.
Where this is going
The CLI and starter template are stable. The desktop app — an Electron editor with live preview, media management, Git integration, and an AI writing assistant — is in alpha. It's the piece that bridges the gap between "developer tool" and "anyone can use this."
The goal is a tool that's simple enough for a freelancer to hand off to a client, powerful enough for a developer to extend without fighting the framework, and portable enough that nobody gets locked in.
Ink is open source on GitHub.