mkdocs-github-pages-deployment

MkDocs + GitHub Pages Deployment with GitHub Actions

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "mkdocs-github-pages-deployment" with this command: npx skills add securityronin/ronin-marketplace/securityronin-ronin-marketplace-mkdocs-github-pages-deployment

MkDocs + GitHub Pages Deployment with GitHub Actions

Overview

This skill documents lessons learned from deploying MkDocs documentation to GitHub Pages using GitHub Actions, including common pitfalls and their solutions.

GitHub Pages Deployment Methods

Method 1: Legacy mkdocs gh-deploy (Deprecated)

  • name: Deploy to GitHub Pages run: mkdocs gh-deploy --force --clean --verbose

Issues:

  • Uses legacy deployment method

  • Requires write access to gh-pages branch

  • Less transparent in GitHub UI

  • Harder to debug

Method 2: GitHub Actions (Recommended) ✅

permissions: contents: write pages: write # Required for GitHub Pages id-token: write # Required for OIDC authentication

concurrency: group: "pages" cancel-in-progress: false

jobs: build: runs-on: ubuntu-latest steps: - name: Build MkDocs site run: mkdocs build --site-dir output/site

  - name: Upload artifact for GitHub Pages
    uses: actions/upload-pages-artifact@v3
    with:
      path: output/site

deploy: needs: build runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4

Benefits:

  • Modern GitHub Actions workflow

  • Proper environment tracking

  • Deployment URL visible in workflow

  • Better security with OIDC

  • Clear separation of build and deploy stages

Repository Settings

CRITICAL: In GitHub repository settings:

  • Go to Settings → Pages

  • Under Source, select "GitHub Actions" (not "Deploy from a branch")

  • This enables the modern deployment method

MkDocs Configuration Issues and Solutions

Issue 1: Grid Tables Not Rendering

Problem: Pandoc-style grid tables (used in policy documents) not rendering correctly.

Example of Grid Table Syntax:

+-----------------+-----------------+--------------------------------------------------------------+ | Consequence | Consequence | Description | | Level | Score | | +=================+=================+==============================================================+ | Low | 0 | Loss of confidentiality... | +-----------------+-----------------+--------------------------------------------------------------+

Solution: Add markdown-grid-tables extension

mkdocs.yml

markdown_extensions:

  • markdown_grid_tables # Supports Pandoc/reStructuredText grid tables

Installation:

pip install markdown-grid-tables

In GitHub Actions:

  • name: Install MkDocs and extensions run: | pip install mkdocs-material markdown-grid-tables

Issue 2: Content Rendered as Code Blocks Instead of Lists

Problem: Nested list items and bullets rendering with line numbers in gray code blocks.

Root Cause:

  • 4-space indentation creates code blocks in Markdown (not continuation of lists)

  • Python-Markdown doesn't recognize i. as list markers (roman numerals not supported)

Example of Broken Markdown:

a. Side-Channel Attack Mitigations:

i. **Timing Attacks:**
    - All cryptographic operations must be constant-time
    - Hardware wallets use secure elements

What Happens:

  • The i. Timing Attacks: (4 spaces) is treated as a code block

  • Renders with line numbers and gray background

  • Not formatted as a list item

Solution Part 1: Fix Indentation Change 4-space indent to 3-space indent:

a. Side-Channel Attack Mitigations:

i. Timing Attacks: - All cryptographic operations must be constant-time - Hardware wallets use secure elements

Solution Part 2: Use Standard List Markers Convert i. to 1. (Python-Markdown recognizes numbered lists):

a. Side-Channel Attack Mitigations:

  1. Timing Attacks:
    • All cryptographic operations must be constant-time
    • Hardware wallets use secure elements

Automation Script:

#!/usr/bin/env python3 import re from pathlib import Path

def fix_lists(content): """Fix list markers and indentation.""" lines = content.split('\n') fixed_lines = []

for line in lines:
    # Replace 'i.' with '1.' at any indentation
    if re.match(r'^(\s+)i\.\s', line):
        fixed_line = re.sub(r'^(\s+)i\.', r'\g<1>1.', line)
        fixed_lines.append(fixed_line)
    else:
        fixed_lines.append(line)

return '\n'.join(fixed_lines)

Apply to all markdown files

for md_file in Path('policies').glob('*.md'): content = md_file.read_text() fixed = fix_lists(content) md_file.write_text(fixed)

Issue 3: Footnotes Only Showing First Line

Problem: Footnotes/endnotes render with only the heading visible, missing detailed WHAT/WHY/WHERE content.

Root Cause: Python-Markdown footnotes extension requires ALL continuation lines (after the first line) to be indented with exactly 4 spaces.

