Plugins
Most MkDocs plugins never touch a template, so they work with any theme. A handful do not: they expect the theme to render something they computed, or to handle a nav shape they created. Those are the ones worth checking.
This site is the check. mkdocs.yml in the repository root enables the plugins that need theme support, and CI builds it with --strict, so a regression breaks the build rather than quietly degrading a page. The candidates were taken from the MkDocs catalog, working down by popularity.
Plugins that need something from the theme
mkdocs-section-index
mkdocs-section-index folds guide/index.md into the Guide section itself, so a nav item ends up with both children and a url. A theme that renders "has children" as a plain section label makes that index page unreachable from the sidebar.
partials/nav-item.html checks nav_item.url and renders the label as a link when there is one. You can see it in the sidebar: Guide and Nested are both clickable.
A warning you can ignore
The plugin recognises supported themes by matching template file paths against a built-in list, so it logs
section-index plugin couldn't detect a supported theme to adapt.
for every third-party theme, including this one. Support here is native — nothing needs adapting — but the message is unavoidable from the theme side.
mkdocs-static-i18n
mkdocs-static-i18n rewrites theme.locale only for the themes it ships support for, which does not include third-party themes. Reading theme.locale alone therefore labels every translated page with the default language.
base.html prefers the i18n_page_locale variable the plugin puts on the page context, and falls back to theme.locale when the plugin is absent:
<html lang="{{ i18n_page_locale | default(config.theme.locale, true) }}">
The translated pages under /es/, /zh/, /hi/, /pt/, /ru/ and /fr/ carry the matching lang attribute. Pages with no *.<locale>.md translation fall back to their English source, which is the plugin's default behaviour.
When at least two configured languages have build: true, the header also renders a language selector. Its labels come from each language's name, and each entry stays on the same page in the target locale. This includes pages for which the plugin falls back to the default-language source. The selector is not rendered without mkdocs-static-i18n, for a single-language build, or on the static 404 page.
mkdocs-git-revision-date-localized
mkdocs-git-revision-date-localized reads the git log and stores the result in page.meta.git_revision_date_localized — and, with enable_creation_date: true, page.meta.git_creation_date_localized too. Nothing displays either unless the theme asks for it, so a theme without those lines makes the plugin look broken. partials/metadata.html prints both, as the "created" and "last updated" items of the metadata line under the page title.
mkdocs-git-authors
mkdocs-git-authors has the same shape: it puts git_page_authors on the page context as a string of HTML and leaves the display to the theme. The metadata line prints it alongside the dates.
mkdocs-rss-plugin
mkdocs-rss-plugin writes feed_rss_created.xml and feed_rss_updated.xml but adds no markup, so nothing points a reader at them. base.html emits the <link rel="alternate"> pair, taking the filenames from the plugin's own config rather than hardcoding them, since they are options.
The plugin is not enabled on this site — see Known plugin conflicts.
mike
mike keeps several documentation versions side by side and adds a version dropdown. It finds a theme's dropdown assets through the mike.themes entry point group and, for a theme it cannot find there, builds no selector at all and says nothing — the site deploys, the versions exist, and the only way to move between them is to edit the URL.
pyproject.toml registers mkdocs_primer.mike under that group, so mike picks up version-select.css and version-select.js from this package and copies them in. The selector lands in the header next to the site name and follows the color mode. Aliases resolve to their real version, so /latest/ shows 2.0 selected rather than an empty control.
That script reads the global base_url, which base.html declares unconditionally. It used to be declared only when the search plugin was enabled, which would have left the selector broken on a site without search.
mkdocs-print-site
mkdocs-print-site renders the whole site as one page using the active theme's templates, which works here. What it cannot do is supply print CSS: it ships one stylesheet per theme it knows about and warns Theme 'primer' not yet supported for the rest.
That is the theme's job anyway. theme.css carries an @media print block that drops the header, sidebar and pagination, releases the content column to full width, and keeps code blocks and tables from splitting across pages. It also pins the body text to Primer's light foreground color, because a visitor printing while in dark mode would otherwise get light gray text on white paper. That block applies to any page, with or without the plugin.
search
The built-in search plugin needs the theme to ship a search.html template and to load search/main.js with base_url in scope. Both are in the theme; the header search box appears whenever the plugin is enabled and disappears when it is not.
mkdocstrings
mkdocstrings emits its own markup with doc-* classes and leaves the styling to the theme. It renders legibly here because everything lands inside .markdown-body and picks up Primer's type scale, but the theme ships no dedicated doc-* rules — signatures and parameter tables use Primer's defaults. Reference is the page it generates.
Plugins that just work
These need nothing from the theme beyond well-formed HTML. The first group is enabled on this site, so that stays true:
| Plugin | What it does on this site |
|---|---|
| mkdocs-awesome-nav | Builds the nav from docs/.nav.yml instead of a nav: key. |
| mkdocs-glightbox | Opens the images on Elements in a lightbox. |
| mkdocs-minify-plugin | Minifies the HTML, CSS and JS of every page, including the theme's inline color-mode script. |
| mkdocs-redirects | /options/ redirects to Configuration. |
| mkdocs-macros-plugin | Renders Jinja in Markdown. This site is MkDocs Primer Theme, built with theme primer — that sentence comes from the plugin, not from Markdown. |
The second group was checked against the theme in a scratch build rather than wired into this site, because each one wants fixture content that would not earn its place in a theme's documentation:
| Plugin | Checked |
|---|---|
| mkdocs-swagger-ui-tag | <swagger-ui> tag expands, assets copied. |
| mkdocs-include-markdown-plugin | Snippet inlined. |
| markdown-exec | Code executed, output inlined. |
| mkdocs-table-reader-plugin | CSV rendered as a table. |
| mkdocs-markdownextradata-plugin | extra: values interpolated. |
| mkdocs-autolinks-plugin | Bare [file.md](file.md) links resolved. |
| mkdocs-encryptcontent-plugin | Page body encrypted with no plaintext left in the HTML, password form rendered, theme shell intact around it. |
| mkdocs-monorepo-plugin | Sub-project merged in through !include. |
material/group | Enables or disables a plugin group. With the built-in search inside it, the theme's search box correctly appears when the group is on and disappears when it is off. |
Nav- and file-level plugins — mkdocs-literate-nav, mkdocs-awesome-pages, mkdocs-exclude — never reach a template at all.
Known plugin conflicts
Not every failure is the theme's. Six worth knowing about, all reproducible under any theme.
Three of them are why this site is not the only build in the repository: the plugins involved cannot share a config with the ones already enabled here, so they get a site of their own under examples/, built with --strict by the same CI job.
The Examples page covers what each of them shows.
- mkdocs-rss-plugin with mkdocs-static-i18n — the RSS plugin rewrites its own
date_from_meta.default_timefrom a string to adatetimeduringon_config. The i18n plugin runson_configonce per language, so the second pass re-parses adatetimeand warns, aborting a--strictbuild. Demonstrated instead at examples/rss/. - mkdocs-gen-files with mkdocs-static-i18n — files created during
on_filesare not classified by the i18n plugin, which logsUnhandled file caseand drops them from the build. Demonstrated instead at examples/gen-files/, together with mkdocs-literate-nav, which would otherwise compete with mkdocs-awesome-nav for the nav. - Mermaid with
minify_html— Mermaid parses its source line by line, and the minifier collapses the newlines inside its<div>. The diagram renders as Syntax error in text and the build says nothing. Demonstrated instead at examples/diagrams/, which also covers mkdocs-charts-plugin and how both pick up the color mode. - mkdocs-monorepo without
repo_url— building a sub-project page raisesTypeError: join() missing 1 required positional argument. Settingrepo_urlandedit_uriavoids it. Reproduces identically under the built-inmkdocstheme. searchwith a default language that mkdocs-static-i18n does not list first — the i18n plugin runs one build pass per language, starting with the default one, and then walkslanguagesskipping whichever it just built. It compares each entry against the pass before it rather than against the default, so a default language listed anywhere but first is built twice and every one of its pages reaches the search plugin twice. The index carries the duplicates through to the search page, which lists each hit twice. Listing the default first avoids it, but the last pass is what writes the site's single404.htmlandsearch.html— so this site keepsenlast and drops the duplicate entries inhooks.pyinstead.material/searchwith a non-Material theme — Material's search plugin renderspartials/language.htmlthrough the active theme's Jinja environment. Under any theme that does not ship that template it raisesTemplateNotFoundand the build dies. Use the built-insearchplugin instead; the theme is built against that one.