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:
| Variable | Description |
|---|---|
--md-primary-fg-color | Primary color |
--md-primary-fg-color--light | Light variant |
--md-primary-fg-color--dark | Dark variant |
--md-accent-fg-color | Accent color |
--md-typeset-color | Body text color |
--md-typeset-a-color | Link color |
--md-code-fg-color | Code text color |
--md-code-bg-color | Code background |
--md-default-fg-color | Default foreground |
--md-default-bg-color | Default 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
| Block | Description |
|---|---|
extrahead | Inside <head> tag |
announce | Announcement banner |
header | Site header |
tabs | Navigation tabs |
content | Main content area |
footer | Page footer |
outdated | Outdated 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
SVG logo
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":
{ 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