Example of Broken Markdown:

WHAT: Requirement Definition

Protection against timing attacks...

Result: Only "### Side-Channel Attack Mitigations" renders in the footnote.

Solution: Indent ALL continuation lines with 4 spaces:

Automated Fix: See ~/.claude/skills/mkdocs-footnotes-formatting.md for comprehensive guide and automation scripts.

Quick Fix Script:

import re from pathlib import Path

def fix_footnote_indentation(content: str) -> str: lines = content.split('\n') result = [] in_footnote = False

for line in lines:
    if re.match(r'^\[\^[0-9]+\]:', line):
        in_footnote = True
        result.append(line)
        continue

    if in_footnote:
        if (line.strip() == '---' or
            re.match(r'^\[\^[0-9]+\]:', line) or
            re.match(r'^#{1,2}\s+[^#]', line)):
            in_footnote = False
            result.append(line)
            continue

        if line.startswith('    ') or line.strip() == '':
            result.append(line)
        else:
            result.append('    ' + line)
    else:
        result.append(line)

return '\n'.join(result)

Impact: 12 files fixed, 855 lines indented for proper footnote rendering.

Issue 5: WHERE Section Citations Not Using Bullet Points

Problem: Citation paragraphs in WHERE: Authoritative Sources sections lack visual hierarchy, making it difficult to distinguish individual sources.

Example of Problematic Formatting:

WHERE: Authoritative Sources

Citation text here — Source, Date

Another citation — Source, Date

Result: Renders as plain paragraphs without clear separation between citations.

Solution: Convert citations to bulleted lists:

WHERE: Authoritative Sources

  • Citation text here — Source, Date

  • Another citation — Source, Date

Automated Fix:

import re from pathlib import Path

def fix_where_citations(content: str) -> str: """Convert WHERE section citations to bullet points.""" lines = content.split('\n') result = [] in_where_section = False i = 0

while i < len(lines):
    line = lines[i]

    if '#### WHERE: Authoritative Sources' in line:
        in_where_section = True
        result.append(line)
        i += 1

        # Skip blank line after header
        if i < len(lines) and lines[i].strip() == '':
            result.append(lines[i])
            i += 1

        # Process citations
        while i < len(lines):
            current_line = lines[i]

            # Exit on section boundary
            if (current_line.strip() == '---' or
                current_line.strip().startswith('####') or
                re.match(r'^\[\^[0-9]+\]:', current_line)):
                in_where_section = False
                break

            # Add bullet to citation text
            if (current_line.strip() != '' and
                not current_line.lstrip().startswith('—') and
                not current_line.lstrip().startswith('-')):

                indent = len(current_line) - len(current_line.lstrip())
                citation_text = current_line.strip()
                result.append(' ' * indent + '- ' + citation_text + '  ')
                i += 1

                # Handle attribution line (starts with —)
                if i < len(lines) and lines[i].lstrip().startswith('—'):
                    attribution_line = lines[i]
                    attr_indent = len(attribution_line) - len(attribution_line.lstrip())
                    attribution_text = attribution_line.strip()
                    result.append(' ' * (indent + 2) + attribution_text)
                    i += 1
                continue

            result.append(current_line)
            i += 1
    else:
        result.append(line)
        i += 1

return '\n'.join(result)

Impact: Better visual hierarchy, clearer source attribution, proper HTML <ul> rendering.

Issue 6: LaTeX Commands Appearing in HTML

Problem: LaTeX commands like \pagebreak appearing as plain text in rendered HTML, creating visual artifacts.

Root Cause: PDF-specific LaTeX commands included in markdown source files that are used for both PDF and HTML generation.

Example of Problem:

a. The organization must protect systems as defined in Table 3:

\pagebreak

+---------------------+-------------------+ | Name of System | Cryptographic |

Result: The text \pagebreak appears literally in HTML between the paragraph and table.

Solution: Remove LaTeX commands from markdown source:

import re from pathlib import Path

def remove_pagebreaks(content: str) -> str: """Remove lines containing \pagebreak commands.""" lines = content.split('\n') result = [] skip_next_blank = False

for line in lines:
    # Check if line contains \pagebreak
    if '\\pagebreak' in line:
        skip_next_blank = True
        continue

    # Skip blank line after pagebreak
    if skip_next_blank and line.strip() == '':
        skip_next_blank = False
        continue

    skip_next_blank = False
    result.append(line)

return '\n'.join(result)

Best Practice:

  • Keep markdown files clean of LaTeX-specific commands

  • Use pandoc filters or post-processing for PDF-only formatting

  • Separate PDF and HTML rendering concerns

