Cherry and NimblePublisher
"Should I use Cherry or NimblePublisher?" is a reasonable question with a slightly unreasonable premise, because they are barely the same species. NimblePublisher is a small, sharp library that turns markdown files into in-memory Elixir structs at compile time. Cherry is a static site generator that emits a deployable tree of files. One gives you data, the other gives you a website. This post draws the line properly, because on the right side of it each tool is clearly the better choice.
What NimblePublisher is
NimblePublisher, from Dashbit, is about a hundred lines of very good taste. You point it at a glob of markdown files, each opening with an Elixir map literal as frontmatter, and at compile time it parses them and hands your module the result:
use NimblePublisher,
build: Post,
from: "posts/**/*.md",
as: :posts
After that, @posts is a list of %Post{} structs, inside your
application, with zero runtime cost. Everything else is yours to build:
routing, layouts, RSS, SEO tags, search, deployment. In practice that
means it lives inside a Phoenix application that already exists, where
posts become one more data source your controllers and LiveViews render
like anything else.
That design has real virtues. There is no second artifact to deploy: the blog ships inside the app you were already shipping. Content sits next to code in the same repository and the same review flow. And because posts are just structs, anything dynamic is trivial, from related-post queries to rendering inside a LiveView.
What Cherry is
Cherry starts where NimblePublisher stops, because the pipeline is the
product. Typed frontmatter where an unknown field is a build error with a
file and line, not a silent nil. Themes with tokens as the styling API,
overlays that carry provenance, and upgrades that merge instead of
freezing. Search without Node, feeds, sitemaps, and the machine surface
(llms.txt, markdown mirrors of every page) generated from the same
content pass as the HTML so nothing can drift. A verifier that returns
structured diagnostics. Deterministic builds, gated in CI. And the output
is a _site/ directory any static host serves, deployed by the workflow
cherry gen.action writes for you.
The deeper difference is who can operate it. NimblePublisher assumes an
Elixir developer with a compiler at hand, because publishing means
recompiling an application. Cherry ships as a standalone binary with a
CLI, so the loop runs without Elixir installed, and every verb takes
--json:
$ cherry version
cherry 0.3.0 (cb4bad2)
That is what makes the whole site operable by an agent as well as a human, which is a design goal here, not a side effect.
The comparison, honestly
| NimblePublisher | Cherry | |
|---|---|---|
| What it is | Compile-time content library | Static site generator and CLI |
| Output | Elixir structs in your app | A _site/ static tree |
| Needs your own app | Yes, in practice | No |
| Layouts, feeds, SEO, search | You write them | Built in, themed |
| Content validation | Whatever you code | Schema-enforced diagnostics |
| Publishing | Redeploy the application | Rebuild, push static files |
| Non-Elixir operators, agents | No | Binary plus --json envelopes |
Could you build a Cherry-shaped tool on top of NimblePublisher as the parsing layer? Roughly, yes. Cherry owns its pipeline instead, and the reason is the compile-time embedding itself: it is NimblePublisher's defining feature and exactly what a static site generator does not want. Content changes should not mean recompiling an application, and a binary user has no compiler at all.
Which one you want
If you already run a Phoenix application and want five posts living inside it, use NimblePublisher. It is lighter, the posts deploy with the app, and anything dynamic comes free. Reaching for a whole site generator there would be carrying a second artifact for no reason.
Cherry earns its keep when the site is the product: a blog, a portfolio, documentation, anything that should be standalone, themed, verified, served from a CDN, and runnable end to end by someone (or something) that never opens an editor. This site is the standing example, and every page of it is also plain markdown, which is the kind of thing you get to promise when the generator owns the whole pipeline.
Two good tools. The line between them is just the question "is the site inside your app, or is the site the app?"