---
title: Add doc pages and link between them
description: "Build out a Guides area with two content pages, wire sibling navigation, hub-style absolute links, and rename-safe uid cross-references."
canonical_url: https://usepennington.net/tutorials/docsite/first-doc-page/
sidecar_url: https://usepennington.net/tutorials/docsite/first-doc-page.md
content_hash: sha256:0323595c885e883c3fa0f63e0d6f2d8df51cd89982d20b66baf7053f9538add3
tokens: 2991
uid: tutorials.docsite.first-doc-page
reading_time_minutes: 5
---

Getting Started
# Add doc pages and link between them

Build out a Guides area with two content pages, wire sibling navigation, hub-style absolute links, and rename-safe uid cross-references.

 
By the end of this tutorial the Guides area has two new pages — `install.md` and `configure.md` — wired into the sidebar in `order:` sequence, cross-linked with relative paths, and reachable from a hub `index.md` that uses both absolute paths and a `uid:`-based `xref:` link.

 
## Prerequisites

 
 - .NET 10 SDK installed
 - Completed [Scaffold a DocSite](https://usepennington.net/tutorials/docsite/scaffold.md) (or have a DocSite project with a `Content/guides/` folder ready — this tutorial adds pages to it)
 
 
The finished code for this tutorial lives in [examples/DocSitePagesAndLinksExample](https://github.com/usepennington/pennington/tree/main/examples/DocSitePagesAndLinksExample).

 
---

 
## 1. Add two content pages

 
Let's drop two markdown files into the Guides area and watch them slot into the sidebar. The pages stand alone for now — linking arrives in the next unit.

 
**Create `Content/guides/install.md`**

 
Add a new file at `Content/guides/install.md` with the markdown below. The four front-matter keys are the ones [DocSiteFrontMatter](https://usepennington.net/reference/api/doc-site-front-matter.md) reads for sidebar wiring: `title` is the link label, `description` becomes the meta tag, `sectionLabel` carries through to breadcrumbs and prev/next chrome, and `order` decides where the page sorts among siblings.

 
````markdown:symbol
---
title: Install Pennington
description: Add the Pennington DocSite package and wire AddDocSite + UseDocSite into a fresh ASP.NET host.
sectionLabel: Guides
order: 20
---
  
# Install Pennington
  
Install Pennington into an ASP.NET project with one NuGet package and three lines of DI wiring.
  
## 1. Add the package
  
```bash
dotnet add package Pennington.DocSite
```
  
## 2. Wire DocSite in `Program.cs`
  
Three calls — register the services, mount the middleware, hand control to the host:
  
```csharp
builder.Services.AddDocSite(() => new DocSiteOptions { /* ... */ });
app.UseDocSite();
await app.RunDocSiteAsync(args);
```
  
The host is now ready for content. Drop markdown files under `Content/guides/` and they appear in the sidebar on the next request.
````

 
**Create `Content/guides/configure.md`**

 
Add a second file next to the first with the markdown below. Note `order: 30` — a larger number than install's `order: 20`, so configure sorts after install in the sidebar.

 
```markdown:symbol
---
title: Configure the site
description: Pick a site title, set the GitHub link, and decide on a single area or multiple.
sectionLabel: Guides
order: 30
---
  
# Configure the site
  
`DocSiteOptions` is the one options record `AddDocSite` reads. Set the fields that surface in the rendered chrome and the rest of the template falls into place.
  
## Fields worth setting first
  
- `SiteTitle` — appears in the header and the `<title>` tag.
- `Description` — meta description used in search snippets and social cards.
- `GitHubUrl` — surfaces the GitHub icon in the header.
- `HeaderContent` / `FooterContent` — raw HTML slots, useful for a logo and a copyright line.
  
## Areas — one or many?
  
`Areas` is an `IReadOnlyList<ContentArea>`. One entry is enough to ship; more entries turn on the area selector and split the sidebar by top-level folder. Stick with a single area until the content outgrows it.
```

 
For deeper coverage of section grouping and `order:` strategy, see [Organize content with sections and areas](https://usepennington.net/tutorials/docsite/sections-and-areas.md).

 
> [!CHECKPOINT]
>  - Run `dotnet run` and visit `http://localhost:5000/guides/install` — the Install Pennington page renders.
>  - Visit `http://localhost:5000/guides/configure` — the Configure the site page renders.
>  - The Guides sidebar lists both new pages, with **Install Pennington** above **Configure the site** (sorted by `order:`).

---

 
## 2. Link siblings with relative paths

 
Both pages exist but neither knows about the other. Adding a relative-path link at the bottom of each one creates a natural "previous / next" flow without hardcoding the area slug.

 
**Add a "Next" footer to `install.md`**

 
Append a `## Next` heading and a relative-path link to the bottom of `install.md`. `./configure` resolves against the current page's URL (`/guides/install`), so it points at `/guides/configure` no matter where the area sits.

 
````markdown:symbol
---
title: Install Pennington
description: Add the Pennington DocSite package and wire AddDocSite + UseDocSite into a fresh ASP.NET host.
sectionLabel: Guides
order: 20
---
  
# Install Pennington
  
Install Pennington into an ASP.NET project with one NuGet package and three lines of DI wiring.
  
## 1. Add the package
  
```bash
dotnet add package Pennington.DocSite
```
  
## 2. Wire DocSite in `Program.cs`
  
Three calls — register the services, mount the middleware, hand control to the host:
  
```csharp
builder.Services.AddDocSite(() => new DocSiteOptions { /* ... */ });
app.UseDocSite();
await app.RunDocSiteAsync(args);
```
  
The host is now ready for content. Drop markdown files under `Content/guides/` and they appear in the sidebar on the next request.
  
## Next
  
Pick a site title and decide on areas in [Configure the site](./configure).
````

 
**Add a "Previously" footer to `configure.md`**

 
Mirror the same shape on `configure.md` with a `./install` link back to the first page. Both pages now link to their sibling with a path that survives any move of the `Content/guides/` folder.

 
```markdown:symbol
---
title: Configure the site
description: Pick a site title, set the GitHub link, and decide on a single area or multiple.
sectionLabel: Guides
order: 30
---
  
`DocSiteOptions` is the one options record `AddDocSite` reads. Set the fields that surface in the rendered chrome and the rest of the template falls into place.
  
## Fields worth setting first
  
- `SiteTitle` — appears in the header and the `<title>` tag.
- `Description` — meta description used in search snippets and social cards.
- `GitHubUrl` — surfaces the GitHub icon in the header.
- `HeaderContent` / `FooterContent` — raw HTML slots, useful for a logo and a copyright line.
  
## Areas — one or many?
  
`Areas` is an `IReadOnlyList<ContentArea>`. One entry is enough to ship; more entries turn on the area selector and split the sidebar by top-level folder. Stick with a single area until the content outgrows it.
  
## Previously
  
[Install Pennington](./install) covered getting the package and wiring in place.
```

 
> [!CHECKPOINT]
>  - Reload `http://localhost:5000/guides/install` — a **Configure the site** link sits at the bottom of the page. Click it.
>  - The browser lands on `/guides/configure`. A **Install Pennington** link at the bottom of that page returns to the first.
>  - View source on either page: the relative `./configure` and `./install` markdown links rendered as `href="/guides/configure"` and `href="/guides/install"`.

---

 
## 3. Turn the index into a hub with absolute paths

 
The `Content/guides/index.md` page from the scaffold still says "Walkthroughs and how-tos live in this folder" — a placeholder that no longer matches the content under it. Let's rewrite it as a hub that links to both pages with absolute paths.

 
**Replace `index.md` with the hub markdown below**

 
Absolute paths (`/guides/install`) survive folder moves of the source page. For the full link-form rundown, see [Link between pages without hardcoding URLs](https://usepennington.net/how-to/navigation/linking.md).

 
```markdown:symbol
---
title: Guides
description: Onboarding walkthroughs for a fresh Pennington DocSite.
sectionLabel: Guides
order: 10
---
  
# Guides
  
Two short walkthroughs cover the path from empty project to running site.
  
- [Install Pennington](/guides/install) — add the package and wire `AddDocSite`.
- [Configure the site](/guides/configure) — set the site title, GitHub link, and areas.
```

 
> [!CHECKPOINT]
>  - Visit `http://localhost:5000/guides/` — the Guides landing page now lists the two walkthroughs.
>  - Click **Install Pennington** — the browser navigates to `/guides/install`.
>  - Click **Configure the site** — the browser navigates to `/guides/configure`.

---

 
## 4. Make one link rename-safe with `uid:` + `xref:`

 
Absolute paths break the moment the target file moves or gets renamed. A `uid:` declared in the page's front matter gives the page a stable identifier; `xref:` links resolve through it, so the link survives the file moving or even the URL changing.

 
**Add `uid: guides.install` to `install.md`'s front matter**

 
Open `install.md` and add one front-matter key — the page is now reachable by `xref:guides.install` no matter where the file lives.

 
````markdown:symbol
---
title: Install Pennington
description: Add the Pennington DocSite package and wire AddDocSite + UseDocSite into a fresh ASP.NET host.
uid: guides.install
sectionLabel: Guides
order: 20
---
  
Install Pennington into an ASP.NET project with one NuGet package and three lines of DI wiring.
  
## 1. Add the package
  
```bash
dotnet add package Pennington.DocSite
```
  
## 2. Wire DocSite in `Program.cs`
  
Three calls — register the services, mount the middleware, hand control to the host:
  
```csharp
builder.Services.AddDocSite(() => new DocSiteOptions { /* ... */ });
app.UseDocSite();
await app.RunDocSiteAsync(args);
```
  
The host is now ready for content. Drop markdown files under `Content/guides/` and they appear in the sidebar on the next request.
  
## Next
  
Pick a site title and decide on areas in [Configure the site](./configure).
````

 
**Swap the install link in `index.md` to use `xref:`**

 
Open `index.md` and replace `/guides/install` with `xref:guides.install`. The configure link stays as an absolute path — handy for seeing both forms side by side in the rendered output.

 
```markdown:symbol
---
title: Guides
description: Onboarding walkthroughs for a fresh Pennington DocSite.
sectionLabel: Guides
order: 10
---
  
Two short walkthroughs cover the path from empty project to running site.
  
- [Install Pennington](xref:guides.install) — add the package and wire `AddDocSite`.
- [Configure the site](/guides/configure) — set the site title, GitHub link, and areas.
```

 
> [!CHECKPOINT]
>  - Reload `http://localhost:5000/guides/` — both links in the hub still work. The rendered `<a>` for **Install Pennington** points at `/guides/install` just as the absolute-path version did.
>  - View source: the `xref:guides.install` href has been rewritten to the canonical URL. The xref form is the same shape an editor would have produced — but the source markdown now survives any rename of `install.md`.

---

 
## Summary

 
 - Two markdown files under `Content/guides/` showed up in the sidebar without any extra wiring, sorted by `order:` from front matter.
 - Relative paths (`./configure`) link tightly coupled sibling pages — the form that survives area-folder renames.
 - Absolute paths (`/guides/configure`) link from a hub where the source page may move but the target's location is stable.
 - `uid:` plus `xref:` — the rename-safe form — turns the page identifier itself into the link target.
 - For the full link-form reference (anchors, assets, sub-path deployments), see [Link between pages without hardcoding URLs](https://usepennington.net/how-to/navigation/linking.md). For deeper `uid:` semantics, see [Cross-reference resolution](https://usepennington.net/explanation/routing/cross-references.md).
 
 
[Previous
                
                Scaffold a documentation site with DocSite](https://usepennington.net/tutorials/docsite/scaffold.md)[Next
                    
                Organize content with sections and areas](https://usepennington.net/tutorials/docsite/sections-and-areas.md)