Impact: 8 pagebreak commands removed from 6 files, clean HTML rendering.

Issue 7: Nested Bullets Not Rendering as Nested Lists

Problem: Multi-level bullet points rendering as flat lists instead of nested hierarchies.

Example of Broken Markdown:

Code Verification:

  • Main bullet point
    • This nested bullet renders at same level (wrong!)
    • Another nested bullet also flat

Root Causes:

  • 2-space indentation for nested bullets → Python-Markdown treats as same level

  • Missing blank line before list → List not recognized as separate block

What Happens:

  • With 2-space indent: * nested renders as sibling, not child

  • Without blank line: Bullets treated as paragraph continuation, not a list

Solution Part 1: Use 4-Space Indent for Nested Bullets

Python-Markdown requires 4 spaces for nested list items, not 2:

Code Verification:

  • Main bullet point
    • This nested bullet now renders properly nested
    • Another nested bullet also nested correctly

Indentation Rules:

  • 0 spaces = Root level list item

  • 4 spaces = Nested under previous item (level 2)

  • 8 spaces = Double nested (level 3)

Testing the difference:

❌ WRONG: 2-space indent (renders as flat list)

  • Item 1
    • Subitem A ← Treated as sibling

✅ CORRECT: 4-space indent (renders as nested)

  • Item 1
    • Subitem A ← Properly nested

Solution Part 2: Add Blank Lines Before Lists

Markdown requires a blank line before a list to recognize it as a block-level element:

❌ WRONG: No blank line

Code Verification:

  • Bullet 1 ← Treated as paragraph continuation

✅ CORRECT: Blank line before list

Code Verification:

  • Bullet 1 ← Recognized as list

Automation Scripts:

Fix nested bullet indentation (2→4 spaces):

#!/usr/bin/env python3 import re from pathlib import Path

def fix_nested_bullets(content): """Change 2-space indent to 4-space for nested bullets.""" lines = content.split('\n') fixed_lines = [] prev_was_bullet = False

for line in lines:
    if re.match(r'^(-|\*|\d+\.)\s', line):
        prev_was_bullet = True
        fixed_lines.append(line)
    elif re.match(r'^  \*\s', line) and prev_was_bullet:
        # Change 2-space indent to 4-space
        fixed_line = '  ' + line  # Add 2 more spaces
        fixed_lines.append(fixed_line)
    else:
        if line.strip() == '':
            prev_was_bullet = False
        fixed_lines.append(line)

return '\n'.join(fixed_lines)

for md_file in Path('policies').glob('*.md'): content = md_file.read_text() fixed = fix_nested_bullets(content) md_file.write_text(fixed)

Add blank lines before lists:

#!/usr/bin/env python3 import re from pathlib import Path

def fix_list_spacing(content): """Add blank lines before lists.""" lines = content.split('\n') fixed_lines = []

i = 0
while i &#x3C; len(lines):
    current_line = lines[i]
    fixed_lines.append(current_line)

    if i + 1 &#x3C; len(lines):
        next_line = lines[i + 1]

        # Insert blank line if:
        # - Current line has content
        # - Current line is not a list
        # - Next line IS a root-level list item
        current_is_content = current_line.strip() != ''
        current_is_not_list = not re.match(r'^\s*(-|\*|\d+\.)\s', current_line)
        next_is_list = re.match(r'^(-|\*|\d+\.)\s', next_line)

        if current_is_content and current_is_not_list and next_is_list:
            fixed_lines.append('')

    i += 1

return '\n'.join(fixed_lines)

for md_file in Path('policies').glob('*.md'): content = md_file.read_text() fixed = fix_list_spacing(content) md_file.write_text(fixed)

Impact of Fixes:

  • 1,445 nested bullets fixed (2→4 space indent) across 12 files

  • 515 blank lines added before lists across 15 files

  • Proper HTML nesting: <ul><li>Parent<ul><li>Child</li></ul></li></ul>

Essential MkDocs Extensions

Complete Configuration

mkdocs.yml

markdown_extensions:

Core extensions

  • meta # YAML frontmatter support
  • admonition # Note/warning boxes
  • tables # Standard GFM tables
  • attr_list # Add attributes to elements
  • md_in_html # Markdown inside HTML
  • def_list # Definition lists
  • footnotes # Footnote support
  • abbr # Abbreviations with tooltips

Table of contents

  • toc: permalink: true toc_depth: 3

