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 Skip to navigation
Getting Started

Scaffold a documentation site with DocSite

Stand up the DocSite template on an empty ASP.NET project and let a folder of markdown light up the sidebar.

By the end of this tutorial the DocSite host runs with a "Scaffold Docs" title, GitHub icon, and header/footer chrome — and a folder of markdown pages that show up in the sidebar on their own, with a landing page at the root.

AddDocSite wires a Divio-style documentation site — host, layout, navigation, styling — into one call; for what the template wires, where the wiring stops, and why DocSite and BlogSite can't share an app, read what the templates wire for you first.

Prerequisites

The DocSite template ships as a NuGet package built for .NET 10, so the stable .NET 10 SDK is all you need — no preview language flag. The .NET 11 beta SDK only matters if you later extend the pipeline by hand; see the SDK and the union shim.

  • .NET 10 SDK installed
  • A terminal and a text editor or IDE

The finished code for this tutorial lives in examples/DocSiteScaffoldExample.


1. Scaffold a new ASP.NET project

Start from an empty ASP.NET web project. DocSite ships everything from routing to the Razor layout, so the project shell is the only scaffolding needed before AddDocSite.

1

Create the web project

bash
dotnet new web -n DocSiteScaffold
cd DocSiteScaffold
2

Add the Pennington DocSite package

bash
dotnet add package Pennington.DocSite

Important

Pennington is in alpha — check NuGet for the current prerelease and pin every Pennington.* package to that same version.

Checkpoint

  • Run dotnet build — the empty project with the DocSite package added compiles before you touch Program.cs

2. Wire AddDocSite, UseDocSite, and RunDocSiteAsync

AddDocSite is a single DI call that registers Pennington core, MonorailCSS, SPA navigation, the content resolver, and the component that renders the page body into the layout — all driven from one options object. UseDocSite is its middleware counterpart; RunDocSiteAsync dispatches the host between dev-serve and static-build modes (see CLI and build arguments for the args contract).

1

Replace Program.cs with the three DocSite calls

AddDocSite takes a function that returns a fresh DocSiteOptions, and the template registers the markdown content reader for you — no separate AddMarkdownContent call. RunDocSiteAsync serves pages live in development and generates static HTML when invoked as dotnet run -- build.

csharp
var builder = WebApplication.CreateBuilder(args);
  
builder.Services.AddDocSite(() => new DocSiteOptions
{
    SiteTitle = "Scaffold Docs",
    SiteDescription = "A minimal DocSite scaffold built on AddDocSite.",
    GitHubUrl = "https://github.com/usepennington/pennington",
    HeaderContent = """<a href="/">Scaffold Docs</a>""",
    FooterContent = """<footer class="mt-16 py-8 text-center text-sm text-base-500">Built with Pennington DocSite.</footer>""",
});
  
var app = builder.Build();
  
app.UseDocSite(); 
  
await app.RunDocSiteAsync(args); 

The five fields populated here — SiteTitle, SiteDescription, GitHubUrl, HeaderContent, FooterContent — each surface in the rendered chrome as soon as they're set. DocSiteOptions carries many more fields; see Pennington.DocSite.DocSiteOptions for the full surface, and What the DocSite and BlogSite templates wire for you for what the template hard-codes.

Checkpoint

  • Run dotnet run and visit http://localhost:5000/
  • The DocSite layout renders: left sidebar, header with site title, search affordance, dark-mode toggle, GitHub icon linking to GitHubUrl, and the footer HTML from FooterContent

3. Add pages and watch the sidebar fill in

DocSite builds the sidebar from the shape of Content/. Drop a markdown file into a folder and it becomes a sidebar entry — no routing table, no registration call. A subfolder turns into a navigation group named after the folder.

1

Create a guides folder with a landing page

Under Content/, create a guides/ folder and add an index.md. The folder name becomes a Guides group in the sidebar, and index.md is the page it links to at /guides/.

markdown
---
title: Guides
description: Task walkthroughs and onboarding.
---
  
Walkthroughs and how-tos live in this folder. Every markdown file under
`Content/guides/` shows up as a page in the sidebar — the folder name becomes
the **Guides** group around them.
2

Add two pages inside the folder

Add two more files next to index.md. Each carries a title, a description, and an order: — the order: decides which sorts first. Dropping the files in the folder is the whole wiring.

markdown
---
title: Getting started
description: Install the package and run the site.
order: 1
---
  
Every markdown file under `Content/guides/` becomes a sidebar entry — no
routing table, no registration call. This page answers to
`/guides/getting-started`.
  
The folder name becomes the sidebar group; `order:` decides where the page
sorts inside it.
markdown
---
title: Configuration
description: Where DocSite reads its settings.
order: 2
---
  
A second page beside the first. Because it carries `order: 2`, it sorts below
*Getting started* (`order: 1`) under the **Guides** group in the sidebar.

Checkpoint

  • Run dotnet run and visit http://localhost:5000/guides/getting-started
  • The sidebar shows a Guides group with Getting started above Configuration — sorted by order:
  • The page you're viewing is highlighted in the sidebar; clicking Configuration swaps to it instantly

4. Give the root / a landing page

The pages under guides/ answer to /guides/..., but the root / has no page of its own yet — a request to / returns a 404. To serve the root, drop a markdown file at Content/index.md, next to the guides/ folder.

1

Author Content/index.md

Use the same DocSiteFrontMatter shape as any other page. What makes this page the root is its location — Content/index.md maps to /.

markdown
---
title: Welcome
description: Start here, then pick a guide.
---

Welcome to Scaffold Docs.

- [Getting started](/guides/getting-started) — install and run.
- [Configuration](/guides/configuration) — where settings live.

Checkpoint

  • http://localhost:5000/ returns the rendered Content/index.md page inside the DocSite chrome
  • Both links navigate into the guides/ pages and highlight them in the sidebar

Summary

  • An empty ASP.NET project picked up AddDocSite + UseDocSite + RunDocSiteAsync, and the full Razor chrome renders.
  • DocSiteOptions carries SiteTitle, SiteDescription, GitHubUrl, HeaderContent, and FooterContent, and each field appears in the rendered layout.
  • Markdown files under Content/ become sidebar entries with no extra wiring — a subfolder turns into a navigation group named after the folder, and order: sorts the pages inside it.
  • The root / is served by Content/index.md; without it, / returns a 404.
  • To split the sidebar into switchable areas and labeled sections, see Organize content with sections and areas. For what the template hard-codes, see What the DocSite and BlogSite templates wire for you.