Ga naar inhoud

Inleiding

Wanneer een project wat groter wordt, volstaat een losse README.md meestal niet meer.

Je wil dan bijvoorbeeld documenteren:

  • hoe je het project lokaal opstart
  • welke omgevingsvariabelen nodig zijn
  • hoe gebruikers of collega-ontwikkelaars de API aanspreken
  • welke modules, classes en functies beschikbaar zijn
  • welke ontwerpkeuzes of beperkingen er zijn

Voor Python-projecten bestaan daar verschillende tools en stijlen voor. In deze les bekijken we kort het landschap, maar daarna focussen we volledig op MkDocs: een eenvoudige, moderne manier om projectdocumentatie als statische website te publiceren.

Waarom Documentatie?

Goede documentatie is geen luxe. Ze verlaagt de drempel voor nieuwe teamleden en/of gebruikers, maakt support eenvoudiger en zorgt dat je project later nog begrijpbaar blijft - ook voor jezelf!

Documentatie heeft meestal meerdere doelgroepen:

  • Gebruikers willen weten hoe ze iets installeren of gebruiken.
  • Developers willen weten hoe de code is opgebouwd en hoe je kan bijdragen.
  • API-clients willen weten welke endpoints bestaan en welk formaat de data heeft.
  • Je toekomstige zelf wil snel snappen waarom iets zo gebouwd is.

Note

Een documentatie website vervangt niet automatisch alle andere documentatievormen. Een README.md, inline comments, type hints, docstrings en OpenAPI-specificaties blijven allemaal noodzakelijk. Een site is eerder de plek waar die puzzelstukken samenkomen.

Goede Documentatie

Wat is nu goede documentatie? We bekijken als oefening een aantal voorbeelden voor projecten van verschillende omvang en doelgroep:

Python documentatie-landschap

Een korte situering

In het Python-ecosysteem kom je vaak deze opties tegen:

Sphinx Lang de standaard geweest en nog steeds gebruikt in veel projecten, waaronder Python zelf. Gebruikt ReStructuredText formaat. Veel extensies
MkDocs Erg populair bij moderne projecten. Markdown-first. Ook veel extensies.
pdoc Lichtgewicht tool om automatisch API-documentatie te genereren vanuit docstrings. Goed voor API-referentie voor kleinere bibliotheken.
pydoc Ingebouwde documentatietool van Python. Genereert eenvoudige HTML- of tekstdocumentatie vanuit docstrings zonder enige installatie. Handig voor snelle inspectie.

pydoc zit in Python zelf en is vooral handig om lokaal docstrings te bekijken. Test bvb. met het volgende commando:

uv run python -m pydoc -p 1234

Sphinx is lang de klassieke standaard geweest voor Python package-documentatie. Het is erg krachtig, maar ook wat zwaarder qua configuratie en terminologie. ReStructuredText is ondertussen qua populariteit volledige overtroffen door Markdown.

MkDocs heeft een andere insteek: schrijf gewone Markdown pagina's, configureer alles met een mkdocs.yml, en genereer een nette website. Zeker in moderne projecten is dat vaak een zeer aangename workflow.

Een gemeenschappelijk kenmerk van al deze opties is dat het zogenaamde Static Site Generators zijn.

  • Static Site: Betekent dat de website een vaste inhoud heeft en niet verandert. Er is bvb. geen database of andere dynamische databronnen aanwezig. Gebruikers kunnen niets veranderen. Er wordt doorgaans vooral HTML+CSS gebruikt en weinig Javascript.
  • Generator: De volledige website wordt in één keer gegenereerd. Ook na een aanpassing van de bronbestanden wordt de volledige site opnieuw gegenereerd.

Waarom focussen we op MkDocs?

Omdat MkDocs:

  • snel op te zetten is
  • Markdown gebruikt i.p.v. een complexer formaat
  • goed past bij moderne Python-projecten
  • vlot combineert met automatische documentatie uit code via mkdocstrings
  • met Material for MkDocs voor een moderne look-and-feel zorgt

Je ziet deze combinatie vaak terug bij populaire moderne projecten. Zeker Material for MkDocs is erg zichtbaar geworden in de Python-wereld, bvb. FastAPI, Pydantic, Textual of uv en ruff.

Eerste stappen met MkDocs

Setup

Veel projecten kiezen ervoor de documentatie samen met code van het project zelf te bewaren. We vertrekken dus vanuit een bestaand project naar keuze. Welk project maakt niet veel uit, maar bij voorkeur bevat het project een code-structuur met verschillende modules.

Voor de onderstaande voorbeelden vertrekken we vanuit de FlaskR applicatie (SQLAlchemy versie): https://github.com/dvx76/flask-tutorial/tree/sqlalchemy

1
2
3
git switch -c add-mkdocs
uv add --dev mkdocs~=1.6
uv run mkdocs new .

