Plugins
Netdocs has a first-class C# plugin system. Plugins are enabled and configured in the
plugins array of appsettings.json, and run in the order listed.
"plugins": [
{ "name": "search", "options": { "lang": "en" } },
{ "name": "tags", "options": { "export": true } },
{ "name": "blog", "options": { "blog_dir": "blog/" } }
]
Plugins are opt-in
Unlike the theme and Markdown extensions, no plugin runs unless you list it in the
plugins array. There is no implicit default set — this keeps builds predictable and fast,
and means a plugin can never surprise you by activating on its own. The trade-off is that a
fresh appsettings.json starts minimal; use the recommended set below as a starting point.
Recommended configuration
Most sites want the majority of plugins enabled — they are inexpensive and only act on the
content that uses them (for example table-reader is a no-op on pages with no
read_csv directive). A good general-purpose starting point:
"plugins": [
{ "name": "search", "options": { "lang": "en" } },
{ "name": "meta" },
{ "name": "tags", "options": { "export": true } },
{ "name": "snippets" },
{ "name": "abbreviations" },
{ "name": "macros" },
{ "name": "table-reader" },
{ "name": "glightbox" },
{ "name": "git-revision-date", "options": { "enabled": true } },
{ "name": "redirects" },
{ "name": "rss" },
{ "name": "social" }
]
Add blog if you publish posts, file-filter for
environment-driven content gating, and link-notes if you want to
annotate outbound links (e.g. affiliate disclosures). A few plugins are intentionally left out of the "enable everything" default:
| Plugin | Why it's opt-in |
|---|---|
| blog | Only meaningful for sites with a blog/ posts directory. |
| social | Generates images (slower); best gated behind netdocs build --prod. |
| file-filter | Needs a .file-filter.yml and env vars to do anything. |
| link-notes | Requires you to declare your affiliate programs / link rules. |
| arithmatex / b64 | Enable when you actually use math or inline-image embedding. |
Ordering only matters for Markdown preprocessors (they transform source text in sequence); see each plugin page for its order. Plugins that emit assets or pages are order-independent.
Disabling a plugin per page
Every configured plugin runs on every page by default. To turn one off (or back on) for a single page, use its front matter. Two forms are supported — the map form wins, so it can re-enable a plugin that a list disabled:
---
title: Raw template snippet
plugins:
macros: false # don't run the macros preprocessor on this page
disable_plugins:
- table-reader # list form: turn these off
---
This is handy for pages that contain literal {{ … }} (which the macros plugin would
otherwise try to expand), or to skip table-reader/snippets on a
page that shouldn't be transformed. Only per-page hooks are gated: Markdown preprocessors and
per-page build hooks (e.g. search indexing). Global contributions — Markdig extensions and
content generators — are not page-scoped and always apply.
Built-in plugins
| Plugin | Purpose |
|---|---|
| search | Material-compatible search_index.json (page + per-section docs). |
| social | 1200×630 Open Graph social cards. |
| blog | Posts, paginated index, categories, archive, post metadata. |
| tags | Hierarchical tag index, shadow tags, tags.json export. |
| meta | Per-directory .meta.yml front-matter defaults. |
| snippets | --8<-- file includes. |
| abbreviations | Shared <abbr> definition files. |
| git-revision-date | Real created/updated dates from git. |
| redirects | Client-side redirect map. |
| glightbox | Image lightbox. |
| rss | RSS feed of blog posts. |
| file-filter | Env-driven label include/exclude. |
| macros | fileuri() / button() Markdown macros (mkdocs-macros subset). |
| table-reader | Expand read_csv() / read_table() into Markdown tables. |
| link-notes | Auto tooltip + footer disclosure for affiliate links. |
| b64 | Embed local images as inline data: URIs (pymdownx.b64). |
| arithmatex | LaTeX math typeset with MathJax (pymdownx.arithmatex). |
| typeset | Smart typography (curly quotes, en/em dashes, ellipses) via SmartyPants. |
How plugins hook into the build
A plugin implements IPlugin (with Configure) plus any of the opt-in hook interfaces
(IMarkdownPreprocessor, IMarkdigContributor, IContentGenerator, IBuildHook,
INavigationFilter, …). Rather than duplicate that here, see:
- Build lifecycle — a visual diagram of where each hook runs in the pipeline, so you know which interface to implement for a given job.
- Events & callbacks — the full reference for every hook interface, its method signatures, ordering, and when it fires.
- External plugins — how to ship a plugin as a separate DLL and load it via config.
See the source under src/Netdocs.Plugins/ for reference implementations.