---
title: AsciiBinder AsciiDoc to Markdown to MkDocs
description: The same Markdown that builds the Astro site becomes an MkDocs Material project with one flag. What the exporter maps, what publishing 1,800 pages taught it, and a repo you can fork.
created: "2026-09-04"
author: Gabriel McGoldrick
tags:
  - topic/asciidoc
  - topic/migration
---

# AsciiBinder AsciiDoc to Markdown to MkDocs {#asciibinder-asciidoc-to-markdown-to-mkdocs}

Part 8 converted the OpenShift documentation to Markdown and built it as an Astro site. The markdown is DogsBay MD, ordinary CommonMark plus a small directive vocabulary for the things AsciiDoc has and Markdown does not. The markdown is not tied to Astro and the DogsBay CLI can serialize it to other site generators' dialects.

This post converts the same ~1,800 pages to **MkDocs with the Material theme**, publishes them to GitHub Pages. The result is at [dogsbay.github.io/openshift-docs-mkdocs](https://dogsbay.github.io/openshift-docs-mkdocs/) and the workflow that builds it is [dogsbay/openshift-docs-mkdocs](https://github.com/dogsbay/openshift-docs-mkdocs).

:::note{title="AsciiDoc to Markdown — part 9 of 10"}
1. [Converting AsciiDoc to Markdown](/blog/converting-asciidoc-to-markdown/)
2. [Why existing AsciiDoc converters lose your structure](/blog/why-existing-converters-lose-structure/)
3. [Why Jinja is the right target](/blog/why-jinja-is-the-right-target/)
4. [Mapping AsciiDoc variables to Jinja](/blog/asciidoc-variables-in-jinja/)
5. [Mapping AsciiDoc conditionals to Jinja](/blog/asciidoc-conditionals-in-jinja/)
6. [Mapping AsciiDoc ifeval to Jinja](/blog/asciidoc-ifeval-in-jinja/)
7. [Mapping AsciiDoc includes and level offsets to Jinja](/blog/asciidoc-includes-in-jinja/)
8. [AsciiBinder AsciiDoc to Markdown to Astro](/blog/asciibinder-adoc-to-markdown-astro/)
9. **AsciiBinder AsciiDoc to Markdown to MkDocs** — you are here
10. [AsciiBinder AsciiDoc to Markdown to Docusaurus](/blog/asciibinder-adoc-to-markdown-docusaurus/)
:::

## One flag {#one-flag}

The export is a flag on the same build that produces the Astro site:

```bash
npx dogsbay site build ./out --to mkdocs --out ./mkdocs \
  --site-url https://<you>.github.io/openshift-docs-mkdocs
```

`--to mkdocs` names the target: the build assembles the pages exactly as it would for Astro and writes them out as an MkDocs project instead, with a `mkdocs.yml` for nav, theme features and Markdown extensions filled in, and a `docs/` tree with one `.md` file per page plus the images.

```
mkdocs/
  mkdocs.yml        site_name, site_url, nav, theme.features, markdown_extensions
  docs/
    welcome.md
    welcome/…
    installing/…
    images/         675 files
```

Then the workflow runs `pip install mkdocs-material && mkdocs build` to create the site.

The `site build` is where attributes resolve, conditionals select the openshift-enterprise variant, and the includes pull in their modules in. Running the export means the MkDocs site is built from the **same 1,799 pages** as the Astro one, and the two can be compared page for page.

## What the exporter has to translate {#what-the-exporter-has-to-translate}

The common Markdown content straightforward. The following table shows how the directives are mapped to a specific MkDocs target:

| DogsBay MD | MkDocs Material |
| --- | --- |
| `:::note`, `:::warning`, … (12 kinds) | `!!! note` admonitions, with AsciiDoc's `IMPORTANT` and `CAUTION` mapped to the Material names |
| `:::tabs` | `=== "Tab"` content tabs (`pymdownx.tabbed`) |
| `:::steps` | ordered lists, since Material has no steps block |
| definition lists | `def_list`, one `Term` / `: definition` pair per entry |
| tables with nested block cells | `<table markdown>`, so Python-Markdown parses what is inside |
| fenced code with a title | `pymdownx.superfences` with the title attribute |
| footnotes, math | `footnotes`, `pymdownx.arithmatex` |

The extensions block is not a fixed list. The exporter walks the trees and switches on only what the corpus uses, so a small site gets a small `mkdocs.yml`.

## Fidelity, measured against AsciiBinder {#fidelity-measured-against-asciibinder}

The comparison target is the page AsciiBinder itself renders from the same AsciiDoc, on a deliberately hard page: bare-metal UPI installation with network customizations, 75 includes, 166 code blocks.

|  | AsciiBinder HTML | MkDocs export |
| --- | --- | --- |
| Code blocks | 166 | 166 |
| Admonitions | 117 | 117 |
| Definition lists | 43 | 45 |
| Token occurrences retained |  | 98.7% |

The two extra definition lists and the missing 1.3% are all traceable to the source side: a `== Next steps` heading that AsciiBinder demotes into a related-links block, ids with a `_` prefix from the module id scheme, and table numbering that AsciiBinder adds at render time.

## Lessons learned {#lessons-learned}

By default, **every page in the MkDocs version carried the whole nav.** Material renders the full `nav:` tree into each page unless `navigation.prune` is on. With 2,100 nav entries that was about 1 MB per page. The welcome page was 981 KB, of which the actual content was only a few KB. and **1.9 GB** for the site, which is over GitHub Pages' 1 GB limit. The exporter now emits `navigation.prune`, Material's own recommendation for large sites:

|  | without prune | with prune |
| --- | --- | --- |
| welcome page | 981 KB | 259 KB |
| whole site | 1.9 GB | 650 MB |

**There was no home page.** MkDocs serves `docs/index.md` at the site root and emits nothing there otherwise. OpenShift's nav starts at `welcome.md`, so the root of the published site was a 404 while every deep link worked. The exporter now writes a `docs/index.md` that redirects to the first page in the nav.

## Try AsciiDoc to Material for MkDocs yourself {#try-asciidoc-to-material-for-mkdocs-yourself}

The repo has the same shape as the Markdown one with the `main` branch holding one workflow and nothing else, and the exported project lands on a branch named after the source branch.

1. Fork [dogsbay/openshift-docs-mkdocs](https://github.com/dogsbay/openshift-docs-mkdocs).
2. In **Settings → Pages**, set the source to **GitHub Actions**. The workflow cannot do this for you; the default token is not allowed to.
3. Open the **Actions** tab, enable workflows, and run **Build MkDocs site**. The input defaults to `enterprise-4.22`.

The workflow does not clone OpenShift or run the AsciiDoc conversion. It sparse-checks-out `markdown/` from [dogsbay/openshift-docs-markdown](https://github.com/dogsbay/openshift-docs-markdown)'s content branch, runs the export, builds with `mkdocs-material`, commits the project to the content branch, and deploys the built HTML from the artefact. The whole run is about **five minutes**. It refuses to deploy a site over 950 MB, which is a GitHub Pages limit, and it runs weekly, two hours after the Markdown repo's own sync.

Your copy appears at `https://<your-username>.github.io/openshift-docs-mkdocs/`.

## Pages to check {#pages-to-check}

| Page | Why |
| --- | --- |
| [/](https://dogsbay.github.io/openshift-docs-mkdocs/) | the redirect that was not there |
| [/installing/installing_bare_metal/upi/installing-bare-metal-network-customizations/](https://dogsbay.github.io/openshift-docs-mkdocs/installing/installing_bare_metal/upi/installing-bare-metal-network-customizations/) | the page measured above: 166 code blocks, 117 admonitions |
| [/welcome/glossary/](https://dogsbay.github.io/openshift-docs-mkdocs/welcome/glossary/) | definition lists through `def_list` |
| [/welcome/oke_about/](https://dogsbay.github.io/openshift-docs-mkdocs/welcome/oke_about/) | the span-cell comparison table, now as `<table markdown>` |
| [/architecture/architecture/](https://dogsbay.github.io/openshift-docs-mkdocs/architecture/architecture/) | images under Material's layout |

The same pages exist on the Astro site and, in the next part, on the Docusaurus one. That is the point: one markdown source, three generators, the same content on each.
