Docs

Darkmown is a Markdown-native framework for mostly-static sites with tiny reactive islands. Pages are plain files: .md stays pure CommonMark, and .wd ("whateverdown") is the same Markdown plus first-party directives.

Relative include: this hidden block lives beside the docs page as -relative-note.wd, so it can be included without becoming a route.

Install

npx @zvndev/darkmown init my-site
cd my-site
npm install
npm run dev

Or add Darkmown to an existing project with npm install -D @zvndev/darkmown. The package is scoped; the command it installs is plain darkmown.

The two formats

Routing rules

Includes

Loops

@loop <things> into <thing> is the only loop. The body is normal Markdown (or more directives) and repeats once per row:

@loop /features.json into card
@include /feature-card.wd
@endloop

The source decides how the loop behaves:

Loops nest, and { card.title } style dotted paths reach into each row.

Interpolation

One syntax everywhere: { name } or { name.path }.

Sections

::: section #id .class opens a container and ::: closes it. Sections scope state: a :state declared inside a section belongs to that section, so two sections can both declare count without colliding. Bindings and buttons resolve to the nearest scope.

Reactive directives

Reactive pages opt into /__wd/runtime.js (~2 KB gzipped, under a CI-enforced 5 KB budget). Static pages do not.

:state count = 0

The count is { count }.

:button "Increment" -> count++

:if count
Count has changed.
:else
Count is still zero.
:endif

:state todos = [{"id": 1, "title": "Route pages"}]

@loop todos into todo
- { todo.title }
@endloop

:button "Add" -> todos += {"id": 2, "title": "Live compile"}

Directive actions are intentionally narrow and compile-time checked. Arbitrary JavaScript belongs in a colocated .js file.

Data, forms, and persistence

See it all live on the Data & Forms page.

Colocation

Spec status

The implementation is faithful to the original core thesis: Markdown-first authoring, no component ceremony, zero runtime on static pages, and tiny direct-DOM reactivity only when declared. :fetch, :form (including server round-trips), :computed, and persist are all shipped and live — try them on the Data & Forms page. Still on the roadmap: a first-party server runtime (site/api/), HTML-fragment swaps, and nested :if over loop items. See docs/spec-alignment.md in the package for the full audit.