I maintain a handful of small Python libraries. None of them is big, but every one of them needs documentation: how to install it, a quick start, a few guides, the options. And every time, setting up the docs took longer than it should.
Why I built it
The tools I tried are good, but none of them fit a small library:
-
Sphinx is powerful and made for large projects. For a library with ten pages, I spent more time on
conf.py, extensions and reStructuredText than on the docs themselves. - MkDocs comes closest, and most projects use it with Material for MkDocs. It is a great, complete theme, but this one is personal: the Material look never did it for me. I wanted something quieter and cleaner.
- Docusaurus, Starlight and VitePress produce beautiful sites, but they bring a JavaScript toolchain into a Python project, just for the docs.
What I wanted was simple: pip install one thing, write Markdown in a docs/ folder, push, and get a site that looks good and has search and dark mode, without assembling anything. I also wanted a tool small enough that I could read all of it.
That became dokk.
It is about 2,000 lines of Python code. You give it a folder of Markdown and it writes plain HTML: a sidebar from your folders, search, dark mode, code highlighting and a set of components, all at build time. There are no plugins to choose and nothing to configure before the first page works.
It is deliberately not everything. dokk does not generate API docs from docstrings, and there is no plugin system. If you need those, Sphinx and MkDocs are still the right tools. If you want good-looking docs for a small project in ten minutes, read on.
Tutorial: docs for a small library
We will add docs to a small, made-up library called slugkit, which turns text into URL slugs. Use your own project instead: the steps are the same.
1. Install dokk
pip install "dokk[serve,search]"
serve adds the dev server with live reload, search adds full-text search (Pagefind). Both are optional; plain pip install dokk builds sites without them.
2. Create the site
In the root of your repository:
dokk init
This creates four things:
dokk.toml title and settings
docs/index.md the home page
.gitignore .dokk/ added (the build output)
.github/workflows/docs.yml publishes the site to GitHub Pages
init never overwrites your files; an existing .gitignore only gets the .dokk/ line added.
3. Start writing
dokk serve
Open http://127.0.0.1:8002/ and edit docs/index.md. The page reloads every time you save.
4. Add pages and folders
Every .md file is a page, and every folder becomes a group in the sidebar. For slugkit:
docs/
index.md
getting-started/
index.md
guides/
unicode.md
reference/
api.md
A page's title comes from its first # Heading, or from front matter, where you can also set its place in the sidebar:
---
title: "Getting started"
sidebar:
order: 1
---
Links between pages are plain relative Markdown links, such as [the guides](../guides/unicode.md). dokk turns them into the right URLs, and tells you when one is broken.
5. Use components
Components are short Markdown blocks, so your docs stay readable on GitHub and in any editor. The getting-started page of slugkit uses three of them:
::install[slugkit]
:::steps
1. Install slugkit.
2. Import it: `from slugkit import slugify`.
3. Call `slugify("Hello World")`.
:::
:::tip
Next, read the [guides](../guides/unicode.md).
:::
::install shows the pip, uv and poetry commands as tabs, and remembers which one the reader picked across the whole site. There are also tabs, cards, callouts, file trees, badges, images, and components for AI projects such as model cards, chats and tool schemas. The components guide shows them all.
6. Check before you publish
dokk check
This builds the site and reports broken links, missing anchors and pages without a title, each with the file it is in. It is also the first step of the GitHub workflow, so a broken link never reaches your live docs.
7. Configure the site
dokk.toml needs only a title. A few more lines make it yours:
title = "slugkit"
site_url = "https://you.github.io/slugkit/"
[theme]
color = "blue"
[links]
github = "https://github.com/you/slugkit"
edit_url = "https://github.com/you/slugkit/edit/main/docs/{path}"
site_url gives you a sitemap and correct links on GitHub Pages. color picks one of the shadcn/ui accent colors; try them all on the theme showcase. The links add a GitHub icon in the header and an "Edit this page" link under every page.
8. Publish
Push to GitHub, then go to Settings → Pages and set Source to GitHub Actions. The workflow from dokk init builds the site on every push to main and publishes it. That's it: your docs are live.
Optional: keep your Markdown tidy
dokk format formats every page, so lists, tables and spacing look the same everywhere. It knows dokk's Markdown, so your components, front matter and tables stay intact:
pip install "dokk[format]"
dokk format
dokk format --check changes nothing and fails when a page is not formatted, which makes it a good fit for CI or a pre-commit hook. Under the hood it is mdformat with mdformat-directives, a plugin I wrote alongside dokk.
What you get
- A sidebar from your folders, or arranged by hand in
dokk.toml. - Search, dark mode and code highlighting, with no JavaScript framework.
- Plain HTML with every asset bundled: no CDN, no tracking. It works on any static host.
- A Markdown copy of every page and an optional
llms.txt, so AI tools can read your docs too. - Fast builds: a thousand pages in about a second and a half.
Links
- Documentation, built with dokk itself
- Quick start
- Components
- Example pages: a CLI tool, a library reference, a changelog, an FAQ and AI projects
- Theme showcase
- GitHub and PyPI
- Basecoat, the components and styles behind dokk's look
- Pagefind, the static search engine dokk uses
dokk is young, so I would love to hear how it works for your project. Open an issue on GitHub with what you miss or what got in your way, or send a pull request.
Top comments (0)