A fast, flexible static site generator in .NET 11 — a reimplementation of the
Material for MkDocs experience with a
first-class C# plugin system. Site configuration lives in appsettings.json, and
the Markdown in docs/ builds with little to no change.
📖 Full documentation: https://xtremeownage.github.io/Netdocs/
Important
Netdocs is an AI-generated derivative work inspired by, and partially reusing
files from, MkDocs and
Material for MkDocs. Full credit for
the theme, its compiled CSS/JS, the lunr-based search, and the overall design goes to
Martin Donath (@squidfunk) and the Material for
MkDocs contributors. This project bundles their assets under
src/Netdocs.Theme.Material/assets/vendor/material/ and redistributes them unmodified
under the MIT License — see THIRD_PARTY_LICENSES/ and
LICENSE. If you want a supported, production-grade tool, use Material for
MkDocs directly and consider sponsoring it.
Well, you probably shouldn't. I vibe-coded this in one day after being dissatisfied with the performance of mkdocs building large sites with 200+ posts. No warranties, promises, or guarantees. The intention was a .NET replacement that was nearly fully compatible with my current project. If you're reading this, there's a good chance I succeeded and it met my expectations.
That said, use at your own risk. If PRs are submitted, I'll try to keep them maintained. If issues are created, there's a good chance I'll try to review them. But I have a day job and usually work on projects during the evenings. I stay very busy.
I don't see this project ever reaching the scale of mkdocs / mkdocs-material, and personally I hope it doesn't — despite being a software developer for 20+ years, I have no idea how to maintain the scale of work-items generated by mkdocs-material.
Contributions are welcomed. Donations are not accepted — I'm perfectly happy with a simple kudos or a hello in my Discord. Just make sure to tag me — due to work and life, I may or may not be responsive.
A rough, honest comparison with the popular static site generators. The headline difference is that Netdocs ships as a single self-contained binary — no Python, Ruby, or Node toolchain to install.
| Netdocs | Material for MkDocs | MkDocs | Jekyll | Hugo | |
|---|---|---|---|---|---|
| Runtime | .NET (single binary) | Python | Python | Ruby | Go (single binary) |
| Config format | appsettings.json |
mkdocs.yml |
mkdocs.yml |
_config.yml |
hugo.toml |
| Material theme | ✅ built-in | ✅ | ➖ theme | ➖ theme | ➖ theme |
| Plugin language | C# (.NET DLL) | Python | Python | Ruby | Go templates/modules |
| Live-reload dev server | ✅ | ✅ | ✅ | ✅ | ✅ |
| Incremental render cache | ✅ | ➖ | ➖ | ➖ | ✅ (fast) |
| Parallel rendering | ✅ | ➖ | ➖ | ➖ | ✅ |
| Built-in search | ✅ (lunr) | ✅ (lunr) | ✅ (lunr) | ➖ | ➖ |
| Social cards | ✅ | ✅ (insiders/CairoSVG) | ➖ | ➖ | ➖ |
mkdocs.yml compatibility |
✅ near-drop-in | n/a | n/a | ➖ | ➖ |
Netdocs targets near drop-in compatibility with an existing Material for MkDocs site —
the Markdown in docs/ builds with little to no change. If you want a supported,
production-grade tool, use Material for MkDocs directly.
- Material for MkDocs — © 2016-2025 Martin Donath. MIT. https://github.com/squidfunk/mkdocs-material
Vendored: compiled
main/paletteCSS,bundle.js, the search worker, and lunr. - MkDocs — the static-site-generator concepts and configuration model this project mirrors.
- lunr / lunr-languages — MIT, © Oliver Nightingale and contributors.
For the full list of derivative plugins and bundled libraries (with authors and
licenses), see ATTRIBUTIONS.md or the
Attributions page on the docs site.
See src/Netdocs.Theme.Material/assets/vendor/material/NOTICE.md
for the full list of vendored files and their origins.
Most users should grab a prebuilt binary from the releases page — no .NET SDK required.
Linux (Debian/Ubuntu — .deb):
curl -LO https://github.com/XtremeOwnage/Netdocs/releases/latest/download/netdocs_amd64.deb
sudo apt install ./netdocs_amd64.debLinux (Fedora/RHEL — .rpm):
sudo yum install https://github.com/XtremeOwnage/Netdocs/releases/latest/download/netdocs_x86_64.rpmLinux (portable, no package manager): download the self-contained netdocs binary
from the releases page, chmod +x netdocs, and put it on your PATH.
Windows: download netdocs.exe from the
releases page and run it
directly (optionally add its folder to PATH).
Docker:
docker run --rm -v ${PWD}:/site ghcr.io/xtremeownage/netdocs build --config /site/appsettings.jsonExact asset file names may vary by release — check the releases page for the build that matches your platform.
Once installed, run the netdocs binary directly:
# Build a site (looks for ./appsettings.json, or pass --config)
netdocs build --config ./appsettings.json
# Serve with live reload
netdocs serve --config ./appsettings.json --port 8000Building from source instead? See CONTRIBUTING.md — contributors use
dotnet run --project src/Netdocs.Cli -- build --config <path>, and in Visual Studio /
VS Code the F5 launch profiles build and serve the sample site with the debugger
attached.
Building in CI? Use the reusable action — no .NET setup required, it downloads the native binary for you:
- uses: XtremeOwnage/Netdocs@v1
with:
command: build
config: appsettings.json
args: --prod
# version: 1.0.0 # pin a release, or omit for 'latest'See Publishing → Using the Netdocs GitHub Action for the full input reference.
| Command | Description |
|---|---|
netdocs build |
Build the site to the configured output dir (site_dir). |
netdocs serve |
Kestrel dev server with file-watch rebuilds + WebSocket live reload. |
netdocs --version |
Print the installed Netdocs version and exit. |
Options: --config/-f, --port/-p, --clean, --strict, --prod, --verbose/-v.
Site config is the Netdocs section of appsettings.json (site name, theme, nav,
plugins, markdown extensions, extra). Logging is the standard .NET Logging section —
set per-category levels (e.g. "Build": "Debug", "Netdocs": "Trace"). The
--verbose flag forces Trace globally.
Netdocs.slnx
├─ src/
│ ├─ Netdocs.Abstractions/ Plugin contracts + page/site models (depends only on Markdig)
│ ├─ Netdocs.Core/ Config, discovery, Markdig pipeline, Scriban templating, build engine, dev server pieces
│ ├─ Netdocs.Plugins/ Built-in plugins (snippets, search, tags, blog, meta, rss, ...)
│ ├─ Netdocs.Theme.Material/ Scriban templates + theme assets (CSS/JS)
│ └─ Netdocs.Cli/ `netdocs build|serve`
└─ tests/
└─ Netdocs.Core.Tests/
Load appsettings.json (Netdocs section) → SiteConfig
→ Discover docs/** (respect .mkdocsignore + NavigationFilters)
→ Load plugins (config plugins + markdown-extension-backed like snippets)
→ OnBuildStart hooks
→ Content generators (blog index/archive/category, ...)
→ Preprocess markdown (snippets/auto-append, macros) [IMarkdownPreprocessor]
→ Parse + render (Markdig, per-thread pipeline) [IMarkdigContributor] [parallel]
→ Resolve navigation
→ Template render (Scriban + theme) [parallel] → emit HTML + 404
→ OnPageRendered hooks
→ Copy assets (theme + docs static + plugin files)
→ OnBuildComplete hooks (search_index.json, tags.json, rss)
Implement IPlugin plus any hook interfaces you need:
IMarkdownPreprocessor— transform raw Markdown (snippets, macros).IMarkdigContributor— add Markdig extensions.IContentGenerator— emit virtual pages (blog lists, tags).IBuildHook— lifecycle (OnBuildStart/OnPageRendered/OnBuildComplete).INavigationFilter— include/exclude pages.
Plugins are matched to appsettings.json plugin names via the CLI's PluginRegistry.
Templates are Scriban (.html) in
Netdocs.Theme.Material/templates. Member access is snake_case (page.title,
config.site_name). Override templates by pointing theme.custom_dir at a folder of
Scriban templates. (Material's Jinja2 overrides are detected and ignored — see the
theme reference.)
Core engine works end-to-end and powers a real 200+ page blog — static.xtremeownage.com/blog — building 243 pages and ~1,880 images in about 6 seconds (see benchmarks). See the documentation site for the full reference, plugin guides, and the build lifecycle.