Het mkdocs new commando maakt de volgende structuur en bestanden aan:

  • docs/ - In deze directory zullen alle documentatiebestanden komen.
  • docs/index.md - Een initiële home-pagina.
  • mkdocs.yml - Het configuratiebestand voor mkdocs.

Documentatie Testen

Het mkdocs serve commando start een lokale webserver waar de gegenereerde documentatiepagina toegankelijk zijn. Pagina's worden automatisch ververst bij wijzigingen.

1
2
3
4
5
6
$ uv run mkdocs serve
INFO    -  Building documentation...
INFO    -  Cleaning site directory
INFO    -  Documentation built in 0.06 seconds
INFO    -  [10:31:29] Watching paths for changes: 'docs', 'mkdocs.yml'
INFO    -  [10:31:29] Serving on http://127.0.0.1:8000/

De eerste manier om een MkDocs website te gebruiken is via de navigatie-links in de informatiebalk bovenaan. Momenteel hebben we daar maar één link: "Welcome to MkDocs".

In deze balk komen automatisch links naar de Markdown bestanden die we in de docs/ directory plaatsen.

Voeg bijvoorbeeld een "about" pagina toe:

docs/about.md
1
2
3
# About FlaskR

FlaskR is a simple blog web applicatie written in Python and made with [Flask](https://flask.palletsprojects.com).

Sub-directories

Sub-directories binnen docs/ zorgen automatisch voor een overeenkomstige navigatie-hiërarchie.

Voeg bijvoorbeeld volgende directories en Markdown bestanden toe en bekijk het resultaat. Let ook op de resulterende URLs voor elke pagina.

docs/user-guide/
docs/user-guide/getting-started.md
docs/user-guide/installation.md
docs/user-guide/advanced/
docs/user-guide/advanced/tips.md

Wil je meer controle over de navigatie-bar en geen één-op-één mapping met de docs/ directory-structuur? Dan kan dit in detail geconfigureerd worden via nav in het mkdocs.yml bestand. Ook daar is het mogelijk om met een hiërarchische structuur te werken.

mkdocs.yml
1
2
3
4
5
6
7
8
site_name: FlaskR

nav:
  - Home: index.md
  - User Guide:
    - Getting Started: user-guide/getting-started.md
    - Installation: user-guide/installation.md
  - About: about.md

(We hebben hier ook tegelijk de naam van de site aangepast.)

Merk op dat er nu geen rechtstreekse navigatie is naar de docs/user-guide/advanced/tips.md pagina (ook al is deze wel rechtstreeks te bereiken via http://127.0.0.1:8000/user-guide/advanced/tips/). Het mkdocs commando geeft dit ook aan met de volgende output:

INFO    -  The following pages exist in the docs directory, but are not included in the
           "nav" configuration:
             - user-guide/advanced/tips.md

Markdown

We gaan er in deze les gemakshalve van uit dat je al bekend bent met Markdown. Ben je dat niet of wil je meer weten over (de evolutie van) Markdown, dan kunnen de volgende bronnen nuttig zijn.

De oorspronkelijke specificatie van John Gruber is een goed startpunt.

MkDocs gebruik python-markdown welk zo goed mogelijk de oorspronkelijke specificatie implementeert.

python-markdown bevat echter ook heel wat extensies (bvb. voor code highlighting) waardoor het nauw aansluit bij GitHub Flavored Markdown, of GFM en CommonMark.

Ten slotte is https://www.markdownguide.org ook een heel goede en complete referentie.

Andere Pagina's

Om naar een andere pagina te linken gebruik je een Markdown link naar het gewenste Markdown bestand. MkDocs zal dit automatisch omzetten naar een correct link in de gegenereerde HTML pagina's.

Let wel dat alle links relatief zijn ten opzichte van het huidig bestand. Om te linken naar een boven- of onder-liggende directory moet je hier dus rekening mee houden.

We passen als voorbeeld de bestaande home-pagina als volgt aan:

docs/index.md
1
2
3
4
5
6
7
# Welcome to FlaskR

## Getting Started
See [Getting Started](user-guide/getting-started.md).

## About
To learn more about this project visit the [About page](about.md).

Binnen de Pagina

Je kan linken naar een sectie (header) binnen de huidige pagina met #sectie-naam, bijvoorbeeld:

docs/index.md
1
2
3
4
5
6
7
8
9
# Welcome to FlaskR

## Getting Started
See [Getting Started](user-guide/getting-started.md).

Go to the [About section](#about).

## About
To learn more about this project visit the [About page](about.md).

Themes

In de theme setting van mkdocs.yml kan een alternatieve theme (en verwante configuratie) worden aangepast.

Standaard zijn twee themes beschikbaar: mkdocs (de default), en readthedocs. We passen de theme aan naar readthedocs. Het resultaat komt je mogelijks bekend voor.

mkdocs.yml
1
2
3
4
5
6
7
8
9
site_name: FlaskR
theme: readthedocs

nav:
  - Home: index.md
  - User Guide:
    - Getting Started: user-guide/getting-started.md
    - Installation: user-guide/installation.md
  - About: about.md

Verder in deze cursus bekijken we nog een ander alternatief.

Andere mkdocs.yml Opties

Op https://www.mkdocs.org/user-guide/configuration/ staan alle mogelijke opties uit mkdocs.yml uitgelegd. We bekijken hieronder een aantal veelgebruikte.

repo_url

Met repo_url krijgen we in de header balk een link naar de geconfigureerde repository. Hiermee kunnen we linken naar de broncode van het project (of van de documentatie). Bijvoorbeeld:

mkdocs.yml
1
2
3
site_name: FlaskR
theme: readthedocs
repo_url: https://github.com/dvx76/flask-tutorial

site_url

Met site_url geef je de basis URL voor de homepage van de website aan. Deze informatie komt terecht in de HTML head sectie van elke pagina en zorgt dat alle links correct zijn. Bijvoorbeeld:

mkdocs.yml
site_name: FlaskR
site_url: https://dvx76.github.io/flask-tutorial/

Merk op dat het pad (in dit voorbeeld docs/) ook wordt gebruikt door mkdocs serve.

site_author en site_description

Met deze settings geven we extra informatie over de site mee in the HTML header. Bijvoorbeeld:

mkdocs.yml
1
2
3
site_name: FlaskR
site_description: A simple blog app made with Flask
site_author: Fabrice Devaux

Voegt een copyright voetnoot toe op elke pagina. Bijvoorbeeld:

mkdocs.yml
1
2
3
4
site_name: FlaskR
site_description: A simple blog app made with Flask
site_author: Fabrice Devaux
copyright: Copyright © 2026 Fabrice Devaux

Website Bouwen voor Publicatie

Met mkdocs serve krijgen we een eenvoudige webserver met live preview. Handig tijdens de ontwikkeling maar niet bruikbaar om de uiteindelijke website te publiceren.

Met het commando mkdocs build zal mkdocs de volledige website genereren in een site/ directory (als HTML en aanverwante bestanden) - klaar om door een webserver aangeboden te worden.

1
2
3
4
5
6
7
8
$ uv run mkdocs build
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory:
           /Users/dfabrice/dev/github/flask-tutorial/site
INFO    -  The following pages exist in the docs directory, but are not included in the "nav"
           configuration:
             - user-guide/advanced/tips.md
INFO    -  Documentation built in 0.08 seconds

Als we de inhoud van site/ bekijken zien we voor elk oorspronkelijk Markdown bestand een overeenkomstige HTML pagina. Daarnaast hebben we nog een heleboel andere bestanden om de website te vervolledigen, zoals Javascript code (bvb. voor de zoekfunctie), CSS en fonts.

De site/ directory is nu klaar om aangeboden te worden voor een echte webserver (zoals bvb. Caddy, nginx or Apache) of web hosting platform (zoals bvb. GitHub Pages of Netlify). Verder in de cursus bekijken we GitHub Pages in meer detail.

$ tree site
site
├── 404.html
├── about
│   └── index.html
├── css
│   ├── fonts
│   │   ├── fontawesome-webfont.eot
│   │   ├── fontawesome-webfont.svg
│   │   ├── fontawesome-webfont.ttf
│   │   ├── ...
│   ├── theme_extra.css
│   └── theme.css
├── img
│   └── favicon.ico
├── index.html
├── js
│   ├── html5shiv.min.js
│   ├── jquery-3.6.0.min.js
│   ├── theme_extra.js
│   └── theme.js
├── search
│   ├── lunr.js
│   ├── main.js
│   ├── search_index.json
│   └── worker.js
├── search.html
├── sitemap.xml
├── sitemap.xml.gz
├── user-guide
│   ├── advanced
│   │   └── tips
│   │       └── index.html  <------
│   ├── getting-started
│   │   └── index.html      <------
│   └── installation
│       └── index.html      <------

Automatische Documentatie uit Code

mkdocstrings

mkdocstrings is een plugin voor mkdocs waarmee automatische documentatie wordt gegenereerd vanaf de source-code van je project.

Deze moet eerst als extra Python package worden geïnstalleerd, hier met ondersteuning voor Python code:

uv add --dev 'mkdocstrings[python]~=1.0'

Vervolgens wordt de plugin geactiveerd in mkdocs via the plugins optie in mkdocs.yml:

mkdocs.yml
1
2
3
4
site_name: FlaskR

plugins:
  - mkdocstrings

Om code-documentatie te genereren gebruik je de volgend syntax in een markdown document:

::: package_name.module_name.ClassName

Bijvoorbeeld, als we de code uit flaskr/db.py in een nieuwe pagina willen documenteren:

docs/reference.md
1
2
3
# Reference

::: flaskr.db

(als je nav gebruikt in mkdocs.yml zul je deze nieuwe pagina daar moeten toevoegen)

En het resultaat is ... een lege pagina! Waarom? Omdat we in db.py helemaal niets gedocumenteerd hebben! We gebruiken wel type annotations, en mkdocstrings maakt daar wel gebruik van, maar enkel type annotations is niet genoeg.

Docstrings

Automatische documentatie m.b.v. mkdocstrings hangt dus sterk af van het bestaan, en de kwaliteit, van docstrings in de code.

Er worden drie verschillende docstring stijlen ondersteund:

  1. sphinx
  2. numpy
  3. google

Tegenwoordig is voor nieuwe projecten vooral de Google stijl erg populair. Onder andere omdat deze niets dupliceert met type annotations en goed leesbaar blijft in de code zelf. Daarom werken we hier verder met enkel deze stijl.

Mkdocstrings detecteert in principe de gebruikte docstring stijl. Maar als we voor een bepaalde stijl kiezen is het beter deze expliciet in te stellen via een configuratie-optie. We voegen direct ook een paar andere handige opties toe.

mkdocs.yml
site_name: FlaskR

plugins:
  - mkdocstrings:
      handlers:
        python:
          options:
            docstring_style: google
            members_order: source
            show_source: false
  • members_order: source zorgt dat methodes, attributen, enz. voorkomen in dezelfde volgorde als in de code.
  • show_source: false om de code niet volledig in de documentatie over te nemen

Material: een Modern MkDocs Theme

Material for MkDocs is heel populaire theme voor MkDocs. Material zorgt voor een mooie en goed navigeerbare site en wordt gebruikt in heel wat moderne Python projecten (FastAPI, Pydantic, Textual, uv, ruff).

Material for MkDocs volgt het door Google ontwikkelde Material Design ontwerpsysteem, dat een visuele taal en reeks principes definieert voor het bouwen van gebruikersinterfaces. Material Design is gebouwd rond de metafoor van fysieke materialen — oppervlakken, schaduwen, diepte en beweging die de echte wereld nabootsen. Het legt de nadruk op heldere typografie, een responsieve rasterindeling, doelbewust kleurgebruik en betekenisvolle animatie.

Installatie

uv add --dev mkdocs-material
mkdocs.yml
1
2
3
4
site_name: FlaskR

theme:
  name: material

YAML Schema

De meeste code editors ondersteunen YAML. Bij VS Code is dit wel via een extensie (bvb. de YAML extensie van RedHat).

Om niet alleen de algemene YAML syntax te ondersteunen, maar ook de specifieke elementen die bij een bepaald bestand horen, is een schema definitie nodig.

Om het juiste schema voor "een Material for MkDocs mkdocs.yml" bestand te gebruiken kan als comment een hint met de link naar het schema bovenaan geplaatst worden. Bvb.

mkdocs.yml
1
2
3
4
5
# yaml-language-server: $schema=https://squidfunk.github.io/mkdocs-material/schema.json
site_name: FlaskR

theme:
  name: material

Markdown Uitbreidingen

Naast het uiterlijk van de website (fonts, kleuren, ...) voegt Material for MkDocs ook een hoop extra functionaliteit toe aan MkDocs. Deze gebruik je in de Markdown documenten die je schrijft. We bekijken hierna een aantal populaire opties maar op https://squidfunk.github.io/mkdocs-material/reference/ kan je de volledige lijst zien.

Admonitions

https://squidfunk.github.io/mkdocs-material/reference/admonitions/

Een admonition (letterlijk vermaning) is een visueel opvallend blok waarmee je extra nadruk geeft aan bepaalde informatie. Bijvoorbeeld voor een waarschuwing, tip of bijkomende informatie.

Om admonitions te gebruiken zijn een aantal markdown_extensions vanuit MkDocs nodig:

mkdocs.yml
1
2
3
4
5
6
site_name: FlaskR

markdown_extensions:
  - admonition
  - pymdownx.details
  - pymdownx.superfences

Om een admonition te plaatsen in een Markdown document gebruik je deze syntax:

1
2
3
!!! <admonition type> "optional title"
   Admonition text.
   More admonition text.

Bijvoorbeeld:

1
2
3
!!! note "Gebruik met mate"
   Admonitions kunnen je documentatie sterker en gebruiksvriendelijker maken.
   Maar overdrijf niet in hun gebruik!

Naast note heb je bvb. ook nog tip, success, question, warning of quote. De volledige lijst, met voorbeelden, vind je op https://squidfunk.github.io/mkdocs-material/reference/admonitions/.

Een admonition wordt wordt "uitklapbaar" door ??? te gebruiken i.p.v. !!!.

Annotations

https://squidfunk.github.io/mkdocs-material/reference/annotations/

Material for MkDocs voorziet een heel elegante manier om tekst (of code!) te annoteren.

Opnieuw moeten een aantal extra markdown_extensions geactiveerd worden:

mkdocs.yml
1
2
3
4
5
6
site_name: FlaskR

markdown_extensions:
  - attr_list
  - md_in_html
  - pymdownx.superfences

Een eenvoudig voorbeeld:

1
2
3
4
FlaskR is a compact teaching app based on the official Flask tutorial. (1)
{ .annotate }

1.  The **tutorial** can be found [here](https://flask.palletsprojects.com/en/stable/tutorial/).

Mark op dat je annotations ook kan gebruiken (nesten) in andere annotations en in admonitions.

Code Blocks

https://squidfunk.github.io/mkdocs-material/reference/code-blocks/

MkDocs zelf ondersteunt reeds code blocks via the standaard Markdown ``` notatie, gevolgd door de gebruikte taal in het block:

```python
print("I am highlighted!")
```
```` linenums="1"

Deze functie gebruikt onderliggend het [pygments](https://github.com/pygments/pygments) package en de lijst met alle ondersteunde talen vind je dan ook terug in de [pygments documentatie](https://pygments.org/languages/).

Material for MkDocs breidt deze functionaliteit verder uit. Ook hier zijn een aantal extra `markdown_extensions` nodig, als ook `theme.features`:

```{.yaml filename="mkdocs.yml"}
site_name: FlaskR

theme:
  name: material
  features:
    - content.code.copy
    - content.code.select
    - content.code.annotate

markdown_extensions:
  - pymdownx.highlight:
      anchor_linenums: true
      line_spans: __span
      pygments_lang_class: true
  - pymdownx.superfences
```

#### Code Copy
`content.code.copy` plaatst een icoon rechtsboven in het code block waarmee de volledige inhoud gekopieerd wordt. Dit is extra nuttig wanneer ook annotations (zie verder) gebruikt worden.

#### Code Select
`content.code.select` voegt een knop doe om "line selection" te activeren. Hiermee kan je een of meer specifieke lijnen selecteren - handig als je code uitlegt aan iemand.

#### Code Annotations
`content.code.annotate` laat toe annotations toe te voegen binnen code blocks

Dit doe je door op het einde van een lijn code als comment een annotatie nummer toe te voegen (bvb. `# (1)!`). _Na_ het code block worden de overeenkomstige annotaties dan geplaatst als een genummerde lijst.

Bijvoorbeeld:

````markdown linenums="1"
```python
def create_app(test_config=None):
    app = Flask(__name__)
    app.config.from_object("flaskr.settings")  # (1)!
    app.config.from_envvar("FLASKR_SETTINGS", silent=True)  # (2)!

    db_session, remove_session = db.create_db_session(
        app.config["DATABASE_URL"]
    )
    app.config["DB_SESSION"] = db_session

    app.teardown_appcontext(remove_session)
    app.register_blueprint(auth.bp)
    app.register_blueprint(blog.bp)

    return app
```

1. Load the default values from `flaskr/settings.py`.
2. Optionally override them with the `FLASKR_SETTINGS` environment variable.
```` linenums="1"

#### Title / Filename
Met de `title` "optie" kan een titel (doorgaans de bestandsnaam) toegevoegd worden aan een code block:

````markdown
```python title="flaskr/__init__.py"
def create_app(test_config=None):
    # ...
```
```` linenums="1"

#### Line Numbers
Met de `linenums` optie zorg je voor regelnummering in het code block. Het argument van de optie bepaald het start-nummer - handig om een groter blok op te splitsen maar de nummering te laten doorlopen.

````markdown
```python title="flaskr/__init__.py" linenums="6"
    db_session, remove_session = db.create_db_session(
        app.config["DATABASE_URL"]
    )
    app.config["DB_SESSION"] = db_session
```
```` linenums="1"

#### Line Highlight
Met de `hl_lines` optie worden specifieke lijnen in het code block gemarkeerd.

````markdown
```python title="flaskr/__init__.py" linenums="1" hl_lines="6-9 15"
def create_app(test_config=None):
    app = Flask(__name__)
    app.config.from_object("flaskr.settings")
    app.config.from_envvar("FLASKR_SETTINGS", silent=True)

    db_session, remove_session = db.create_db_session(
        app.config["DATABASE_URL"]
    )
    app.config["DB_SESSION"] = db_session

    app.teardown_appcontext(remove_session)
    app.register_blueprint(auth.bp)
    app.register_blueprint(blog.bp)

    return app
```
```` linenums="1"

### Content Tabs
<https://squidfunk.github.io/mkdocs-material/reference/content-tabs/>

Met content tabs kan je alternatieve inhoud in verschillende tabs plaatsen. Om deze manier kan je bijvoorbeeld op een **duidelijke** en **plaatsbesparende** manier **verschillende opties** geven om een pakket te installeren.

Nodige `markdown_extensions`:

```{.yaml filename="mkdocs.yml"}
site_name: FlaskR

markdown_extensions:
  - pymdownx.superfences
  - pymdownx.tabbed:
      alternate_style: true
```

Een tab hoofding start met `===` en de inhoud voor die tab wordt geïndenteerd:

````markdown linenums="1"
=== "Install with `uv`"

    Run this:

    ```bash
    uv add flask
    ```

=== "Install with `pip`"

    Run this:

    ```bash
    pip install flask
    ```

Theme Customization

De standaard opmaak van Material for MkDocs is prima maar natuurlijk ook volledig configureerbaar.

Schema en Kleuren

https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/

Via theme.palette in mkdocs.yaml kan het visueel karakter van de site aangepast worden.

  • scheme bepaalt light mode (default) of dark mode (slate)
  • primary bepaalt de kleur voor de header, sidebar, links, ...
  • accent bepaalt de kleur bij interacties, bvb bij geselecteerde links
site_name: FlaskR

theme:
  name: material
  palette:
    scheme: slate
    primary: red
    accent: orange

theme.palette kan ook een lijst zijn waarbij elk element voorzien is van een extra toggle element. Er wordt dan een icoon zichtbaar in de header bar. Bij het aanklikken van dit icoon wordt de volgende configuratie in de palette lijst actief. Het toggle element bepaalt welk icoon getoond wordt.

Bijvoorbeeld:

mkdocs.yml
site_name: FlaskR

theme:
  name: material
  palette:
    - scheme: default
      primary: red
      accent: orange
      toggle:
        icon: material/brightness-7
        name: Switch to dark mode
    - scheme: slate
      primary: green
      accent: lime
      toggle:
        icon: material/brightness-4
        name: Switch to light mode

Fonts

Natuurlijk is het mogelijk de gebruikte fonts aan te passen, ook al zijn de defaults prima. Alle Google fonts kunnen gebruikt worden.

Bijvoorbeeld:

mkdocs.yml
1
2
3
4
5
6
7
site_name: FlaskR

theme:
  name: material
  font:
    text: Sansation # Default: Roboto
    code: Fire Code # Roboto Mono

Taal en Internationalization

Er is ondersteuning voor alle talen (voor de tekst elementen die Material zelf aanbrengt) als ook het aanbieden van de site in (en switchen tussen) verschillende talen.

mkdocs.yml
site_name: FlaskR

theme:
  name: material
  language: fr

extra:
  alternate:
    - name: English
      link: /en/
      lang: en
    - name: Deutsch
      link: /de/
      lang: de

Extra Material for MkDocs Functies

https://squidfunk.github.io/mkdocs-material/setup/setting-up-navigation/

Website Sneller Maken

mkdocs.yml
1
2
3
4
5
6
7
site_name: FlaskR

theme:
  name: material
  features:
    - navigation.instant
    - navigation.instant.prefetch
  • navigation.instant zorgt m.b.v. XHR voor sneller inladen van pagina's.
  • navigation.instant.prefetch laadt pagina's in nog voor er op de link geklikt is.

Het is mogelijk de eerste laag navigatie-links in de header te plaatsen (i.p.v. de linker zijbalk). Optioneel blijven deze tabs ook zichtbaar ("sticky") als je naar onder scrolt.

mkdocs.yml
1
2
3
4
5
6
7
site_name: FlaskR

theme:
  name: material
  features:
    - navigation.tabs
    - navigation.tabs.sticky

Je kan voor links naar andere pagina's van de site een "instant preview" laten verschijnen zonder dat de gebruiker effectief op de link klikt. Dit kan bijvoorbeeld erg handig zijn voor links naar referenties.

Dit doe je voor een specifieke link door { data-preview } achter de link te plakken. Bijvoorbeeld:

docs/index.md
Meer weten over [`create_app`](reference.md#flaskr.create_app){ data-preview }.

Het is ook mogelijk om deze functie te activeren voor alle links naar (secties van) een of meerdere pagina's. Dit gebeurt door configuratie van de material.extensions.preview extension:

mkdocs.yml
1
2
3
4
5
6
7
8
site_name: FlaskR

markdown_extensions:
  - material.extensions.preview:
      configurations:
        - targets:
            include:
              - reference.md

MkDocs zelf (dus zonder Material) voorziet reeds een zoekfunctie via een (ingebouwde) plugin. Omdat we een plugins sectie gedefinieerd hebben (om mkdocstrings toe te voegen) moet de search plugin expliciet terug toegevoegd worden:

mkdocs.yml
1
2
3
4
site_name: FlaskR

plugins:
  - search

Material voegt wel nog een aantal functies toe aan deze plugin:

mkdocs.yml
1
2
3
4
5
6
7
site_name: FlaskR

theme:
  name: material
  features:
    - search.suggest
    - search.highlight
  • search.suggest zorgt voor suggesties bij het typen in de zoekbalk
  • search.highlight highlight de zoekterm wanneer een pagina via de zoekfunctie wordt geopend

Material geeft ook de mogelijkheid de zoekresultaten per pagina te beïnvloeden door metadata bovenaan een pagina te plaatsen.

Met boost zorg je dat een pagina hoger (boost > 1) of lager (boost < 1) komt te staan in de resultaten.

1
2
3
4
5
6
7
---
search:
  boost: 2
---

# Page title
...

Met exclude zal de pagina helemaal niet gevonden worden door de zoekfunctie.

1
2
3
4
5
6
7
---
search:
  exclude: true
---

# Page title
...

Plugins

We hebben al twee plugins geactiveerd: search en mkdocstrings. Er zijn nog heel wat andere plugins beschikbaar. We bekijken nog de veelgebruikte blog plugin.

Blog Plugin

https://squidfunk.github.io/mkdocs-material/plugins/blog/

Met de blog plugin kan je op een eenvoudige manier een blog toevoegen aan je site. Elke post is een eenvoudig Markdown document. De plugin zorgt voor de rest.

mkdocs.yml
1
2
3
4
site_name: FlaskR

plugins:
  - blog

Met de default instellingen verwacht de plugin de volgende directory structuur:

docs
└── blog
    ├── index.md
    └── posts
        ├── first-post.md
        └── another-post.md

In posts/ komen Markdown documenten (zoals andere documenten voor de site) maar met extra metadata bovenaan (ook wel frontmatter genoemd). Deze metadata is in YAML formaat en moet minstens een date.created bevatten om aan de geven wanneer de post is geschreven.

Bijvoorbeeld:

docs/blog/posts/first-post.md
---
date:
  created: 2026-03-01
---

# This is the first blog post!

You won't believe what comes next...
<!-- more -->

Welcome to the project. Check out the user guide to get started!

Andere nuttige metadata die je kan toevoegen zijn authors en links. Voor authors is een extra bestand nodig waarin elke auteur wordt beschreven, bijvoorbeeld:

docs/blog/.authors.yml
1
2
3
4
5
6
authors:
  fabrice:
    name: Fabrice
    description: Chief FlaskR
    avatar: https://avatars.githubusercontent.com/u/785424
    url: https://github.com/dvx76

In de post metadata krijgen we dan het volgende:

docs/blog/posts/first-post.md
---
date:
  created: 2026-03-01
authors:
  - fabrice
links:
  - user-guide/getting-started.md
  - External links:
    - Flask documentation: https://flask.palletsprojects.com
---

Nog Meer

Material heeft nog talloze andere functies die we hier niet allemaal aan bod kunnen laten komen. Een aantal voorbeelden en links:

Laat je Inspireren

Heel wat MkDocs (met of zonder Material) die je tegenkomt horen bij een open-source project. De code van de site is vaak ook publiek en is bijgevolg een prima bron van inspiratie voor je eigen site.

Hou je bijvoorbeeld van de FastAPI documentatie site dan kan je de bijhorende mkdocs.yml gewoon bekijken en (deels) overnemen.

OpenAPI Spec Integratie

Als je met Connexion of FastAPI een API hebt gemaakt is de API zelf al grotendeels gedocumenteerd (en bruikbaar) m.b.v. de OpenAPI Specification (OAS).

Met de mkdocs-render-swagger-plugin plugin kunnen we de Swagger representatie van de OAS rechtstreeks in onze MkDocs site integreren.

uv add mkdocs-render-swagger-plugin
mkdocs.yml
1
2
3
4
site_name: FlaskR

plugins:
  - render_swagger

Nadat de plugin is geïnstaleerd en geactiveerd kan een lokaal of online OAS JSON bestand in een Markdown pagina worden geplaats met !!swagger FILENAME!! of !!swagger-http URL!!.

Als test kan je de oneline petstore specificatie gebruiken.

mkdocs.yml
1
2
3
nav:
  # ...
  - API: api.md
docs/api.md
!!swagger-http https://petstore.swagger.io/v2/swagger.json!!

Een MkDocs Website Publiceren

Het zagen dat het mkdocs build commando de volledige website genereert. Er zijn vervolgens eindeloos veel opties om die inhoud te hosten en zo publiek te maken. We bekijk hieronder twee eenvoudige en populaire manieren: GitHub Pages en Read the Docs.

Publiceren met GitHub Actions en Pages

Als de broncode van je MkDocs site op GitHub staat zijn GitHub Pages in combinatie met GitHub Actions een erg handige manier om te starten.

Ook hier zijn verschillende oplossingen mogelijk. We volgen de voorbeeldconfiguratie uit de Material for MkDocs documentatie. Dat is een heel eenvoudige manier waarbij de GitHub action de gegenereerde website zal pushen naar een aparte branch (gh-pages) en GitHub Pages geconfigureerd wordt om die branch te gebruiken.

De GitHub action configureer je door het volgende bestand te committen en pushen:

.github/workflows/deploy-docs.yml
name: Deploy Docs
on:
  push:
    branches:
      - main
      - master
permissions:
  contents: write
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Configure Git Credentials
        run: |
          git config user.name github-actions[bot]
          git config user.email 41898282+github-actions[bot]@users.noreply.github.com
      - uses: actions/setup-python@v5
        with:
          python-version: 3.x
      - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
      - uses: actions/cache@v4
        with:
          key: mkdocs-material-${{ env.cache_id }}
          path: ~/.cache
          restore-keys: |
            mkdocs-material-
      - run: pip install mkdocs-material "mkdocstrings[python]"
      - run: mkdocs gh-deploy --force
mkdocs gh-deploy

Je hebt misschien opgemerkt dat het commando dat uiteindelijke wordt uitgevoerd een mkdocs commando is. De functionaliteit die in één stap de website genereert en het resultaat naar de gh-pages branch pusht komt inderdaad uit het basis MkDocs package.

In principe kan je de website nu bekijken op https://<github_username>.github.io/<repo_name>/ (bvb. https://dvx76.github.io/flask-tutorial/).

Zo niet, controleer dan volgende zaken:

  • Fouten tijdens het uitvoeren van de GitHub action (Actions bovenaan in GitHub)
  • site_url correct ingesteld in mkdocs.yml (bvb. site_url: https://dvx76.github.io/flask-tutorial/)
  • Controleer online op GitHub de inhoud van de gh-pages branch
  • Controleer dat GitHub Pages voor deze repo correct is ingesteld met de gh-pages branch als bron:
  • Open je repository op GitHub
  • Klik bovenaan op Settings
  • Klik in de linkerzijbalk op Pages
  • Onder Build and deployment:
    1. zet Source op Deploy from a branch
    2. zet de Branch op gh-pages en de folder op / (root)

Publiceren met Read the Docs

Read the Docs is een gespecialiseerd platform om technische documentatie automatisch te genereren en hosten. Verschillende versies van de documentatie zijn ook toegangelijk.

In tegenstelling tot GitHub Pages hoef je hier dus geen aparte CI-workflow te schrijven: Read the Docs haalt zelf je repository op, voert de build uit, en publiceert daarna de site.

Community of Business?

Read the Docs heeft zowel een (gratis) Community als een (betalende) Business optie.

Voor persoonlijke, publieke en/of open-source projecten kan je de community optie gebruiken.

Configuratiebestand

Om een MkDocs project op Read the Docs te publiceren, voeg je in de root van je repository een .readthedocs.yaml bestand toe:

.readthedocs.yaml
version: 2

build:
  os: ubuntu-24.04
  tools:
    python: "3.13"

mkdocs:
  configuration: mkdocs.yml

python:
  install:
    - requirements: docs/requirements.txt

In het voorbeeld hierboven verwacht Read the Docs ook een requirements-bestand met de packages die nodig zijn om je documentatie te bouwen:

docs/requirements.txt
1
2
3
4
mkdocs~=1.6
mkdocs-material
mkdocstrings[python]
mkdocs-render-swagger-plugin

mkdocs.yml aanpassen

Read the Docs geeft tijdens de build zelf de correcte publieke URL door. Daarom is het handig om site_url in mkdocs.yml dynamisch in te stellen:

mkdocs.yml
site_name: FlaskR
site_url: !ENV [READTHEDOCS_CANONICAL_URL, "https://dvx76.github.io/flask-tutorial/"]

Project Toevoegen

Nadat je .readthedocs.yaml hebt gecommit en gepusht:

  1. Maak een account aan op Read the Docs.
  2. Koppel je GitHub account.
  3. Kies Add Project en selecteer je repository.

Bij een succesvolle build wordt je site gepubliceerd op een URL zoals https://flasktutorial.readthedocs.io.

Documentatie voor AI/LLMs

Vandaag wordt projectdocumentatie niet alleen door personen gebruikt, maar veelal ook door "AI".

LLMs zijn per definitie taalmodellen en zijn (onder andere) getraind op menselijke taal. Bijgevolg: documentatie die nuttig is voor mensen zal dat ook zijn voor een LLM. Een reden te meer om de documentatie van je project extra te verzorgen.

Specifieke richtlijnen om je documentatie extra compatible met LLMs te maken:

  • Gebruik beknopte, duidelijke taal.
  • Voeg bij het linken naar bronnen korte, informatieve beschrijvingen toe.
  • Vermijd dubbelzinnige termen of onverklaard jargon.
  • Hou documentatie-sites statisch en eenvoudig (MkDocs is dus zeer geschikt!)
  • Test het gebruik van je documentatie met een LLM door een link te geven en de LLM vragen te laten beantwoorden.

Er zijn initiatieven zoals https://llmstxt.org om LLM-specifieke documentatie te standaardiseren maar deze hebben tot nog toe weinig gevolg gekregen.