Skip to content

Darkmown vs. Markdoc

Markdoc is a good tool, and the closest thing to Darkmown in spirit: Markdown with first-party syntax instead of MDX's "Markdown plus JavaScript". If you are choosing between them, the difference is narrow and specific.

Markdoc renders content. Darkmown runs it. Markdoc has {% if %}, {% partial %} and $variables, so it can vary what it renders at build time. It has no loop tag, and no state, so the moment your page needs a filter, a cart, or a running total, you register a custom tag backed by a React component, ship React and a hydration runtime to the browser, and wire it up in your build. Darkmown expresses those in the Markdown file, and ships one 7,654-byte runtime.

The same store, both ways

store.wd (Darkmown)

:state products = [
  { "id": 1, "name": "Aurora Lamp", "price": 49 },
  { "id": 2, "name": "Briza Fan", "price": 39 }
]
:state cart = []
:state q = ""
:computed count = cart.length

:bind q placeholder="Search products…"

@loop products into p where p.name contains q
::: card .product
**{ p.name }** · ${ p.price }
:button "Add" -> cart += p
:::
@endloop

Cart: { count } item(s)

That is the whole file. It is running on the homepage: search, add to cart, and a live total.

store.md (Markdoc)

{% if $products %}
- **Aurora Lamp**, $49
- **Briza Fan**, $39
{% /if %}

There is no loop tag, so each row is written by hand and the list is static. To filter, add to a cart, or total it, you reach for code:

const tags = {
  store: { render: 'Store' }
};

// your filter + cart + total live here
Markdoc.renderers.react(content, React, {
  components: { Store }
});

…plus React and a hydration runtime shipped to the browser, and the build step that wires the tag to the component.

Where each one wins

Honest differences

Read the docs Try Darkmown in your browser