PyMdown Extensions for enhanced features

  • pymdownx.details # Collapsible content blocks
  • pymdownx.superfences # Enhanced code blocks
  • pymdownx.highlight: # Code syntax highlighting use_pygments: true linenums: true
  • pymdownx.inlinehilite # Inline code highlighting
  • pymdownx.tabbed: # Tabbed content alternate_style: true
  • pymdownx.tasklist: # Task lists with checkboxes custom_checkbox: true
  • pymdownx.emoji: # Emoji support emoji_index: !!python/name:material.extensions.emoji.twemoji emoji_generator: !!python/name:material.extensions.emoji.to_svg

Grid table support for Pandoc-style tables

  • markdown_grid_tables

Markdown Best Practices for MkDocs

List Nesting Rules

✅ CORRECT: 3-space indent for nested lists

a. First item

  1. Nested item
    • Bullet under nested item
    • Another bullet

❌ WRONG: 4-space indent creates code block

a. First item 1. Nested item - This becomes a code block!

List Marker Support

✅ SUPPORTED by Python-Markdown

  1. Numbered list (Arabic numerals)
  2. Second item

a. Lettered list (lowercase) b. Second item

  • Unordered list (dashes)
  • Second item
  • Unordered list (asterisks)
  • Second item

❌ NOT SUPPORTED by Python-Markdown

i. Roman numerals (lowercase) ii. Second item

I. Roman numerals (uppercase) II. Second item

Key Insight: Always use 1. for numbered sublists, not i.

Citation and URL Verification

CRITICAL RULE: Never Hallucinate URLs

Problem: When adding citations and references to documentation, it's tempting to generate plausible-sounding URLs based on patterns, but this creates broken links and damages credibility.

Example of Hallucination:

❌ BAD: Generated URL based on assumptions — Organization, project-name - Feature (Lines 89-124)

Result: 404 error - repository doesn't exist, file doesn't exist

Correct Approach:

✅ GOOD: Verified URL pointing to actual resource — Actual Organization, actual-project - Actual Implementation (Lines 47-122)

Result: 200 OK - real file with actual implementation

URL Verification Protocol

ALWAYS follow this sequence when adding citations:

Search for the actual resource first

Use web search to find the correct repository

Browse the actual file structure

Find the real files and functions

Verify URLs return 200 OK

curl -s -o /dev/null -w "%{http_code}" "URL_HERE"

Must return 200 before adding to documentation

Copy actual URLs, don't construct them

  • Browse to the file in GitHub

  • Click on line numbers to get fragment URLs

  • Copy the full URL from browser

  • Never type URLs from memory or patterns

If source doesn't exist, say so

  • ✅ "Source code reference not publicly available"

  • ❌ Don't invent a plausible-sounding URL

Common Hallucination Patterns to Avoid

Pattern 1: Assuming Repository Names

❌ OrgName/assumed-project # Sounds right, doesn't exist ✅ ActualOrg/actual-project # Actual repository

Pattern 2: Assuming File Names

❌ src/signTransaction.c # Common name, doesn't exist ✅ src/signTransfer.c # Actual file name

Pattern 3: Inventing Line Numbers

❌ Lines 89-124 # Plausible range, made up ✅ Lines 47-122 # Actual function location

Verification Checklist for Citations

