Pricing Dashboard Sign up
Recent
· 9 min read · MDisBetter

Build a MkDocs Site from Word Documents (Walkthrough)

You have a folder of Word documents — internal handbook, API guide, runbook collection, training material — and you want them as a real documentation site with search, navigation, dark mode, and a public URL. MkDocs is the answer. Free, open source, ships beautiful templates out of the box, builds in seconds, deploys anywhere static. The path: convert each Word doc to Markdown, drop it in docs/, write a small mkdocs.yml, run mkdocs build. Here's the complete walkthrough.

What you'll end up with

A static site at https://yourname.github.io/yourdocs (or any host you want) with:

All from the same Markdown that came out of your Word conversions. No CSS to write.

Step 1: Install MkDocs

pip install mkdocs mkdocs-material

The Material theme is the de facto MkDocs theme — gorgeous out of the box, hugely configurable, used by FastAPI docs, Pydantic docs, and many others. Confirm install:

mkdocs --version

Step 2: Initialize the project

mkdir my-docs && cd my-docs
mkdocs new .

This creates a starter structure:

my-docs/
├── docs/
│   └── index.md
└── mkdocs.yml

You'll add converted Word docs into docs/ next.

Step 3: Convert each Word document

Take each .docx through the MDisBetter Word to Markdown converter one at a time:

  1. Drop .docx in the converter
  2. Click Convert
  3. Download the .md
  4. Save it in the appropriate docs/ subfolder with a kebab-case filename

For 30+ documents, install Pandoc and bulk-convert (see convert multiple Word documents):

