All.publish mkdocs.how to guide
How to Publish Mkdocs Documentation#
Overview#
At Causify, we use MkDocs with the Material theme to publish documentation for multiple projects. We have two main publishing methods:
- Custom domain with S3 (e.g., https://docs.causify.ai) - VPN-protected internal documentation
- GitHub Pages (e.g., https://causify-ai.github.io/helpers) - Public documentation
Both methods follow the same structure and workflow, with only minor variations in the deployment step.
Publishing Options#
Option 1: Custom Domain (S3 + VPN)#
Use case: Internal documentation that should be VPN-protected
Infrastructure:
- S3 bucket for static hosting
- CloudFront distribution (optional, for caching)
- VPN → VPC → Load Balancer → S3 VPC Endpoint → S3 bucket
- Custom subdomain (e.g.,
docs.causify.ai)
Examples:
- Causify documentation: https://docs.causify.ai
- Causify blog: https://blog.causify.ai
Workflow: GitHub Action builds MkDocs → syncs to S3 → invalidates CloudFront cache Example:-Causify doc Git Action
Option 2: Github Pages#
Use case: Public documentation that should be accessible without VPN
Infrastructure:
- GitHub Pages hosting (free)
- Automatic HTTPS via GitHub
- URL format:
https://<org>.github.io/<repo>/
Examples:
- Helpers documentation: https://causify-ai.github.io/helpers
Workflow: GitHub Action builds MkDocs → pushes to gh-pages branch → GitHub
Pages serves it
Directory Structure#
Required Layout#
Every MkDocs site we publish must follow this exact directory and file layout:
<site-root>/
mkdocs.yml # Site configuration (docs_dir points to tmp.mkdocs)
docs/ # Raw source content (committed to git)
index.md # Homepage
<other .md files> # Documentation pages
<folders>/ # Organized documentation sections
assets/ # Images and icons
logo.png # Site logo (symlink or real file)
favicon.ico # Site favicon (symlink or real file)
styles/ # Custom CSS
styles.css # Main stylesheet (symlink or real file)
tmp.mkdocs/ # Preprocessed content (DO NOT COMMIT)
index.md # Processed files
<other processed files>
assets/ # Copied assets
styles/ # Copied styles
File Descriptions#
mkdocs.yml
- Main configuration file for the site
- Defines site name, theme, plugins, and markdown extensions
- Critical:
docs_dir: tmp.mkdocspoints to preprocessed content
docs/
- Contains raw markdown files that you write and edit
- This is what gets committed to git
- Organized with folders for different documentation sections
docs/assets/
- Logo, favicon, images, diagrams
- Should be symlinked to canonical versions (see below)
docs/styles/
- Custom CSS for site styling
- Should be symlinked to canonical stylesheet
tmp.mkdocs/
- Generated by the preprocessing script
- Never commit this directory to git (add to
.gitignore) - This is what MkDocs builds from
Design Invariants#
To maintain consistency across all our documentation sites, we follow these invariants:
- Unified Configuration
- All documentation sites reuse the same
mkdocs.ymltemplate - Only
site_name,site_url, and site-specific settings change -
Blogs add the blog plugin but keep the same base structure
-
Standardized Workflows
- Only two GitHub workflow templates:
- Documents workflow: For standard documentation (with preprocessing)
- Blog workflow: For blog posts (no preprocessing needed)
-
Same logic with small variations for S3 vs GitHub Pages
-
Consistent Structure
- All sites follow the same directory layout
- Assets and styles in predictable locations
-
Preprocessing always outputs to
tmp.mkdocs/ -
Shared Assets
- Logo, favicon, and CSS should be symlinked from canonical sources
- This ensures consistency and single source of truth
- Changes propagate to all sites automatically
Canonical Assets and CSS#
To ensure consistent branding and styling across all documentation sites, we maintain canonical versions of shared assets.
Source of Truth#
The canonical assets are located in the helpers repository:
helpers_root/docs/mkdocs/assets/logo.png
helpers_root/docs/mkdocs/assets/favicon.ico
helpers_root/docs/mkdocs/styles/styles.css
- When creating a new documentation site, symlink rather than copy these files:
Benefits of symlinking:
- Single source of truth for branding
- Updates to logo/favicon/styles propagate automatically
- No duplicate files to maintain
- Consistent appearance across all sites
Verify symlinks:
ls -la docs/assets/
ls -la docs/styles/
You should see symlinks pointing to the helpers repository.
How to Publish Documentation#
Preview Locally#
Before publishing, always preview your documentation locally to ensure it renders correctly.
Step 1: Run preprocessing
Navigate to your repository root and run the preprocessing script:
cd ~/src/your_repo
# Run Preprocessing.
python helpers_root/docs/mkdocs/preprocess_mkdocs.py \
--input_dir docs \
--output_dir tmp.mkdocs \
-v INFO
Step 2: Activate the MkDocs environment
source "$HOME/src/venv/mkdocs/bin/activate"
Step 3: Navigate to your docs directory
cd your_docs_directory # e.g., docs_mkdocs/ or the directory with mkdocs.yml
Step 4: Start the local server
mkdocs serve
Step 5: Open in browser
- The terminal will display the URL (typically
http://127.0.0.1:8000) - Open this URL in your browser
- The server supports live reload - changes will auto-refresh
Step 6: Stop the server
Press Ctrl+C when done previewing
Publish to Custom Domain (S3) (Instead of Gh-Pages)#
Prerequisites:
- S3 bucket configured for static hosting
- AWS credentials configured in GitHub repository secrets
- CloudFront distribution (optional but recommended)
Step 1: Set up GitHub Actions workflow
Create and .github/workflows/publish_docs.yml:
name: Publish MkDocs
on:
push:
branches:
- master
paths:
- docs/**
workflow_dispatch:
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive # If using helpers as submodule.
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Install MkDocs
run: pip install mkdocs mkdocs-material
- name: Run preprocessing
run: |
python helpers_root/docs/mkdocs/preprocess_mkdocs.py \
--input_dir docs \
--output_dir tmp.mkdocs \
-v INFO
- name: Build MkDocs
run: mkdocs build
working-directory: ./docs_mkdocs # Adjust to your structure.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: ${{ vars.GH_ACTION_AWS_ROLE_ARN }}
role-session-name: ${{ vars.GH_ACTION_AWS_SESSION_NAME }}
aws-region: ${{ vars.CSFY_AWS_DEFAULT_REGION }}
- name: Publish to S3
run: |
aws s3 sync ./docs_mkdocs/site s3://your-bucket-name --delete
The workflow will automatically run on push to master! Example: Csfy Repo docs Git Action
Publish to Github Pages#
Prerequisites:
- GitHub Pages enabled in repository settings
gh-pagesbranch will be created automatically
Step 1: Set up GitHub Actions workflow
Create .github/workflows/publish_mkdocs.yml:
name: Publish MkDocs
on:
push:
branches:
- master
paths:
- docs/**
workflow_dispatch:
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive # If using helpers as submodule.
- 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: pip install mkdocs mkdocs-material
- name: Update PYTHONPATH
run: |
echo "PYTHONPATH=${{ github.workspace }}:${{ github.workspace }}/helpers_root" >> $GITHUB_ENV
- name: Preprocess MkDocs
working-directory: ./docs/mkdocs # Adjust to your structure.
run: |
python ../../helpers_root/docs/mkdocs/preprocess_mkdocs.py \
--input_dir docs \
--output_dir tmp.mkdocs
- run: mkdocs gh-deploy --force
working-directory: ./docs/mkdocs
Step 2: Enable GitHub Pages
- Go to repository Settings → Pages
- Source: Deploy from a branch
- Branch:
gh-pages// (root) - Click Save
Step 3: Commit and push
git add .github/workflows/publish_mkdocs.yml
git commit -m "Add MkDocs GitHub Pages workflow"
git push origin master
Step 4: Access your site
After the workflow completes:
- Your site will be available at:
https://<org>.github.io/<repo>/ - Example:
https://causify-ai.github.io/helpers/
Mkdocs Configuration#
Example Mkdocs.Yml#
Here's a standard mkdocs.yml template used across all Causify documentation:
site_name: Your Site Name
# Site_Url: Https://Yourdomain.Org/Yoursite # Optional: for Absolute Urls.
theme:
name: material
palette:
primary: black
accent: cyan
logo: assets/logo.png
favicon: assets/favicon.ico
features:
# - navigation.tabs
# - navigation.top
- content.action.edit # Shows "Edit this page" link.
# CRITICAL: Docs_Dir Must Point to Preprocessed Content.
docs_dir: tmp.mkdocs
# Helps Render Images and Other Assets Correctly.
use_directory_urls: false
# Plugins - Search Is Enabled by Default, but Must Be Explicit If You Add Others.
plugins:
- search
# Markdown Extensions for Enhanced Functionality.
markdown_extensions:
- toc:
permalink: "#"
baselevel: 2
separator: "_"
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
# Custom CSS.
extra_css:
- styles/styles.css
Example at: Helpers repo mkdocs
Key Configuration Options#
site_name
- Required: The name of your documentation site
- Appears in the browser title and site header
- Example:
"Helpers Documentation","Causify Docs"
site_url
- Optional but recommended for SEO and absolute URLs
- Format:
https://yourdomain.com/path - Not needed for GitHub Pages (auto-detected)
theme
- We use Material theme for all documentation
- Colors:
primary: black,accent: cyan(Causify brand colors) - Logo and favicon paths relative to
docs_dir
docs_dir
- CRITICAL: Must be
tmp.mkdocs(preprocessed content) - Never point directly to
docs/- preprocessing is required
use_directory_urls: false
- Ensures clean URLs work with S3 static hosting
- Pages are
page.htmlinstead ofpage/index.html - Required for S3/CloudFront setup
plugins
search: Enables full-text search (include explicitly if adding others)- For blogs, add the
blogplugin here
markdown_extensions
- Table of contents with permalink support
pymdownx.superfences: Code blocks with syntax highlighting and mermaid diagrams
extra_css
- Path to custom stylesheet (relative to
docs_dir) - Should point to
styles/styles.css(symlinked from canonical)
Preprocessing#
What Preprocessing Does#
The preprocessing script (preprocess_mkdocs.py) transforms raw markdown files
before MkDocs builds them. It performs:
- Removes table of contents blocks
- Strips content between markers
-
MkDocs generates its own navigation
-
Dedents Python code blocks
- Ensures code is properly aligned
-
Fixes indentation issues that break rendering
-
Standardizes indentation
- Converts 2-space indentation to 4 spaces
-
Maintains consistent code formatting
-
Processes markdown syntax
- Handles mermaid diagrams
- Processes PlantUML blocks
-
Other markdown transformations via
hmkdocshelpers -
Copies and processes directory structure
- Creates
tmp.mkdocs/with all processed files - Preserves directory structure
- Copies assets and styles
Running Preprocessing Manually#
Basic usage:
python helpers_root/docs/mkdocs/preprocess_mkdocs.py \
--input_dir docs \
--output_dir tmp.mkdocs \
-v INFO
Examples#
Causify Documentation (S3 + Custom Domain):
- Repository: https://github.com/causify-ai/csfy
- Live site: https://docs.causify.ai (VPN required)
- Workflow:
.github/workflows/publish_mkdocs.yml - Configuration:
docs_mkdocs/mkdocs.yml
Helpers Documentation (GitHub Pages):
- Repository: https://github.com/causify-ai/helpers
- Live site: https://causify-ai.github.io/helpers
- Workflow:
.github/workflows/publish_mkdocs.yml - Configuration:
/docs/mkdocs/mkdocs.yml - Example: https://github.com/causify-ai/helpers/blob/master/docs/mkdocs/mkdocs.yml
Causify Blog (S3 + Custom Domain):
- Repository: https://github.com/causify-ai/csfy
- Live site: https://blog.causify.ai
- Workflow:
.github/workflows/publish_blog.yml - Configuration:
blog/mkdocs.yml - Note: Blogs don't use preprocessing