Skip to content

Customization Guide

DocsForge provides powerful customization options beyond the basic configuration. This guide covers advanced techniques for tailoring your site's appearance, behavior, and functionality.


Custom CSS

Add custom stylesheets via the extra_css setting in docsforge.yml:

extra_css:
  - stylesheets/extra.css

Create docs/stylesheets/extra.css:

/* Custom brand color */
:root {
  --md-primary-fg-color: #4051b5;
  --md-primary-fg-color--light: #5d6cc0;
  --md-primary-fg-color--dark: #2e3b8e;
}

/* Custom font for headings */
.md-typeset h1,
.md-typeset h2 {
  font-family: 'Georgia', serif;
  font-weight: 700;
}

/* Wider content area */
@media screen and (min-width: 76.25em) {
  .md-content {
    max-width: 900px;
  }
}

Overriding theme variables

DocsForge uses CSS custom properties for theming. Override them in your custom CSS:

VariableDescription
--md-primary-fg-colorPrimary color
--md-primary-fg-color--lightLight variant
--md-primary-fg-color--darkDark variant
--md-accent-fg-colorAccent color
--md-typeset-colorBody text color
--md-typeset-a-colorLink color
--md-code-fg-colorCode text color
--md-code-bg-colorCode background
--md-default-fg-colorDefault foreground
--md-default-bg-colorDefault background

Custom JavaScript

Add custom scripts via extra_javascript:

extra_javascript:
  - javascripts/extra.js

Create docs/javascripts/extra.js:

// Custom behavior on page load
document.addEventListener('DOMContentLoaded', function() {
  // Add copy button to all tables
  const tables = document.querySelectorAll('.md-typeset table');
  tables.forEach(table => {
    const button = document.createElement('button');
    button.className = 'md-clipboard';
    button.innerHTML = 'Copy';
    button.addEventListener('click', () => {
      navigator.clipboard.writeText(table.innerText);
    });
    table.parentElement.insertBefore(button, table);
  });
});

Hooking into DocsForge events

// Listen for search events
window.addEventListener('docsforge-search', function(e) {
  console.log('Search query:', e.detail.query);
});

// Listen for theme changes
window.addEventListener('docsforge-theme', function(e) {
  console.log('Theme changed to:', e.detail.scheme);
});

Custom Templates

Override built-in templates by creating an overrides directory and referencing it in docsforge.yml:

custom_dir: overrides

Override partials

Create docs/overrides/partials/copyright.html:

<!-- Custom copyright notice -->
<div class="md-copyright">
  <strong>My Company</strong> β€” 
  <a href="{{ config.repo_url }}" target="_blank" rel="noopener">
    {{ config.repo_name }}
  </a>
</div>

Override base template

Create docs/overrides/main.html to extend the base template:

{% extends "base.html" %}

{% block extrahead %}
  {{ super() }}
  <meta property="og:image" content="{{ config.site_url }}assets/social-card.png">
{% endblock %}

{% block announce %}
  <div class="announcement">
    πŸŽ‰ New version released! <a href="/changelog">See what's new</a>
  </div>
{% endblock %}

Available blocks

BlockDescription
extraheadInside <head> tag
announceAnnouncement banner
headerSite header
tabsNavigation tabs
contentMain content area
footerPage footer
outdatedOutdated version notice

Custom Admonitions

Define custom admonition types with CSS:

/* Custom "tip" admonition in brand color */
.md-typeset .admonition.tip {
  border-color: #4051b5;
}

.md-typeset .admonition.tip > .admonition-title {
  background-color: rgba(64, 81, 181, 0.1);
  color: #4051b5;
}

.md-typeset .admonition.tip > .admonition-title::before {
  background-color: #4051b5;
  -webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>');
  mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>');
}

Usage in Markdown:

!!! tip "Custom Tip"
    This uses your brand color!

Custom Icons and Logos

Use an SVG for crisp rendering at any size:

logo: assets/logo.svg

The SVG should be optimized and have viewBox for proper scaling.