cd /path/to/word-docs
for f in *.docx; do
  base=$(echo "${f%.docx}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
  pandoc -f docx -t gfm \
    --extract-media="$HOME/my-docs/docs/images" \
    "$f" -o "$HOME/my-docs/docs/$base.md"
done

Step 4: Organise the docs folder

Group your converted .md files into logical sections:

docs/
├── index.md                  (landing page)
├── getting-started/
│   ├── installation.md
│   └── first-steps.md
├── guides/
│   ├── authentication.md
│   ├── data-import.md
│   └── deployment.md
├── reference/
│   ├── cli-commands.md
│   └── configuration.md
├── tutorials/
│   └── building-an-app.md
└── images/                   (extracted from Word)

Rename files to clear, lowercase, kebab-case slugs. Drop docs that are obsolete. Merge docs that overlap.

Step 5: Write mkdocs.yml

Replace the auto-generated mkdocs.yml with a configured version:

site_name: My Documentation
site_url: https://example.com
site_description: "Internal documentation, runbooks, and guides."

theme:
  name: material
  features:
    - navigation.tabs
    - navigation.sections
    - navigation.expand
    - navigation.top
    - search.suggest
    - search.highlight
    - content.code.copy
    - content.tabs.link
  palette:
    - media: "(prefers-color-scheme: light)"
      scheme: default
      primary: indigo
      toggle:
        icon: material/brightness-7
        name: Switch to dark mode
    - media: "(prefers-color-scheme: dark)"
      scheme: slate
      primary: indigo
      toggle:
        icon: material/brightness-4
        name: Switch to light mode

nav:
  - Home: index.md
  - Getting Started:
    - Installation: getting-started/installation.md
    - First Steps: getting-started/first-steps.md
  - Guides:
    - Authentication: guides/authentication.md
    - Data Import: guides/data-import.md
    - Deployment: guides/deployment.md
  - Reference:
    - CLI Commands: reference/cli-commands.md
    - Configuration: reference/configuration.md
  - Tutorials:
    - Building an App: tutorials/building-an-app.md

markdown_extensions:
  - admonition
  - attr_list
  - md_in_html
  - tables
  - toc:
      permalink: true
  - pymdownx.details
  - pymdownx.superfences
  - pymdownx.tabbed:
      alternate_style: true
  - pymdownx.highlight:
      anchor_linenums: true
      line_spans: __span
  - pymdownx.inlinehilite
  - pymdownx.snippets

plugins:
  - search

Step 6: Preview locally

mkdocs serve

Open http://127.0.0.1:8000. The site auto-reloads as you edit. Verify:

Step 7: Fix common conversion issues

Even with a clean conversion, you'll find a few things to polish:

Empty headings

Word styles sometimes generate empty heading paragraphs. Find them:

grep -rn '^#\+ \?$' docs/

Delete them by hand.

Broken image references

If image paths in the .md don't match where you put the files:

grep -rn '!\[' docs/ | head -20

Adjust the relative paths or rewrite them with sed.

Bad heading levels

Some Word docs start at H2 instead of H1, or skip levels (H1 → H3 → H2). MkDocs builds the table of contents from headings, so consistent levels matter. Open each top-level page and ensure the structure is sane.

Tables that didn't survive

Complex Word tables (merged cells, multi-row headers) often break in conversion. For those, consider replacing with a Markdown definition list, an admonition with bullet points, or a simpler flat table. See word tables to Markdown guide for tactics.

Step 8: Add admonitions and callouts

Word's "highlighted box" or "important note" styles don't survive conversion. Replace them with MkDocs admonitions:

!!! warning
    Don't run this in production without testing.

!!! note
    This applies only to v3.0 and later.

!!! tip
    Use --dry-run to preview the changes.

Worth doing for the most-read sections — instantly more scannable than the converted plain paragraphs.

Step 9: Build the site

mkdocs build

Output goes to site/. Static HTML, CSS, and JS — no server needed. Upload to:

Step 10: Continuous deployment

If your docs live in a Git repo, deploy on push. GitHub Actions:

name: Build & Deploy Docs
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.x' }
      - run: pip install mkdocs-material
      - run: mkdocs gh-deploy --force

Now every commit to main rebuilds and redeploys the site automatically. See migrate Word documentation to GitHub for the full docs-as-code workflow.

Bonus: instant search

The Material theme ships full-text search out of the box. For larger sites consider mkdocs-material-extensions or external search via Algolia DocSearch. Both index your Markdown and provide instant search-as-you-type.

Bonus: versioning

If you ship multiple versions of a product (v1, v2, v3 docs side by side), use the mike plugin:

pip install mike
mike deploy --push 3.0 latest
mike set-default --push 3.0

Visitors get a version dropdown in the header.

What if some docs aren't Word?

If your knowledge base mixes Word with other source formats, convert each through the appropriate tool and drop into docs/:

All produce GFM-compatible .md that drops directly into the same MkDocs structure.

Why MkDocs over alternatives

ToolBest forTradeoff
MkDocsInternal docs, project docs, runbooksLimited customisation vs SPA generators
DocusaurusProduct docs with versioning + i18nReact-heavy, slower builds
HugoMarketing-style docs sites, blogsSteeper learning curve, Go templating
JekyllGitHub-native, classic blog-styleOlder, slower than alternatives
SphinxPython project docs, API referencesRST-first, Markdown is bolted on

For most teams converting from Word, MkDocs hits the sweet spot — beautiful output, minimal config, lives entirely in Markdown.

Plugins worth installing

The MkDocs ecosystem has a deep plugin catalogue. Worth knowing:

Add to mkdocs.yml under plugins: and pip install. Most are zero-config.

Common deployment patterns

Once your MkDocs site builds locally, you have several deployment options worth comparing:

For most teams, Cloudflare Pages or GitHub Pages is the right starting point. Switch to self-hosted only when you have a specific reason (compliance, internal-only, custom auth).

Performance optimisation

For sites over 500 pages, MkDocs build can become slow. Speed-ups:

Search at scale

The built-in lunr.js search is fine up to a few hundred pages. Beyond that, search becomes slow and the index becomes large. Alternatives:

All three integrate with MkDocs Material via official or community plugins.

Recommendation

Convert your Word docs progressively (web tool for one-offs, Pandoc for bulk), drop into docs/, configure mkdocs.yml, build, deploy. Total setup time for a 30-doc site: about 4 hours including reorg and polish. The result is a real documentation site you can hand a stranger and they can navigate. See migrate Word documentation to GitHub for the full docs-as-code workflow that pairs with this MkDocs setup. The combined approach — converted Markdown in docs/, version-controlled in Git, auto-deployed via CI on every push — turns a static Word library into a living documentation system.

Frequently asked questions

Can MkDocs handle a docs site with 1,000+ pages?
Yes — MkDocs builds typically run at a few hundred pages per second, so even 5,000-page sites build in well under a minute. Search performance is the bottleneck on very large sites; for 1,000+ pages consider replacing the built-in lunr.js search with Algolia DocSearch (free for OSS docs) or a self-hosted Meilisearch instance.
How do I add a custom domain to my MkDocs site?
On GitHub Pages, add a CNAME file with your domain to the docs/ folder, configure your DNS to CNAME to <user>.github.io, and set the custom domain in the repo's Pages settings. On Netlify/Cloudflare Pages/Vercel, use the platform's custom domain UI. The mkdocs.yml site_url field should also reflect the custom domain so canonical URLs and sitemaps generate correctly.
What if my Word docs use lots of inline screenshots?
Pandoc with --extract-media=docs/images dumps every embedded image to that folder and rewrites the Markdown to reference them. The MkDocs site renders them as inline images. For very screenshot-heavy docs, consider also enabling the lightgallery extension so users can click to enlarge.