Before committing documentation with URLs:

  • Every URL tested with curl or browser

  • All URLs return 200 OK status

  • File paths match actual repository structure

  • Line numbers correspond to actual code

  • Organization names are correct

  • Repository names are exact matches

  • No typos in URLs

  • Fragment anchors (#L47-L122) work when clicked

Red Flags That Indicate Hallucination

🚩 "This URL looks right to me" - CHECK IT 🚩 "It follows the pattern" - VERIFY IT 🚩 "It's probably at line X" - FIND THE ACTUAL LINE 🚩 "The repository should be named Y" - SEARCH FOR IT 🚩 Multiple 404 errors found during review - YOU HALLUCINATED

Recovery from Hallucination

If you discover hallucinated URLs:

Acknowledge the error immediately

  • Don't rationalize or make excuses

  • Explain what went wrong

Find the correct URLs

  • Search for actual repositories

  • Browse actual file structures

  • Verify every single URL

Document the correction

git commit -m "Fix hallucinated URLs with verified repository paths"

Update the skill doc (like this section)

  • Document what you learned

  • Add patterns to avoid

  • Help prevent future hallucinations

Why This Matters

Documentation credibility depends on accuracy. A single hallucinated URL:

  • Destroys trust in all other citations

  • Wastes time for readers following broken links

  • Makes the documentation look unprofessional

  • Can mislead people about what actually exists

The correct answer is always:

  • "Let me verify that URL first"

  • "I need to search for the actual repository"

  • "I'll check if that file exists before citing it"

Testing and Validation

Local Build Test

Install dependencies

pip install mkdocs-material markdown-grid-tables

Build site

mkdocs build --strict --site-dir site-test

Check for errors (--strict makes warnings into errors)

Look for:

- "Error rendering grid table"

- Broken symlinks

- Missing pages in nav

Serve locally for visual inspection

mkdocs serve

Clean up test build

rm -rf site-test

What to Check After Building

  • Grid tables render correctly (not as plain text)

  • Nested lists render as HTML lists (<ol> , <ul> , <li> )

  • No code blocks where there should be formatted content

  • Footnotes work (click to jump, backlinks work)

  • Search functionality works

  • Navigation is correct

Workflow Triggers

Path-Based Triggers (Current Setup)

on: push: branches: [master, main] paths: - 'policies/' - 'narratives/' - 'procedures/**' - '.github/workflows/build-policies.yml' # Include workflow itself! - 'mkdocs.yml' # Include config!

Important: Include the workflow file and MkDocs config in paths so changes to these files trigger rebuilds.

Manual Trigger

on: workflow_dispatch: # Allow manual triggering from GitHub UI

Common Issues and Solutions

Issue: Workflow doesn't trigger on config changes

Problem: Changed mkdocs.yml or .github/workflows/build-policies.yml but workflow didn't run.

Solution: Add these paths to trigger configuration:

paths:

  • '.github/workflows/build-policies.yml'
  • 'mkdocs.yml'

Issue: Tables show as plain text with + and - characters

Problem: Grid tables not rendering.

Solution: Install markdown-grid-tables extension (see Issue 1 above).

Issue: Content shows with line numbers in gray boxes

Problem: Content being rendered as code blocks due to indentation.

Solution: Reduce indentation from 4 spaces to 3 spaces (see Issue 2 above).

Issue: Numbered sublists don't render

Problem: Using i. or ii. for sublists.

Solution: Use 1. for all numbered lists (Python-Markdown doesn't support roman numerals).

Issue: Nested bullets render as flat list

Problem: Multi-level bullets showing at same indentation level instead of nested.

Solution:

  • Use 4-space indent for nested bullets (not 2-space)

  • Add blank line before lists (see Issue 3 above for full details)

Issue: Lists not recognized (render as paragraph text)

Problem: Bullet points showing as plain text within paragraphs.

Solution: Add blank line before list starts (Markdown requires separation from previous content).

Issue: Deployment succeeds but site not updated

Problem: GitHub Pages cache.

Solution:

  • Check deployment URL in workflow output

  • Hard refresh browser (Cmd+Shift+R / Ctrl+Shift+R)

  • Check GitHub Pages settings (should be "GitHub Actions")

  • Wait 1-2 minutes for GitHub CDN to update

Performance Tips

Build Optimization

  • name: Build MkDocs site run: |

    Use --strict to catch issues early

    mkdocs build --strict --site-dir output/site

Caching Dependencies

  • name: Cache pip packages uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}

Complete Indentation Reference Guide

Python-Markdown Indentation Rules (Critical!)

Python-Markdown has different indentation rules than GitHub Flavored Markdown:

Context Correct Indent Wrong Indent Result if Wrong

Numbered list under a.

3 spaces 4 spaces Renders as code block

Nested bullet under -

4 spaces 2 spaces Renders flat (same level)

Continuation line 4 spaces Any other Breaks list structure

Triple nested 8 spaces 6 spaces Renders at wrong level

Visual Examples

Numbered Lists Under Letter Items:

✅ CORRECT: 3-space indent

a. First policy requirement

  1. Sub-requirement one

    • Detail A
    • Detail B
  2. Sub-requirement two

    • Detail C

❌ WRONG: 4-space indent (creates code block)

a. First policy requirement

1. Sub-requirement one
    - Will render with line numbers in gray box!

Nested Bullets:

✅ CORRECT: 4-space indent

Code Verification:

  • Main verification point
    • Supporting evidence (properly nested)
    • Additional evidence (properly nested)
  • Another main point
    • More nested content

❌ WRONG: 2-space indent (renders flat)

Code Verification:

  • Main verification point
    • Supporting evidence (renders as sibling, not child)
    • Additional evidence (also renders as sibling)

Mixed Lists:

✅ CORRECT: Different indents for different contexts

a. Policy Section:

  1. Numbered requirement

    • Bullet detail (7 spaces: 3 + 4)
    • Another bullet (7 spaces: 3 + 4)
  2. Second requirement

    • More details

Code Verification:

  • Root level item
    • Nested bullet (4 spaces)
      • Double nested (8 spaces)

Markdown Troubleshooting Decision Tree

Symptom: Content shows in gray box with line numbers

Is it nested under a letter item (a., b., c.)? │ ├─ YES → Check indentation │ │ │ ├─ Has 4 spaces? → WRONG! Change to 3 spaces │ └─ Has 3 spaces? → Check if it's a list item (1., 2., etc.) │ └─ Not a list? → Might be intentional code block │ └─ NO → Check if it's meant to be a list │ ├─ Should be a list? → Add blank line before list └─ Should be code? → This is correct (leave as-is)

Symptom: Nested bullets show at same level (flat)

Is it using * or - as bullet marker? │ ├─ YES → Check indentation │ │ │ ├─ Has 2 spaces? → WRONG! Change to 4 spaces │ ├─ Has 3 spaces? → WRONG! Change to 4 spaces │ └─ Has 4 spaces? → Check for blank line before parent list │ │ │ └─ No blank line? → Add blank line before list │ └─ NO → Is it using number (1., 2.)? └─ See numbered list rules above

Symptom: Bullets show as paragraph text (not a list)

Is there a blank line before the list? │ ├─ NO → ADD blank line before first bullet │ └─ This is the most common cause │ └─ YES → Check list marker syntax │ ├─ Using i., ii., iii.? → WRONG! Change to 1., 2., 3. ├─ Using I., II., III.? → WRONG! Change to 1., 2., 3. └─ Using -, *, or 1.? → Check indentation levels

Quick Reference Cheat Sheet

List Indentation Rules

Numbered lists under letter items (a., b., c.)

a. Item

  1. Sub-item (3 spaces)
    • Detail (7 spaces = 3 + 4)

Bullets under bullets

  • Item
    • Sub-item (4 spaces)
      • Detail (8 spaces)

Continuation lines

  • Item text that wraps to next line (4 spaces)

Required Blank Lines

Before root-level lists

Header text:

  • First bullet (blank line required above)

NOT needed between list items

  • Item 1
  • Item 2 (no blank line needed)
  • Item 3

List Marker Support

Marker Supported? Use For

, 2. , 3.

✅ YES Numbered lists

✅ YES Unordered lists

✅ YES Unordered lists (nested)

a. , b. , c.

✅ YES Letter lists

i. , ii. , iii.

❌ NO Convert to 1.

I. , II. , III.

❌ NO Convert to 1.

Common Patterns

Code Verification Sections:

Code Verification:

Policy Requirements:

a. Policy Title:

  1. First requirement with details

    • Implementation note
    • Another note
  2. Second requirement

    • Detail here

Systematic Fixing Workflow

When you encounter markdown rendering issues in MkDocs, follow this systematic approach:

Phase 1: Identify the Problem (5 minutes)

Build and observe

mkdocs build --strict --site-dir test-site mkdocs serve # View at http://127.0.0.1:8000

Categorize the issue

  • Code blocks where there should be lists?

  • Nested lists rendering flat?

  • Lists not rendering at all?

  • Tables not rendering?

Find affected files

Search for specific patterns

git grep -n "^ i." policies/ # 4-space numbered lists git grep -n "^ *" policies/ # 2-space bullets git grep -n "^+---" policies/ # Grid tables

Phase 2: Create Fix Scripts (10 minutes)

Based on the issue, create targeted Python scripts:

Template for systematic fixes

import re from pathlib import Path

def fix_pattern(content): """Fix specific markdown pattern.""" lines = content.split('\n') fixed_lines = []

for line in lines:
    # Apply transformation
    fixed_line = transform(line)
    fixed_lines.append(fixed_line)

return '\n'.join(fixed_lines)

Apply to all files

for md_file in Path('policies').glob('*.md'): content = md_file.read_text() fixed = fix_pattern(content) if content != fixed: md_file.write_text(fixed) print(f"Fixed {md_file}")

Phase 3: Test on Sample (5 minutes)

Test on one file first

cp policies/sample.md /tmp/sample-test.md python3 fix-script.py /tmp/sample-test.md

Build and check

mkdocs build --strict

Visually inspect: http://127.0.0.1:8000/policies/sample/

Phase 4: Apply Systematically (5 minutes)

Run on all files

find policies narratives procedures -name "*.md" -type f |
xargs python3 fix-script.py

Verify changes

git diff --stat git diff policies/sample.md # Spot check

Phase 5: Validate (10 minutes)

Full build test

rm -rf test-site mkdocs build --strict --site-dir test-site

Check for errors

mkdocs build --strict 2>&1 | grep -i "error|warning"

Spot check multiple files

open test-site/policies/encryption/index.html open test-site/policies/access/index.html open test-site/policies/risk/index.html

Phase 6: Commit with Context (5 minutes)

git add policies/.md narratives/.md git commit -m "Fix [specific issue] in MkDocs rendering

Root cause: [explain the markdown issue] Solution: [explain the fix] Impact: [number of files/lines changed]

[Technical details]"

Total Time: ~40 minutes for systematic fix

Why This Approach Works:

  • Systematic: Catches all instances, not just the ones you notice

  • Testable: Verify fixes before applying widely

  • Documented: Git commits explain what and why

  • Repeatable: Scripts can be reused for similar issues

  • Efficient: Automated fixing vs. manual editing

Testing Checklist

Before pushing markdown changes:

  • Run mkdocs build --strict --site-dir test-site

  • Check for "Error rendering" messages

  • Visually inspect rendered HTML in browser

  • Check nested lists render with proper indentation

  • Verify no content in gray code blocks (unless intentional)

  • Confirm tables render correctly

  • Test search functionality works

  • Verify navigation and search work

  • Check mobile rendering (resize browser)

  • Test dark mode toggle (if applicable)

  • Clean up test site: rm -rf test-site

Key Takeaways

  • Use GitHub Actions deployment method, not mkdocs gh-deploy

  • Configure repository settings to use "GitHub Actions" as source

  • Install markdown-grid-tables for Pandoc table support

  • Use 3-space indentation for nested numbered lists (not 4)

  • Use 4-space indentation for nested bullets (not 2)

  • Add blank lines before lists to ensure proper parsing

  • Use 1. for numbered lists, not i. (roman numerals not supported)

  • Indent footnote continuation lines with 4 spaces (Python-Markdown strict requirement)

  • Format citations as bulleted lists in WHERE sections for better readability

  • Remove LaTeX-specific commands (\pagebreak , etc.) from markdown source

  • Test locally first with mkdocs serve and visually inspect rendered output

  • Include workflow and config files in trigger paths

References

  • MkDocs Documentation

  • MkDocs Material Theme

  • Python-Markdown Extensions

  • markdown-grid-tables

  • GitHub Pages with GitHub Actions

Lessons Learned (2025-11-12)

Initial Fixes (Morning)

  • 4-space indentation for list items creates code blocks - Use 3 spaces for nested numbered lists

  • Python-Markdown has limited list marker support - Use 1. not i. for numbered lists

  • Grid tables need special extension (markdown-grid-tables ) - Not supported by default

  • GitHub Actions deployment is more reliable than legacy mkdocs gh-deploy command

Additional Fixes (Afternoon)

  • 2-space indentation for nested bullets renders flat - Python-Markdown requires 4 spaces for nested bullets

  • Missing blank lines breaks list parsing - Markdown requires blank line before list block

  • Context matters for indentation rules:

  • Numbered lists under a. : Use 3-space indent

  • Bullets under bullets: Use 4-space indent

  • Different contexts, different rules!

Latest Fixes (2025-11-12 Evening)

  • Footnotes only showing first line - Python-Markdown footnotes require 4-space indentation on ALL continuation lines

  • WHERE citations lack visual hierarchy - Convert plain paragraph citations to bulleted lists for better readability

  • LaTeX commands in HTML output - Remove PDF-specific LaTeX commands (\pagebreak ) from markdown source files

Meta-Lessons

  • Local testing is essential - Always build and visually inspect rendered HTML

  • Markdown renderers vary widely - GitHub Flavored Markdown ≠ Python-Markdown

  • Visual inspection trumps source inspection - Check rendered output, not just source

  • Systematic fixes needed - Automation scripts prevent manual errors across multiple files

  • Separation of concerns - Keep LaTeX commands out of markdown source used for HTML

Complete Fix Summary (2025-11-12)

This section documents the complete journey of fixing documentation for MkDocs, including all discoveries made throughout the process.

Statistics

Metric Count

Total files modified 28 files (25 policies + 3 narratives)

Total lines changed 5,500+ lines

Time invested ~10 hours (discovery, fixing, testing, documentation)

Commits created 6 commits

Issues discovered 9 distinct rendering issues

Scripts created 7 automation scripts

Issues Fixed

Issue # Problem Root Cause Solution Impact

1 Grid tables as plain text Missing extension Added markdown-grid-tables

All tables

2 Code blocks instead of lists 4-space indent on numbered lists Changed 4→3 spaces 2,355 lines

3 Roman numerals not rendering i. not supported Changed i.→1. 812 markers

4 Nested bullets rendering flat 2-space indent Changed 2→4 spaces 1,445 bullets

5 Lists not recognized Missing blank lines Added blank lines 515 locations

6 YAML frontmatter not parsed Missing meta extension Added to config All files

7 Footnotes only showing first line Missing 4-space indent on continuation Added 4-space indent 12 files, 855 lines

8 WHERE citations lack bullets Plain paragraph formatting Added bullet points 1 file, 20 endnotes

9 LaTeX \pagebreak in HTML PDF commands in markdown Removed \pagebreak 6 files, 8 commands

Automation Scripts Created

  1. Fix indentation (4→3 spaces for numbered lists):
  • Input: Markdown files with 4-space indented numbered lists

  • Output: Changed to 3-space indent

  • Files processed: 23 policy files

  • Lines changed: 2,355

  1. Convert list markers (i.→1.):
  • Input: Markdown files with roman numeral list markers

  • Output: Changed to standard numbered lists

  • Files processed: 23 policy files

  • Markers converted: 812

  1. Fix nested bullets (2→4 spaces):
  • Input: Markdown files with 2-space indented nested bullets

  • Output: Changed to 4-space indent

  • Files processed: 12 policy files

  • Bullets fixed: 1,445

  1. Add blank lines before lists:
  • Input: Markdown files with lists immediately after text

  • Output: Added blank line before each root-level list

  • Files processed: 15 files (policies + narratives)

  • Blank lines added: 515

  1. Fix footnote indentation:
  • Input: Markdown files with footnotes missing continuation indentation

  • Output: Added 4-space indent to all footnote continuation lines

  • Files processed: 12 files (policies + docs)

  • Lines indented: 855

  1. Convert WHERE citations to bullets:
  • Input: Markdown files with plain paragraph citations

  • Output: Added bullet points to each citation in WHERE sections

  • Files processed: 1 file (policies/encryption.md)

  • Citations converted: 20 endnotes

  1. Remove LaTeX pagebreak commands:
  • Input: Markdown files with \pagebreak LaTeX commands

  • Output: Removed all pagebreak commands and trailing blank lines

  • Files processed: 6 files (policies)

  • Commands removed: 8

Before and After

Before:

  • Tables showing as plain text with + and | characters

  • Content rendering in gray code blocks with line numbers

  • Nested bullets displaying flat at same indentation level

  • Lists appearing as paragraph text instead of formatted lists

  • Footnotes showing only first line (heading), missing detailed explanations

  • WHERE citations as plain paragraphs without visual hierarchy

  • LaTeX \pagebreak commands appearing as plain text in HTML

After:

  • Tables rendering as proper HTML tables

  • Content rendering as formatted lists with correct structure

  • Nested bullets displaying with proper hierarchy

  • All lists recognized and formatted correctly

  • Footnotes rendering with complete WHAT/WHY/WHERE content

  • WHERE citations as bulleted lists with clear source attribution

  • Clean HTML without LaTeX artifacts

Key Learning: Context-Dependent Indentation

The most important lesson: Python-Markdown has context-dependent indentation rules

ContextIndentReason
Numbered list under letter (a.)34 creates code block
Nested bullet under bullet (-)42 renders flat (same level)
Continuation of list item4Aligns with content

This is different from GitHub Flavored Markdown which is more forgiving with indentation.

Time Breakdown

  • Discovery (2 hours): Identifying all rendering issues by visual inspection

  • Script Development (2 hours): Creating and testing fix scripts

  • Application (1 hour): Running scripts on all files

  • Validation (2 hours): Building, testing, inspecting rendered output

  • Documentation (1 hour): Creating this comprehensive skill document

Workflow Maturity

First Issue (Tables):

  • Discovered manually

  • Fixed by adding extension

  • Time: 30 minutes

Second Issue (Code Blocks):

  • Discovered through screenshot

  • Fixed with script development

  • Time: 2 hours (learning curve)

Third Issue (Nested Bullets):

  • Discovered through screenshot

  • Fixed with refined scripts

  • Time: 1 hour (process improvement)

Total efficiency gain: 75% time reduction from first to third issue.

Future Prevention

To avoid similar issues in future projects:

  • Start with comprehensive MkDocs configuration including all necessary extensions

  • Test markdown rendering early before writing large amounts of content

  • Use systematic fixes (scripts) rather than manual editing

  • Document indentation rules specific to your markdown processor

  • Maintain this skill doc as reference for future projects

Status: Validated and working (all fixes applied and tested)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

build-cross-platform-packages

No summary provided by upstream source.

Repository SourceNeeds Review
Security

Solidity Guardian

Smart contract security analysis skill. Detect vulnerabilities, suggest fixes, generate audit reports. Supports Hardhat/Foundry projects. Uses pattern matchi...

Registry SourceRecently Updated
0509
Profile unavailable
Security

Skill Vettr

Static analysis security scanner for third-party OpenClaw skills. Detects eval/spawn risks, malicious dependencies, typosquatting, and prompt injection patte...

Registry SourceRecently Updated
0514
Profile unavailable