I did not write a Markdown parser. Michel Fortin and Waylan Limberg wrote one. It is called Python-Markdown. It has been maintained since 2004. It handles fenced code blocks, tables, table of contents, smart quotes, and attribute lists. It does its job.
I did not write a frontmatter extractor. Bob Gilmore wrote one. It is called python-frontmatter. It parses YAML metadata from Markdown files. It does its job.
I did not write a slug generator. Val Neekman wrote one. It is called python-slugify. It turns titles into URL-safe strings. It does its job.
I did not write a template engine. Armin Ronacher wrote one. It is called Jinja2. It has been rendering HTML since 2008. It outlived the framework that made it famous. It does its job.
I did not write a web framework. Sebastian Ramirez wrote one. It is called FastAPI. It is async, typed, and gets out of the way. It does its job.
I did not write a database driver. Denis Vasilev and the psycopg team wrote one. It talks to PostgreSQL without prepared statement complications. It does its job.
I did not write an HTTP client. Tom Christie wrote one. It is called httpx. It pushes HTML to GitHub Pages. It does its job.
Seven libraries. Seven maintainers. Seven people who released their work under permissive licenses with conviction. Each library does one thing, does it well, and does not care what calls it.
I gathered them behind four HTTP endpoints and pointed them at a specific problem: turning a note into a blog post without opening a browser.
That is the entire innovation. Composition. Not invention.
The 242 Megabyte Thesis
The Docker image that contains the complete note2cms publishing system – API, build pipeline, taxonomy database, deployment engine, eight visual themes – weighs 242 megabytes.
WordPress with its runtime weighs over a gigabyte. Ghost weighs over 600 megabytes. A Next.js deployment with a headless CMS adapter weighs 400 megabytes or more.
The difference is not optimization. The difference is that note2cms contains only what is needed: a language runtime and seven libraries. No ORM. No admin panel framework. No plugin system. No media library. No authentication cascade. No session management. No cron daemon. No background workers.
Everything that is not in the image is a feature, not a limitation.
Python Is Not Slow
Python is slow at serving web pages in real time. This is true. A PHP worker or a Go binary will serve a dynamic request faster than a Python process.
Python is not slow at transforming Markdown into HTML once and writing the result to a file. This operation takes milliseconds. It happens once per publish. The reader never sees it. The reader sees static HTML on a CDN, which is served at the speed of light minus network latency.
The “Python is slow” argument benchmarks the factory. The customer never visits the factory. The customer visits the store, where the product is already on the shelf. The speed of the factory is irrelevant when the factory only runs a few times a week.
Python is the best language for this job not because it is fast but because it is the best language for working with data. Markdown is data. Frontmatter is data. Taxonomy is data. Templates are data transformations. The pipeline is a data pipeline. Python was built for this.
The output – static HTML served from a CDN – is faster than any dynamically rendered page in any language. Not because Python is fast. Because the architecture eliminated the need for speed.
The Composition Thesis
Every component in note2cms existed before note2cms. The Markdown parser, the frontmatter extractor, the slug generator, the template engine, the web framework, the database driver, the HTTP client. Seven tools, each maintained by someone else, each battle-tested by millions of users.
The innovation is not in any component. It is in the composition. It is in seeing that these seven things, arranged in a specific order behind four HTTP endpoints, eliminate an entire category of unnecessary infrastructure.
This is not a new idea. Unix was built on the same principle – small tools that do one thing, connected by pipes. The cathedral-and-bazaar debate was about whether this principle could scale to large projects. FastAPI was built on the principle that the framework should compose, not contain.
What is new is applying the composition principle to an industry that forgot it. The web publishing industry built monoliths. CMS platforms that contain their own template engines, their own ORMs, their own authentication systems, their own media libraries, their own plugin architectures. They rebuilt inside their walls what already existed outside them – and then charged for the maintenance of the duplication.
note2cms contains nothing that was built for note2cms. Every component is a general-purpose library that happens to be pointed at a publishing problem. If any library is abandoned, it can be replaced with another library that does the same job. If Python itself falls out of favor, the entire pipeline can be rewritten in another language – because the logic is trivial and the architecture is documented in a protocol spec.
The components are replaceable. The composition is the contribution.
I did not invent anything. I composed everything. The composition is the contribution.