This documentation is also published as Markdown for efficient machine reading: the whole site is indexed at /llms.txt, and every page has a clean Markdown copy under /_llms/. These are generated from the same source and cost far fewer tokens to read than this rendered HTML.

Skip to main content

A static content engine for .NET

A static site your .NET project deserves.
Without leaving the SDK.

Markdown in, static site out. No Node, no npm, no bundler — just dotnet run. Pennington ships content at the speed of your build.

Your content
/content
M↓ index.md .md
@ Layout.razor .razor
hero.png .png
{} site.json .json
# theme.css .css
M↓ guide.md .md
Pennington Server
ASP.NET · Kestrel
dotnet run
one server · two outputs
<> .html<> .html
Development interactive · hot reload
localhost:5000
hero.png
Deployment static html · shipped
<> index.html
<> guide.html
<> blog.html
<> api.html
dotnet run -- build → output

One ASP.NET server, two outputs — a live, hot-reloading site while you write, and the flat HTML you ship when you build. The getting-started tutorial wires it up from dotnet new web.

Quickstart

Add Pennington to an ASP.NET project.

Start from dotnet new web, add the package, and wire AddPennington. The tutorial walks every line.

Walk through the full tutorial
1

Create an ASP.NET host

$ dotnet new web -n my-site
2

Add the Pennington package

$ dotnet add package Pennington
3

Wire AddPennington, then run

$ cd my-site && dotnet run

Familiar on purpose

Pick up where your dotnet habits already are.

No new CLI to learn, no build tool to babysit. Open the solution, hit F5, and you're shipping content. Your layouts are Razor components. Your config is a C# record. Your deploy target is whatever you'd deploy an ASP.NET app to.

One .slnx

Your docs are a project in the same solution. Add a <ProjectReference> to the code you document — samples and API reference come straight from the source.

Config in C#

A POCO with real types. IntelliSense, refactoring, and compile errors instead of silent YAML typos.

Live in dev. Flat in prod.

Dev mode is a live ASP.NET app with hot reload. Build mode crawls its own routes and writes flat files. Same code, two outputs.

The dev loop

Edit. Save. See it.

Run dotnet run once. Markdown, front matter, navigation, cross-references, and Razor components all hot-reload. The feedback loop is the one you already trust for web apps — pointed at your content.

Content/index.md saved • just now
---
title: Release notes
order: 1
---

## Shipping v1.2

Now with <Badge Variant="Success">faster builds</Badge>
and a rewritten navigation tree.
localhost:5000 live

Shipping v1.2

Now with faster builds and a rewritten navigation tree.

Nav

Tree rebuilt

Search

Index refreshed

Xrefs

Resolved

Content-first

The shell stays out of your way.

Layout, navigation, search, dark mode — handled. Your attention belongs on the content: Razor components inside your markdown, syntax highlighting from the same grammars your editor uses, and an API reference generated from your assemblies’ XML docs.

Your components. In your markdown.

Write a Razor component. Drop it in prose. Rendered at build time, no JS bundle required.

guide.md
## API Status

The ingest endpoint is <Badge Variant="Warning">beta</Badge>.
Read the <ApiLink Id="T:Ingest.Client" />
for the current shape.
rendered

API Status

The ingest endpoint is beta. Read the Ingest.Client for the current shape.

Pull real source into your docs.

Point at a file — or a single method by name — and the real declaration is pulled straight from your repo at build time. The sample can’t drift out of date, because it is the source.

writing.md
```csharp:symbol,bodyonly
src/BlogSiteServiceExtensions.cs > BlogSiteServiceExtensions.AddBlogSite
```
rendered
services.AddSingleton<IBlogContentService, BlogContentService>();
services.AddSingleton<BlogHomeRouteGenerator>();
services.AddSingleton<BlogArchiveRouteGenerator>();
services.AddSingleton<TagRouteGenerator>();
// …
return services;

Utility CSS, generated

Write Tailwind-style classes in your Razor and markdown. MonorailCSS scans them and emits exactly the CSS you used — in C#, at build time. No Tailwind CLI, no PostCSS, no purge step.

Rich Markdown

Tabbed code blocks, Mermaid, alerts, diff highlights, and focus lines. Shipped. Configurable.

All the bells and whistles

Search, RSS, sitemap, structured data, llms.txt, locale routing — all built in. Sensible defaults; reach for config only when you want it.

Where to next

Four doors in. Pick one.

The docs are split by what you’re trying to do: learn, solve, understand, or look something up.

Tutorials

Build it alongside us.

Step through a working site, one piece at a time.

How-to

Solve one thing.

Short recipes to get unstuck and back to work.

Explanation

See how it fits together.

Context and reasoning behind the moving parts.

Reference

Look it up.

The dry, complete listings — for when you need a name.