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

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.