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 at the same URL with .md appended. 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

Add a Razor landing page at the site root

Route a Razor component at / so a DocSite opens on a hand-built landing page, and swap the doc-page chrome for the sidebar-free FullWidthLayout.

By the end of this tutorial the DocSite at http://localhost:5000/ opens on a Razor landing page — a hero heading, a call to action, and two cards linking into the Guides area — laid out with the sidebar-free FullWidthLayout instead of the default doc-page chrome.

Along the way the tutorial covers routing a Razor component at /, why a @page "/" route wins over DocSite's catch-all, and swapping the layout a routed page renders inside.

Prerequisites

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


1. Clear the root so a Razor component can claim it

The host from Add doc pages and link between them binds one content area, guides, to the /guides/ tab. If you also followed Scaffold a documentation site with DocSite, a Content/index.md is serving the root — that's the markdown landing page this tutorial replaces with a routed Razor component. Delete it so the root is free, then confirm / returns a 404 before you route a component at it.

1

Delete Content/index.md

Remove the scaffold's root markdown page. With nothing bound to the root — no Content/index.md and no routed component pointed at / — a request to / returns a 404.

2

Run the host and visit the root

bash
dotnet run

Open http://localhost:5000/ in a browser.

Checkpoint


2. Route a Razor component at the root

A routed Razor component whose @page template is / owns the root URL. AddDocSite adds your project's assembly to the routing assemblies it hands both the live Blazor router and the static build's page scanner, so a @page component in your project is picked up by both with no extra wiring. And a literal / route is more specific than DocSite's own catch-all, so it wins the match.

1

Create Components/Index.razor

Create a Components/ folder at the project root and add Index.razor with a @page "/" directive and minimal markup.

razor
@page "/"
  
<h1>Pages &amp; Links</h1>
<p>The site root now renders a Razor component.</p>

The @page "/" directive is the whole wiring — no Program.cs change, no registration call.

2

Restart the host

A .razor edit is a compile change, so stop the host and run dotnet run again to pick up the new component.

Checkpoint

  • http://localhost:5000/ no longer 404s — it renders the Pages & Links heading.
  • The page is wrapped in the default doc-page chrome: a sidebar on the left and an outline rail on the right. The next unit replaces that layout.

3. Switch to the full-width layout

A routed component with no @layout directive renders inside DocSite's default, MainLayout — the three-column doc-page chrome with the sidebar and outline rail. A landing page wants the header and footer but not the navigation columns. FullWidthLayout is exactly that shape.

1

Add a @layout directive to Index.razor

Add one line under @page naming the layout by its full type name.

razor
@page "/"
@layout Pennington.DocSite.Components.Layout.FullWidthLayout
  
<h1>Pages &amp; Links</h1>
<p>The site root now renders a Razor component.</p>

FullWidthLayout keeps the DocSite header and footer and gives the page the full content width — no sidebar, no outline rail.

2

Restart the host

The @layout directive is another .razor edit, so stop the host and run dotnet run again to recompile.

Checkpoint

  • http://localhost:5000/ renders the heading across the full content width.
  • The sidebar and outline rail are gone; the DocSite header and footer remain.

4. Build out the landing page

With routing and layout settled, the component is plain Razor markup. Fill it with a hero, a call to action, and two cards linking into the Guides area. Styling is MonorailCSS utility classes using the semantic palette — primary, accent, base — with a dark: variant on every color-bearing utility.

1

Replace Index.razor with the finished landing page

razor
@page "/"
@layout Pennington.DocSite.Components.Layout.FullWidthLayout
@using Microsoft.AspNetCore.Components.Web
  
@* A Razor component named Index with @page "/" owns the root URL. DocSite
   registers this project's assembly in its routing assemblies, so the literal
   "/" route is picked up by both the live Blazor router and the static build —
   and it beats the catch-all in Pages.razor. @layout swaps the sidebar layout
   for FullWidthLayout, which keeps the header and footer but drops the nav. *@
  
<PageTitle>Pages &amp; Links</PageTitle>
  
<section class="py-12 lg:py-20">
    <p class="text-xs font-display font-semibold tracking-widest uppercase text-primary-600 dark:text-primary-400 mb-4">
        Pennington DocSite
    </p>
    <h1 class="font-display text-4xl lg:text-6xl font-bold tracking-tight text-base-900 dark:text-base-50 leading-tight mb-6 text-balance">
        A docs site with a front door.
    </h1>
    <p class="text-base lg:text-lg text-base-600 dark:text-base-400 max-w-2xl mb-8 leading-relaxed">
        Every guide in one place — installing Pennington, configuring the host,
        and the linking patterns that hold a documentation site together.
    </p>
    <div class="flex flex-wrap items-center gap-3">
        <a href="/guides/"
           class="inline-flex items-center font-display font-semibold bg-primary-600 hover:bg-primary-500 text-white rounded-xl px-6 py-3 transition-colors">
            Read the guides
        </a>
        <a href="https://github.com/usepennington/pennington"
           class="inline-flex items-center font-display font-semibold text-base-700 dark:text-base-200 hover:text-primary-700 dark:hover:text-primary-400 rounded-xl px-5 py-3 ring-1 ring-base-300 dark:ring-base-700 transition-colors">
            View on GitHub
        </a>
    </div>
</section>
  
<section class="pb-16 lg:pb-24">
    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
        <a href="/guides/install"
           class="rounded-2xl border border-base-200 dark:border-base-800 bg-base-50 dark:bg-base-900/50 p-6 transition-colors hover:border-primary-400 dark:hover:border-primary-500">
            <h2 class="font-display text-xl font-semibold text-base-900 dark:text-base-50 mb-2">
                Install Pennington
            </h2>
            <p class="text-sm text-base-600 dark:text-base-400 leading-relaxed">
                Add the package and stand up the DocSite host.
            </p>
        </a>
        <a href="/guides/configure"
           class="rounded-2xl border border-base-200 dark:border-base-800 bg-base-50 dark:bg-base-900/50 p-6 transition-colors hover:border-primary-400 dark:hover:border-primary-500">
            <h2 class="font-display text-xl font-semibold text-base-900 dark:text-base-50 mb-2">
                Configure the site
            </h2>
            <p class="text-sm text-base-600 dark:text-base-400 leading-relaxed">
                Set the title, footer, and area routing.
            </p>
        </a>
    </div>
</section>

The two cards link to /guides/install and /guides/configure — the pages built in Add doc pages and link between them. <PageTitle> sets the browser tab text, the same component DocSite uses on doc pages.

2

Restart the host and open the root

Stop the host and run dotnet run again to recompile the component, then open http://localhost:5000/.

Checkpoint

  • http://localhost:5000/ renders the hero heading, the Read the guides button, and two guide cards.
  • Clicking a card navigates to the matching guide page; the Read the guides button lands on /guides/.
  • Run dotnet run -- build — the static build's page scanner picks up the same @page "/" route and writes the landing page to output/index.html.

Summary

  • A Razor component with @page "/" owns the site root — AddDocSite already routes your project's assembly, so the directive is the whole wiring.
  • A literal / route beats DocSite's catch-all, and the same route is honored by both the live host and the static build.
  • A routed component defaults to MainLayout; a @layout directive naming FullWidthLayout drops the sidebar for a landing-page shape.
  • The component body is ordinary Razor styled with MonorailCSS — semantic palette utilities, dark: variants, and links straight into the content areas.