---
title: Add a blog to your documentation site
description: "Drop a Content/blog folder into a DocSite and watch the blog index, post pages, browse-by-tag pages, and RSS feed light up — no Program.cs changes."
canonical_url: https://usepennington.net/tutorials/docsite/add-a-blog/
sidecar_url: https://usepennington.net/tutorials/docsite/add-a-blog.md
content_hash: sha256:41fc35ecd0cae9d5d9b77cebb46b8b5cc7cd5cc06fdc7f45025bdb1d6ba72888
tokens: 1948
uid: tutorials.docsite.add-a-blog
reading_time_minutes: 5
---

Getting Started
# Add a blog to your documentation site

Drop a Content/blog folder into a DocSite and watch the blog index, post pages, browse-by-tag pages, and RSS feed light up — no Program.cs changes.

 
By the end of this tutorial the DocSite at `http://localhost:5000/` carries a **Blog** link in its header, a `/blog` index listing two posts newest-first, post pages with a date and byline, browse-by-tag pages, and an RSS feed at `/rss.xml`.

 
The blog activates from content alone — a folder named `blog` under `Content/`. There is no `Program.cs` change anywhere in this tutorial; every step is a markdown file.

 
## Prerequisites

 
 - .NET 10 SDK installed
 - Completed [Scaffold a documentation site with DocSite](https://usepennington.net/tutorials/docsite/scaffold.md) — or any DocSite host ready to run
 
 
The finished code for this tutorial lives in [examples/DocSiteBlogExample](https://github.com/usepennington/pennington/tree/main/examples/DocSiteBlogExample).

 
---

 
## 1. Write your first post

 
A DocSite turns on its blog when it finds a folder named `blog` under `Content/`. Create that folder, drop one post into it, and the blog appears.

 
**Create `Content/blog/launching-the-docs.md`**

 
Add a `blog` folder under `Content/`, alongside your area folders, and create `launching-the-docs.md` inside it. The filename minus `.md` becomes the post's URL slug, so this post serves at `/blog/launching-the-docs`.

 
> [!NOTE]
> The folder must be named exactly `blog`, in lowercase. On a case-sensitive filesystem `Blog` or `blogs` is not detected.

 
**Paste in the post**

 
Paste the markdown below. The four front-matter fields are the ones every post uses: `title` is the post heading and link label, `description` is the summary shown on the blog index, `author` is the byline, and `date` is the publication date.

 
```markdown:symbol
---
title: Launching the Harbor docs
description: The Harbor documentation site is live, and it now has a blog.
author: Dana Reyes
date: 2026-05-08
---
  
Harbor's documentation has a new home. Alongside the guides, this blog will
carry release notes, design notes, and the occasional field report.
  
## Why a blog
  
Guides explain how Harbor works today. A blog is the place for what changed
and why — the running story behind the tool.
```

 
**Run the host**

 
```bash
dotnet run
```

 
Open `http://localhost:5000/`.

 
> [!CHECKPOINT]
>  - A **Blog** link appears in the site header, beside the theme toggle.
>  - `http://localhost:5000/blog` lists one post — **Launching the Harbor docs** — with its date and description.
>  - `http://localhost:5000/blog/launching-the-docs` renders the post body under its title, with the **By Dana Reyes** byline.

---

 
## 2. Add a second post

 
The blog index orders posts by `date`, newest first. Add a second, more recent post and watch it take the top slot.

 
**Create `Content/blog/whats-next.md`**

 
Add a second file in the `blog` folder with the markdown below. Its `date` — `2026-05-15` — is a week after the first post.

 
```markdown:symbol
---
title: What's next for Harbor
description: A look at the features on the Harbor roadmap for the next release.
author: Dana Reyes
date: 2026-05-15
---
  
The docs are live, so here is where Harbor goes next.
  
## On the roadmap
  
- Faster incremental builds.
- A watch mode that reloads on content changes.
- A plugin hook for custom output formats.
```

 
**Reload the blog index**

 
A markdown edit needs no restart — the host watches `Content/`. Save the file and reload `http://localhost:5000/blog`.

 
> [!CHECKPOINT]
>  - `http://localhost:5000/blog` now lists two posts.
>  - **What's next for Harbor** sits above **Launching the Harbor docs** — the newer `date` puts it first.

---

 
## 3. Tag your posts and find the feed

 
A `tags` list on a post adds it to browse-by-tag pages. Tag both posts, then look at the feed the blog has been publishing all along.

 
**Add tags to the first post**

 
Add a `tags` block to `launching-the-docs.md`. The file now reads:

 
```markdown:symbol
---
title: Launching the Harbor docs
description: The Harbor documentation site is live, and it now has a blog.
author: Dana Reyes
date: 2026-05-08
tags:
  - announcements
  - docs
---
  
Harbor's documentation has a new home. Alongside the guides, this blog will
carry release notes, design notes, and the occasional field report.
  
## Why a blog
  
Guides explain how Harbor works today. A blog is the place for what changed
and why — the running story behind the tool.
```

 
**Add tags to the second post**

 
Give `whats-next.md` its own `tags` block. One tag, `announcements`, is shared with the first post.

 
```markdown:symbol
---
title: What's next for Harbor
description: A look at the features on the Harbor roadmap for the next release.
author: Dana Reyes
date: 2026-05-15
tags:
  - announcements
  - roadmap
---
  
The docs are live, so here is where Harbor goes next.
  
## On the roadmap
  
- Faster incremental builds.
- A watch mode that reloads on content changes.
- A plugin hook for custom output formats.
```

 
**Reload and follow the tags**

 
Save both files and reload `http://localhost:5000/blog/launching-the-docs`.

 
> [!CHECKPOINT]
>  - The post page now lists its tags beneath the body — **launching-the-docs** shows **announcements** and **docs** as links.
>  - Following a tag opens its page — `http://localhost:5000/blog/tags/announcements` lists both posts; `/blog/tags/docs` lists only the first.
>  - The blog index carries a **Browse by tag** link to `http://localhost:5000/blog/tags`, which lists all three tags with their post counts — **announcements** (2), **docs** (1), and **roadmap** (1).

 
Now look at the feed the blog has been publishing since your first post.

 
> [!CHECKPOINT]
>  - `http://localhost:5000/rss.xml` is a valid RSS feed — a `<channel>` with the site title and two `<item>` elements whose `<title>`, `<description>`, `<pubDate>`, and `<author>` come from the front matter. The `<link>` URLs are relative to your site root, since no `CanonicalBaseUrl` is set; set `DocSiteOptions.CanonicalBaseUrl` to make them absolute.
>  - Run `dotnet run -- build` — the static build writes `blog/index.html`, the two post pages, the `blog/tags/` pages, and `rss.xml` into `output/`.

---

 
Every front-matter field you wrote into those posts is parsed into a [BlogPostFrontMatter](https://usepennington.net/reference/front-matter/keys.md) record, the type a DocSite binds for content under the `blog` folder.

 
## Summary

 
 - A folder named `blog` under `Content/` is the whole switch — `AddDocSite` finds it at startup and turns on the blog index, post pages, tag pages, the RSS feed, and the header link.
 - Each `BlogPostFrontMatter` field drives a surface: `title`, `description`, and `date` for the index; `author` for the byline and RSS; `tags` for the `/blog/tags/` pages.
 - Posts sort newest-first by `date`.
 - `/rss.xml` is generated automatically; its `<link>` URLs are relative until you set `DocSiteOptions.CanonicalBaseUrl`.
 - None of it needed a `Program.cs` change — the blog is pure content.
 
 
That rounds out the Getting Started with DocSite series. To go further, the **Beyond the Basics** tutorials build on this same host: [add a second locale to your site](https://usepennington.net/tutorials/beyond-basics/add-a-locale.md) and [author a custom Razor component for markdown](https://usepennington.net/tutorials/beyond-basics/custom-razor-component.md).

 
[Previous
                
                Add a Razor landing page at the site root](https://usepennington.net/tutorials/docsite/landing-page.md)[Next
                    
                Scaffold a blog with BlogSite](https://usepennington.net/tutorials/blogsite/scaffold.md)