Custom icon definitions

Define custom icons in extra.css:

.md-icon--custom::after {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  background-image: url("assets/custom-icon.svg");
  background-size: contain;
  vertical-align: middle;
}

Custom Fonts

Self-hosted fonts

Place font files in docs/assets/fonts/ and define them in CSS:

@font-face {
  font-family: 'CustomFont';
  src: url('../assets/fonts/CustomFont.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --md-text-font: 'CustomFont', 'Roboto', sans-serif;
}

Custom 404 Page

Create docs/overrides/404.html:

{% extends "base.html" %}

{% block content %}
  <div class="md-content__inner">
    <h1>404 β€” Page Not Found</h1>
    <p>The page you requested doesn't exist.</p>
    <a href="{{ nav.homepage.url | url }}" class="md-button md-button--primary">
      Go Home
    </a>
  </div>
{% endblock %}

Performance Tuning

Lazy loading images

Images are lazy-loaded by default. For above-the-fold images, use loading="eager":

![Hero image](hero.png){ loading=eager }

Image optimization

Optimize images before adding them to docs/:

# Convert to WebP for smaller size
ffmpeg -i image.png image.webp

# Or use ImageMagick
convert image.png -quality 85 image.webp

Preload critical resources

{% block extrahead %}
  {{ super() }}
  <link rel="preload" href="{{ 'assets/fonts/CustomFont.woff2' | url }}" as="font" type="font/woff2" crossorigin>
{% endblock %}

Accessibility

Color contrast

Ensure your custom colors meet WCAG AA standards (4.5:1 for normal text, 3:1 for large text). Test with a contrast checker.

Keyboard navigation

DocsForge supports keyboard navigation out of the box. Custom interactive elements should handle Tab, Enter, and Escape keys.

ARIA labels

<button class="md-button" aria-label="Close announcement">
  <span class="md-icon">close</span>
</button>

Multi-language Sites

DocsForge does not include a built-in internationalization plugin. You have two practical options:

Option 1: Build separate sites per language

Maintain a docsforge.yml for each language and build them independently:

docs/
β”œβ”€β”€ en/
β”‚   └── index.md
β”œβ”€β”€ de/
β”‚   └── index.md
└── fr/
    └── index.md

Use a small build script to output each language to a separate subdirectory.

Option 2: Use a third-party i18n plugin

Install a MkDocs-compatible i18n plugin and declare it under plugins::

plugins:
  - i18n:
      languages:
        - locale: en
          name: English
          default: true
        - locale: de
          name: Deutsch
        - locale: fr
          name: FranΓ§ais

Compatibility

Third-party MkDocs plugins may need to be adapted for DocsForge. Test thoroughly before relying on them in production.


Analytics Integration

Google Analytics 4

extra:
  analytics:
    provider: google
    property: G-XXXXXXXXXX

Plausible

extra:
  analytics:
    provider: plausible
    property: docs.example.com

Custom analytics

{% block extrahead %}
  {{ super() }}
  <script async src="https://analytics.example.com/script.js" data-site="YOUR_SITE_ID"></script>
{% endblock %}

Social Cards

DocsForge generates social cards automatically. For custom control, override in templates:

{% block extrahead %}
  {{ super() }}
  <meta property="og:title" content="{{ page.title | default(config.site_name) }}">
  <meta property="og:description" content="{{ page.meta.description | default(config.site_description) }}">
  <meta property="og:image" content="{{ config.site_url }}assets/social-card.png">
  <meta name="twitter:card" content="summary_large_image">
{% endblock %}

Build Hooks

Pre-build script

Run a script before building:

#!/bin/bash
# scripts/pre-build.sh
python scripts/generate-api-docs.py
# docsforge.yml
hooks:
  pre-build:
    - scripts/pre-build.sh

Post-build script

#!/bin/bash
# scripts/post-build.sh
rsync -av site/ production-server:/var/www/docs/
hooks:
  post-build:
    - scripts/post-build.sh