I prefer Djot over Markdown

Why Djot?

Markdown is very useful, widely adopted and at a first glance simple. But the simplicity falls apart when you look at edge cases, compatibility across applications and non-basic features. And despite the heroic effort of CommonMark, the fragmentation seems to grow with more dialects and extensions rather than consolidating. Even strict adherence to CommonMark would leave us with a spec that is large and hard to understand and implement due to the focus on codifying the markup as it was used, rather than prescribing something that is internally consistent.

This is where Djot[1] comes in, designed for conceptual clarity from the start. As we’ve learned in the “Standards” xkcd[2], it won’t replace the existing Markdown dialects, but it provides a sane alternative that I would like to see more widely adopted. In my opinion it is better suited than most other competitors:

1: Djot

2: “Standards” xkcd

=> https://johnmacfarlane.net/ 1: John MacFarlane

What do I do about it?

If I want others to use it, then I should start working with it myself. Here’s what I’ve done so far:

Switched my blog[1] to use Djot

I must admit that Markdown worked quite well for my blog, so this is more to get some experience with Djot and promote its usage rather than a big technical advantage. But I did notice some improvements due to the change:

=> https://geminiprotocol.net/docs/gemtext-specification.gmi 1: gemtext

=> https://github.com/karlb/md2gemini 2: md2gemini

=> https://github.com/karlb/gemtext.lua 3: gemtext.lua

=> https://pandoc.org/ 4: pandoc

=> gemini-blog.html 5: Gemini blog post

The conversion was small. The posts ended up at roughly the same length, with about 15 lines of syntax differences across all of them. The toolchain switch[1] was mostly trivial (renaming .md to .dj, swapping smu for cdjot). Only dropping the perl preprocessor from the GEMINI() function was a real simplification.

1: toolchain switch

Pandoc is a heavy dependency, but it is only required for the Gemini protocol output and I might replace it with something lightweight later (I did a minipandoc experiment[1], but that’s out of scope for this post). And pandoc is great.

1: minipandoc experiment

Created cdjot[1], a Djot->HTML converter

There was no C implementation to convert from Djot to HTML and I wanted to find out how hard it would be to create a simple dependency-free version in the style of a suckless[1] project. It turned out to be easy (with LLM help, which admittedly is not at all suckless-style) and resulted in a lightweight and fast[2] converter. I like it enough that I’ll probably maintain this instead of smu[3] and enjoy the benefits of a good spec and a more comprehensive test suite.

1: suckless

2: fast

3: smu

Upstreamed contributions

I contributed test cases[1] (maybe more to come[2]) and a footnote-reference fix[3] to djot.js. I added an autolink rendering fix[4] and a CI fix[5] to djot.lua, and a heading auto-ID clarification suggestion[6] to the spec.

1: test cases

2: more to come

3: footnote-reference fix

4: autolink rendering fix

5: CI fix

6: heading auto-ID clarification suggestion

None of these were big problems and I consider it a good sign that I could contribute these as someone new to the ecosystem. That shows both that it is easy enough to understand that I feel capable of doing it and that it is maintained well enough to get them accepted.

Why you might not like Djot

Try it yourself

If you’d like to try Djot, start with the syntax reference[1] and the quickstart for Markdown users[2], convert an existing Markdown file with pandoc[3] (pandoc -f markdown -t djot input.md -o output.dj), or experiment in the playground[4].

1: syntax reference

2: quickstart for Markdown users

3: pandoc

4: playground

Written on 2026-05-14.

Proxied content from gemini://gmi.karl.berlin/djot.gmi (external content)

Gemini request details:

Original URL
gemini://gmi.karl.berlin/djot.gmi
Status code
Success
Meta
text/gemini
Proxied by
kineto

Be advised that no attempt was made to verify the remote SSL certificate.