---
title: The Pennington mental model
description: "A short map of the host, content sources, rendering pipeline, response pipeline, and DocSite/BlogSite templates before you dive into the deeper architecture pages."
canonical_url: https://usepennington.net/explanation/core/mental-model/
sidecar_url: https://usepennington.net/explanation/core/mental-model.md
content_hash: sha256:c1f83725d1e6e9f2f025d26f12248cedf781879a2c94c13f06a508d4fa85c22a
tokens: 7042
uid: explanation.core.mental-model
reading_time_minutes: 5
---

Under the Hood
# The Pennington mental model

A short map of the host, content sources, rendering pipeline, response pipeline, and DocSite/BlogSite templates before you dive into the deeper architecture pages.

 
Pennington is easiest to understand as a normal ASP.NET app with a content engine inside it. You run the app while writing, and you ask the same app to build static files when publishing.

 
That single idea explains most of the project:

 
 - The host is ASP.NET. `Program.cs` owns dependency injection, middleware order, Razor components, and any custom endpoints.
 - Content sources discover pages. Markdown folders, Razor pages, redirects, generated API reference, taxonomy pages, and custom services all report routes into the same site model.
 - The content pipeline turns discovered content into rendered content. A page moves from "I know where it is" to "I parsed its front matter" to "I rendered its HTML"; failures travel through the same pipeline so the build report can name them.
 - The response pipeline finishes the HTML. Cross-references, locale prefixes, base URLs, live reload, diagnostics, and other response processors run against the actual HTTP response.
 - Build mode crawls the host. `dotnet run` serves through Kestrel; `dotnet run -- build` starts the same app on an in-process test server, requests every discovered route, and writes the responses to disk.
 
 
That is the whole map. Each deeper architecture page zooms into one box: [The content pipeline and union types](https://usepennington.net/explanation/core/content-pipeline.md) opens up the content pipeline, [The response-processing pipeline](https://usepennington.net/explanation/core/response-processing.md) the response pipeline, and [Dev mode and build mode share one code path](https://usepennington.net/explanation/core/dev-vs-build.md) the serve/build fork on the right edge.

 
.b-7c0cb1c4{--beck-surface:var(--color-base-50, #ffffff);--beck-node-bg:var(--color-base-50, #ffffff);--beck-node-border:var(--color-base-200, #e2e8f0);--beck-node-shadow:0 1px 3px rgb(0 0 0 / 0.05), 0 4px 12px rgb(0 0 0 / 0.06);--beck-text:var(--color-base-800, #1e293b);--beck-text-muted:var(--color-base-500, #64748b);--beck-text-faint:var(--color-base-400, #94a3b8);--beck-primary:var(--color-primary-600, #175ddc);--beck-success:var(--color-emerald-500, #10b981);--beck-warn:var(--color-amber-500, #f59e0b);--beck-danger:var(--color-red-500, #ef4444);--beck-info:var(--color-violet-500, #8b5cf6);--beck-neutral:var(--color-base-400, #94a3b8);--beck-group-border:color-mix(in srgb, var(--beck-neutral) 45%, transparent);--beck-group-label:var(--beck-text-muted);--beck-edge:var(--color-base-300, #cbd5e1);--beck-packet:var(--beck-primary);--beck-icon-bg:var(--color-base-100, #f1f5f9);--beck-accent:var(--beck-primary);--beck-font:'Inter', system-ui, -apple-system, sans-serif;--beck-font-mono:'IBM Plex Mono', ui-monospace, monospace;}[data-theme='dark'] .b-7c0cb1c4{--beck-surface:var(--color-base-950, #0d1117);--beck-node-bg:var(--color-base-900, #161b22);--beck-node-border:var(--color-base-700, #30363d);--beck-node-shadow:0 1px 3px rgb(0 0 0 / 0.3), 0 4px 14px rgb(0 0 0 / 0.4);--beck-text:var(--color-base-50, #f0f6fc);--beck-text-muted:var(--color-base-400, #8b949e);--beck-text-faint:var(--color-base-500, #6e7681);--beck-edge:var(--color-base-700, #30363d);--beck-icon-bg:var(--color-base-800, #21262d);--beck-font:'Inter', system-ui, -apple-system, sans-serif;--beck-font-mono:'IBM Plex Mono', ui-monospace, monospace;}@media (prefers-color-scheme: dark){:root:not([data-theme='light']) .b-7c0cb1c4{--beck-surface:var(--color-base-950, #0d1117);--beck-node-bg:var(--color-base-900, #161b22);--beck-node-border:var(--color-base-700, #30363d);--beck-node-shadow:0 1px 3px rgb(0 0 0 / 0.3), 0 4px 14px rgb(0 0 0 / 0.4);--beck-text:var(--color-base-50, #f0f6fc);--beck-text-muted:var(--color-base-400, #8b949e);--beck-text-faint:var(--color-base-500, #6e7681);--beck-edge:var(--color-base-700, #30363d);--beck-icon-bg:var(--color-base-800, #21262d);--beck-font:'Inter', system-ui, -apple-system, sans-serif;--beck-font-mono:'IBM Plex Mono', ui-monospace, monospace;}}.b-7c0cb1c4{font-family:var(--beck-font);}.b-7c0cb1c4 .beck-fx-node{transform-box:fill-box;transform-origin:center;}.b-7c0cb1c4 .beck-packet-label{font-family:var(--beck-font-mono);font-size:11px;font-weight:600;}.b-7c0cb1c4 .beck-node{fill:var(--beck-node-bg);stroke:color-mix(in srgb, var(--beck-accent) 32%, var(--beck-node-border));stroke-width:1.5;filter:drop-shadow(0 1px 3px rgb(0 0 0/.05)) drop-shadow(0 4px 12px rgb(0 0 0/.06));}[data-theme='dark'] .b-7c0cb1c4 .beck-node{filter:drop-shadow(0 1px 3px rgb(0 0 0/.3)) drop-shadow(0 4px 14px rgb(0 0 0/.4));}@media (prefers-color-scheme: dark){:root:not([data-theme='light']) .b-7c0cb1c4 .beck-node{filter:drop-shadow(0 1px 3px rgb(0 0 0/.3)) drop-shadow(0 4px 14px rgb(0 0 0/.4));}}.b-7c0cb1c4 .beck-node--external{stroke-dasharray:5 4;}.b-7c0cb1c4 .beck-node--subtle{opacity:.72;}.b-7c0cb1c4 .beck-node--ghost{fill:transparent;stroke-dasharray:5 4;filter:none;}.b-7c0cb1c4 .beck-icon-chip{fill:color-mix(in srgb, var(--beck-accent) 15%, var(--beck-icon-bg));}.b-7c0cb1c4 .beck-node--ghost .beck-icon-chip{fill:transparent;}.b-7c0cb1c4 .beck-icon{color:var(--beck-accent);}.b-7c0cb1c4 .beck-node-title{fill:var(--beck-text);}.b-7c0cb1c4 .beck-node-subtitle,.b-7c0cb1c4 .beck-ghost-label{fill:var(--beck-text-muted);}.b-7c0cb1c4 .beck-status-inline{fill:var(--beck-accent);}.b-7c0cb1c4 .beck-status-bg{fill:color-mix(in srgb, var(--beck-accent) 14%, transparent);}.b-7c0cb1c4 .beck-status-text{fill:var(--beck-accent);}.b-7c0cb1c4 .beck-group{fill:none;stroke:var(--beck-group-border);stroke-width:1.5;stroke-dasharray:6 6;}.b-7c0cb1c4 .beck-group-label-bg{fill:var(--beck-surface);}.b-7c0cb1c4 .beck-group-label{fill:var(--beck-group-label);}.b-7c0cb1c4 .beck-node--start{fill:var(--beck-text-muted);}.b-7c0cb1c4 .beck-node--end{fill:none;stroke:var(--beck-text-muted);stroke-width:2;}.b-7c0cb1c4 .beck-end-dot{fill:var(--beck-text-muted);}.b-7c0cb1c4 .beck-class-head{fill:color-mix(in srgb, var(--beck-accent) 10%, transparent);}.b-7c0cb1c4 .beck-class-head-border{stroke:color-mix(in srgb, var(--beck-accent) 28%, var(--beck-node-border));stroke-width:1;}.b-7c0cb1c4 .beck-class-divider{stroke:var(--beck-node-border);stroke-width:1;}.b-7c0cb1c4 .beck-class-stereo{fill:var(--beck-text-muted);}.b-7c0cb1c4 .beck-class-title{fill:var(--beck-text);}.b-7c0cb1c4 .beck-class-field{fill:var(--beck-text-muted);}.b-7c0cb1c4 .beck-class-method{fill:var(--beck-text);}.b-7c0cb1c4 .beck-lifeline{stroke-width:2;stroke-dasharray:6 7;}.b-7c0cb1c4 .beck-activation{filter:drop-shadow(0 0 5px color-mix(in srgb, var(--beck-accent) 45%, transparent));}.b-7c0cb1c4 .beck-msg-chip{fill:var(--beck-node-bg);stroke:color-mix(in srgb, var(--beck-accent) 40%, transparent);stroke-width:1;}.b-7c0cb1c4 .beck-msg-text{fill:color-mix(in srgb, var(--beck-accent) 34%, var(--beck-text));}.b-7c0cb1c4 .beck-msg--reply .beck-msg-chip{stroke:none;}.b-7c0cb1c4 .beck-msg--reply .beck-msg-text,.b-7c0cb1c4 .beck-msg-text--bare{fill:var(--beck-text-muted);}.b-7c0cb1c4 .beck-band-box{fill:color-mix(in srgb, var(--beck-accent) 5%, transparent);stroke:color-mix(in srgb, var(--beck-accent) 30%, transparent);stroke-width:1.5;stroke-dasharray:6 6;}.b-7c0cb1c4 .beck-band-chip{fill:var(--beck-surface);stroke:color-mix(in srgb, var(--beck-accent) 40%, transparent);stroke-width:1;}.b-7c0cb1c4 .beck-band-label{fill:color-mix(in srgb, var(--beck-accent) 70%, var(--beck-text));}.b-7c0cb1c4 .beck-edge{fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;}.b-7c0cb1c4 .beck-edge-label{fill:var(--beck-text-muted);paint-order:stroke;stroke:var(--beck-surface);stroke-width:3px;stroke-linejoin:round;}.b-7c0cb1c4 .beck-title{fill:var(--beck-text);}.b-7c0cb1c4 .beck-subtitle{fill:var(--beck-text-muted);}@media (prefers-reduced-motion:no-preference){.b-7c0cb1c4 .bp0-7c0cb1c4{animation:kp0-7c0cb1c4 26.07s linear infinite;}@keyframes kp0-7c0cb1c4{0%{offset-distance:0%;opacity:0;}15.7054%{opacity:0;}15.7154%{offset-distance:0%;opacity:1;animation-timing-function:linear;}21.0029%{offset-distance:100%;opacity:1;}21.0129%{opacity:0;}100%{offset-distance:0%;opacity:0;}}.b-7c0cb1c4 .bt0-7c0cb1c4{animation:kt0-7c0cb1c4 26.07s linear infinite;}@keyframes kt0-7c0cb1c4{0%{stroke-dashoffset:289.44;}15.7154%{stroke-dashoffset:289.44;animation-timing-function:linear;}21.0029%{stroke-dashoffset:0;}95.3964%{stroke-dashoffset:0;}95.4064%{stroke-dashoffset:289.44;}100%{stroke-dashoffset:289.44;}}.b-7c0cb1c4 .bp1-7c0cb1c4{animation:kp1-7c0cb1c4 26.07s linear infinite;}@keyframes kp1-7c0cb1c4{0%{offset-distance:0%;opacity:0;}23.2947%{opacity:0;}23.3047%{offset-distance:0%;opacity:1;animation-timing-function:linear;}25.6065%{offset-distance:100%;opacity:1;}25.6165%{opacity:0;}100%{offset-distance:0%;opacity:0;}}.b-7c0cb1c4 .bt1-7c0cb1c4{animation:kt1-7c0cb1c4 26.07s linear infinite;}@keyframes kt1-7c0cb1c4{0%{stroke-dashoffset:97.5;}23.3047%{stroke-dashoffset:97.5;animation-timing-function:linear;}25.6065%{stroke-dashoffset:0;}95.3964%{stroke-dashoffset:0;}95.4064%{stroke-dashoffset:97.5;}100%{stroke-dashoffset:97.5;}}.b-7c0cb1c4 .bp2-7c0cb1c4{animation:kp2-7c0cb1c4 26.07s linear infinite;}@keyframes kp2-7c0cb1c4{0%{offset-distance:0%;opacity:0;}27.8983%{opacity:0;}27.9083%{offset-distance:0%;opacity:1;animation-timing-function:linear;}33.922%{offset-distance:100%;opacity:1;}33.932%{opacity:0;}100%{offset-distance:0%;opacity:0;}}.b-7c0cb1c4 .bt2-7c0cb1c4{animation:kt2-7c0cb1c4 26.07s linear infinite;}@keyframes kt2-7c0cb1c4{0%{stroke-dashoffset:329.19;}27.9083%{stroke-dashoffset:329.19;animation-timing-function:linear;}33.922%{stroke-dashoffset:0;}95.3964%{stroke-dashoffset:0;}95.4064%{stroke-dashoffset:329.19;}100%{stroke-dashoffset:329.19;}}.b-7c0cb1c4 .bp3-7c0cb1c4{animation:kp3-7c0cb1c4 26.07s linear infinite;}@keyframes kp3-7c0cb1c4{0%{offset-distance:0%;opacity:0;}55.9912%{opacity:0;}56.0012%{offset-distance:0%;opacity:1;animation-timing-function:linear;}58.303%{offset-distance:100%;opacity:1;}58.313%{opacity:0;}100%{offset-distance:0%;opacity:0;}}.b-7c0cb1c4 .bt3-7c0cb1c4{animation:kt3-7c0cb1c4 26.07s linear infinite;}@keyframes kt3-7c0cb1c4{0%{stroke-dashoffset:96;}56.0012%{stroke-dashoffset:96;animation-timing-function:linear;}58.303%{stroke-dashoffset:0;}95.3964%{stroke-dashoffset:0;}95.4064%{stroke-dashoffset:96;}100%{stroke-dashoffset:96;}}.b-7c0cb1c4 .bp4-7c0cb1c4{animation:kp4-7c0cb1c4 26.07s linear infinite;}@keyframes kp4-7c0cb1c4{0%{offset-distance:0%;opacity:0;}60.5948%{opacity:0;}60.6048%{offset-distance:0%;opacity:1;animation-timing-function:linear;}63.892%{offset-distance:100%;opacity:1;}63.902%{opacity:0;}100%{offset-distance:0%;opacity:0;}}.b-7c0cb1c4 .bt4-7c0cb1c4{animation:kt4-7c0cb1c4 26.07s linear infinite;}@keyframes kt4-7c0cb1c4{0%{stroke-dashoffset:179.94;}60.6048%{stroke-dashoffset:179.94;animation-timing-function:linear;}63.892%{stroke-dashoffset:0;}95.3964%{stroke-dashoffset:0;}95.4064%{stroke-dashoffset:179.94;}100%{stroke-dashoffset:179.94;}}.b-7c0cb1c4 .bp5-7c0cb1c4{animation:kp5-7c0cb1c4 26.07s linear infinite;}@keyframes kp5-7c0cb1c4{0%{offset-distance:0%;opacity:0;}85.9611%{opacity:0;}85.9711%{offset-distance:0%;opacity:1;animation-timing-function:linear;}89.2583%{offset-distance:100%;opacity:1;}89.2683%{opacity:0;}100%{offset-distance:0%;opacity:0;}}.b-7c0cb1c4 .bt5-7c0cb1c4{animation:kt5-7c0cb1c4 26.07s linear infinite;}@keyframes kt5-7c0cb1c4{0%{stroke-dashoffset:179.94;}85.9711%{stroke-dashoffset:179.94;animation-timing-function:linear;}89.2583%{stroke-dashoffset:0;}95.3964%{stroke-dashoffset:0;}95.4064%{stroke-dashoffset:179.94;}100%{stroke-dashoffset:179.94;}}.b-7c0cb1c4 .bn3-7c0cb1c4 .beck-fx-node{animation:kn3-7c0cb1c4 26.07s linear infinite;}@keyframes kn3-7c0cb1c4{0%{transform:none;}21.0029%{transform:none;animation-timing-function:linear(0 0%, 0.2557 3.33%, 0.4834 6.67%, 0.6845 10%, 0.8603 13.33%, 1.0121 16.67%, 1.1414 20%, 1.2495 23.33%, 1.3377 26.67%, 1.4074 30%, 1.46 33.33%, 1.4967 36.67%, 1.5191 40%, 1.5284 43.33%, 1.5259 46.67%, 1.4913 53.33%, 1.4261 60%, 1.3411 66.67%, 1.2472 73.33%, 1.1554 80%, 1.0763 86.67%, 1.0209 93.33%, 1 100%);}21.6934%{transform:translateY(-2px) scale(1.04);animation-timing-function:linear(0 0%, 0.1286 1.67%, 0.2749 3.33%, 0.5785 6.67%, 0.7194 8.33%, 0.8455 10%, 0.9534 11.67%, 1.0415 13.33%, 1.1093 15%, 1.1575 16.67%, 1.1878 18.33%, 1.2023 20%, 1.2035 21.67%, 1.1941 23.33%, 1.154 26.67%, 1.0496 33.33%, 1.0082 36.67%, 0.9807 40%, 0.9668 43.33%, 0.964 46.67%, 0.9773 53.33%, 0.9952 60%, 1.0049 66.67%, 1.0061 73.33%, 1.0032 80%, 1.0003 86.67%, 0.999 93.33%, 1 100%);}23.3047%{transform:none;}25.6065%{transform:none;animation-timing-function:linear(0 0%, 0.2557 3.33%, 0.4834 6.67%, 0.6845 10%, 0.8603 13.33%, 1.0121 16.67%, 1.1414 20%, 1.2495 23.33%, 1.3377 26.67%, 1.4074 30%, 1.46 33.33%, 1.4967 36.67%, 1.5191 40%, 1.5284 43.33%, 1.5259 46.67%, 1.4913 53.33%, 1.4261 60%, 1.3411 66.67%, 1.2472 73.33%, 1.1554 80%, 1.0763 86.67%, 1.0209 93.33%, 1 100%);}26.297%{transform:translateY(-2px) scale(1.04);animation-timing-function:linear(0 0%, 0.1286 1.67%, 0.2749 3.33%, 0.5785 6.67%, 0.7194 8.33%, 0.8455 10%, 0.9534 11.67%, 1.0415 13.33%, 1.1093 15%, 1.1575 16.67%, 1.1878 18.33%, 1.2023 20%, 1.2035 21.67%, 1.1941 23.33%, 1.154 26.67%, 1.0496 33.33%, 1.0082 36.67%, 0.9807 40%, 0.9668 43.33%, 0.964 46.67%, 0.9773 53.33%, 0.9952 60%, 1.0049 66.67%, 1.0061 73.33%, 1.0032 80%, 1.0003 86.67%, 0.999 93.33%, 1 100%);}27.9083%{transform:none;}33.922%{transform:none;animation-timing-function:linear(0 0%, 0.2557 3.33%, 0.4834 6.67%, 0.6845 10%, 0.8603 13.33%, 1.0121 16.67%, 1.1414 20%, 1.2495 23.33%, 1.3377 26.67%, 1.4074 30%, 1.46 33.33%, 1.4967 36.67%, 1.5191 40%, 1.5284 43.33%, 1.5259 46.67%, 1.4913 53.33%, 1.4261 60%, 1.3411 66.67%, 1.2472 73.33%, 1.1554 80%, 1.0763 86.67%, 1.0209 93.33%, 1 100%);}34.6126%{transform:translateY(-2px) scale(1.04);animation-timing-function:linear(0 0%, 0.1286 1.67%, 0.2749 3.33%, 0.5785 6.67%, 0.7194 8.33%, 0.8455 10%, 0.9534 11.67%, 1.0415 13.33%, 1.1093 15%, 1.1575 16.67%, 1.1878 18.33%, 1.2023 20%, 1.2035 21.67%, 1.1941 23.33%, 1.154 26.67%, 1.0496 33.33%, 1.0082 36.67%, 0.9807 40%, 0.9668 43.33%, 0.964 46.67%, 0.9773 53.33%, 0.9952 60%, 1.0049 66.67%, 1.0061 73.33%, 1.0032 80%, 1.0003 86.67%, 0.999 93.33%, 1 100%);}36.2238%{transform:none;}100%{transform:none;}}.b-7c0cb1c4 .bn4-7c0cb1c4 .beck-fx-node{animation:kn4-7c0cb1c4 26.07s linear infinite;}@keyframes kn4-7c0cb1c4{0%{transform:none;}58.303%{transform:none;animation-timing-function:linear(0 0%, 0.2557 3.33%, 0.4834 6.67%, 0.6845 10%, 0.8603 13.33%, 1.0121 16.67%, 1.1414 20%, 1.2495 23.33%, 1.3377 26.67%, 1.4074 30%, 1.46 33.33%, 1.4967 36.67%, 1.5191 40%, 1.5284 43.33%, 1.5259 46.67%, 1.4913 53.33%, 1.4261 60%, 1.3411 66.67%, 1.2472 73.33%, 1.1554 80%, 1.0763 86.67%, 1.0209 93.33%, 1 100%);}58.9936%{transform:translateY(-2px) scale(1.04);animation-timing-function:linear(0 0%, 0.1286 1.67%, 0.2749 3.33%, 0.5785 6.67%, 0.7194 8.33%, 0.8455 10%, 0.9534 11.67%, 1.0415 13.33%, 1.1093 15%, 1.1575 16.67%, 1.1878 18.33%, 1.2023 20%, 1.2035 21.67%, 1.1941 23.33%, 1.154 26.67%, 1.0496 33.33%, 1.0082 36.67%, 0.9807 40%, 0.9668 43.33%, 0.964 46.67%, 0.9773 53.33%, 0.9952 60%, 1.0049 66.67%, 1.0061 73.33%, 1.0032 80%, 1.0003 86.67%, 0.999 93.33%, 1 100%);}60.6048%{transform:none;}100%{transform:none;}}.b-7c0cb1c4 .bn5-7c0cb1c4 .beck-fx-node{animation:kn5-7c0cb1c4 26.07s linear infinite;}@keyframes kn5-7c0cb1c4{0%{transform:none;}63.892%{transform:none;animation-timing-function:linear(0 0%, 0.2557 3.33%, 0.4834 6.67%, 0.6845 10%, 0.8603 13.33%, 1.0121 16.67%, 1.1414 20%, 1.2495 23.33%, 1.3377 26.67%, 1.4074 30%, 1.46 33.33%, 1.4967 36.67%, 1.5191 40%, 1.5284 43.33%, 1.5259 46.67%, 1.4913 53.33%, 1.4261 60%, 1.3411 66.67%, 1.2472 73.33%, 1.1554 80%, 1.0763 86.67%, 1.0209 93.33%, 1 100%);}64.5825%{transform:translateY(-2px) scale(1.04);animation-timing-function:linear(0 0%, 0.1286 1.67%, 0.2749 3.33%, 0.5785 6.67%, 0.7194 8.33%, 0.8455 10%, 0.9534 11.67%, 1.0415 13.33%, 1.1093 15%, 1.1575 16.67%, 1.1878 18.33%, 1.2023 20%, 1.2035 21.67%, 1.1941 23.33%, 1.154 26.67%, 1.0496 33.33%, 1.0082 36.67%, 0.9807 40%, 0.9668 43.33%, 0.964 46.67%, 0.9773 53.33%, 0.9952 60%, 1.0049 66.67%, 1.0061 73.33%, 1.0032 80%, 1.0003 86.67%, 0.999 93.33%, 1 100%);}66.1938%{transform:none;}100%{transform:none;}}.b-7c0cb1c4 .bn6-7c0cb1c4 .beck-fx-node{animation:kn6-7c0cb1c4 26.07s linear infinite;}@keyframes kn6-7c0cb1c4{0%{transform:none;}89.2583%{transform:none;animation-timing-function:linear(0 0%, 0.2557 3.33%, 0.4834 6.67%, 0.6845 10%, 0.8603 13.33%, 1.0121 16.67%, 1.1414 20%, 1.2495 23.33%, 1.3377 26.67%, 1.4074 30%, 1.46 33.33%, 1.4967 36.67%, 1.5191 40%, 1.5284 43.33%, 1.5259 46.67%, 1.4913 53.33%, 1.4261 60%, 1.3411 66.67%, 1.2472 73.33%, 1.1554 80%, 1.0763 86.67%, 1.0209 93.33%, 1 100%);}89.9488%{transform:translateY(-2px) scale(1.04);animation-timing-function:linear(0 0%, 0.1286 1.67%, 0.2749 3.33%, 0.5785 6.67%, 0.7194 8.33%, 0.8455 10%, 0.9534 11.67%, 1.0415 13.33%, 1.1093 15%, 1.1575 16.67%, 1.1878 18.33%, 1.2023 20%, 1.2035 21.67%, 1.1941 23.33%, 1.154 26.67%, 1.0496 33.33%, 1.0082 36.67%, 0.9807 40%, 0.9668 43.33%, 0.964 46.67%, 0.9773 53.33%, 0.9952 60%, 1.0049 66.67%, 1.0061 73.33%, 1.0032 80%, 1.0003 86.67%, 0.999 93.33%, 1 100%);}91.5601%{transform:none;}100%{transform:none;}}.b-7c0cb1c4 .brip0-7c0cb1c4{animation:krip0-7c0cb1c4 26.07s linear infinite;}@keyframes krip0-7c0cb1c4{0%{opacity:0;transform:scale(1);}20.9929%{opacity:0;transform:scale(1);}21.0029%{opacity:0.6;transform:scale(1);animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}22.8443%{opacity:0;transform:scale(1.15);}100%{opacity:0;transform:scale(1);}}.b-7c0cb1c4 .brip1-7c0cb1c4{animation:krip1-7c0cb1c4 26.07s linear infinite;}@keyframes krip1-7c0cb1c4{0%{opacity:0;transform:scale(1);}25.5965%{opacity:0;transform:scale(1);}25.6065%{opacity:0.6;transform:scale(1);animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}27.4479%{opacity:0;transform:scale(1.15);}100%{opacity:0;transform:scale(1);}}.b-7c0cb1c4 .brip2-7c0cb1c4{animation:krip2-7c0cb1c4 26.07s linear infinite;}@keyframes krip2-7c0cb1c4{0%{opacity:0;transform:scale(1);}33.912%{opacity:0;transform:scale(1);}33.922%{opacity:0.6;transform:scale(1);animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}35.7635%{opacity:0;transform:scale(1.15);}100%{opacity:0;transform:scale(1);}}.b-7c0cb1c4 .brip3-7c0cb1c4{animation:krip3-7c0cb1c4 26.07s linear infinite;}@keyframes krip3-7c0cb1c4{0%{opacity:0;transform:scale(1);}58.293%{opacity:0;transform:scale(1);}58.303%{opacity:0.6;transform:scale(1);animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}60.1445%{opacity:0;transform:scale(1.15);}100%{opacity:0;transform:scale(1);}}.b-7c0cb1c4 .brip4-7c0cb1c4{animation:krip4-7c0cb1c4 26.07s linear infinite;}@keyframes krip4-7c0cb1c4{0%{opacity:0;transform:scale(1);}63.882%{opacity:0;transform:scale(1);}63.892%{opacity:0.6;transform:scale(1);animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}65.7334%{opacity:0;transform:scale(1.15);}100%{opacity:0;transform:scale(1);}}.b-7c0cb1c4 .brip5-7c0cb1c4{animation:krip5-7c0cb1c4 26.07s linear infinite;}@keyframes krip5-7c0cb1c4{0%{opacity:0;transform:scale(1);}89.2483%{opacity:0;transform:scale(1);}89.2583%{opacity:0.6;transform:scale(1);animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}91.0997%{opacity:0;transform:scale(1.15);}100%{opacity:0;transform:scale(1);}}.b-7c0cb1c4 .bbeat0-7c0cb1c4{animation:kbe0-7c0cb1c4 26.07s linear infinite;}@keyframes kbe0-7c0cb1c4{0%{opacity:0;}0.4504%{opacity:0;}0.4604%{opacity:0;animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}1.6113%{opacity:1;}36.2238%{opacity:1;animation-timing-function:linear(0 0%, 0.0044 6.67%, 0.0178 13.33%, 0.04 20%, 0.0711 26.67%, 0.1111 33.33%, 0.16 40%, 0.2178 46.67%, 0.2844 53.33%, 0.36 60%, 0.4444 66.67%, 0.5378 73.33%, 0.64 80%, 0.7511 86.67%, 0.8711 93.33%, 1 100%);}36.6842%{opacity:0;}100%{opacity:0;}}.b-7c0cb1c4 .bbeat1-7c0cb1c4{animation:kbe1-7c0cb1c4 26.07s linear infinite;}@keyframes kbe1-7c0cb1c4{0%{opacity:0;}36.6742%{opacity:0;}36.6842%{opacity:0;animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}37.8351%{opacity:1;}66.1938%{opacity:1;animation-timing-function:linear(0 0%, 0.0044 6.67%, 0.0178 13.33%, 0.04 20%, 0.0711 26.67%, 0.1111 33.33%, 0.16 40%, 0.2178 46.67%, 0.2844 53.33%, 0.36 60%, 0.4444 66.67%, 0.5378 73.33%, 0.64 80%, 0.7511 86.67%, 0.8711 93.33%, 1 100%);}66.6541%{opacity:0;}100%{opacity:0;}}.b-7c0cb1c4 .bbeat2-7c0cb1c4{animation:kbe2-7c0cb1c4 26.07s linear infinite;}@keyframes kbe2-7c0cb1c4{0%{opacity:0;}66.6441%{opacity:0;}66.6541%{opacity:0;animation-timing-function:linear(0 0%, 0.187 6.67%, 0.349 13.33%, 0.488 20%, 0.6056 26.67%, 0.7037 33.33%, 0.784 40%, 0.8483 46.67%, 0.8984 53.33%, 0.936 60%, 0.963 66.67%, 0.981 73.33%, 0.992 80%, 0.9976 86.67%, 0.9997 93.33%, 1 100%);}67.805%{opacity:1;}95.3964%{opacity:1;animation-timing-function:linear(0 0%, 0.0044 6.67%, 0.0178 13.33%, 0.04 20%, 0.0711 26.67%, 0.1111 33.33%, 0.16 40%, 0.2178 46.67%, 0.2844 53.33%, 0.36 60%, 0.4444 66.67%, 0.5378 73.33%, 0.64 80%, 0.7511 86.67%, 0.8711 93.33%, 1 100%);}95.8964%{opacity:0;}100%{opacity:0;}}}dev servedotnet run -- buildMarkdown foldersRazor pagesCustom sourcesAPI reference · taxonomy · redirectsContent pipelinediscover · parse · renderResponse pipelinexrefs · locales · base URL · headBrowserStatic outputEvery source reports routes into the same site modelRendered HTML is finished by the response pipeline, never by the sourcesBuild mode crawls the same app and writes each response to disk
## The layers

 
### `Pennington`

 
`Pennington` is the lower-level engine. It gives you content discovery, markdown parsing, rendering, route resolution, response processing, diagnostics, search artifacts, feeds, and static output. You bring the site shell: layout, navigation markup, styling, and any app-specific endpoints.

 
Start here when you are embedding content into an existing ASP.NET app, building a custom layout, or mixing several kinds of content that do not fit a stock documentation or blog template. The first getting-started arc walks this path: [Create your first Pennington site](https://usepennington.net/tutorials/getting-started/first-site.md).

 
### `Pennington.DocSite`

 
`Pennington.DocSite` is a pre-assembled documentation site on top of the engine. One `AddDocSite` call wires the engine, markdown content, DocSite layout, sidebar navigation, search, MonorailCSS styling, SPA navigation, feeds, and static build behavior.

 
Start here for a conventional documentation site. You can still customize options and add extension points, but the template owns the article-shaped layout. The scaffold tutorial starts here: [Scaffold a documentation site with DocSite](https://usepennington.net/tutorials/docsite/scaffold.md).

 
### `Pennington.BlogSite`

 
`Pennington.BlogSite` is the same idea for a blog-first site. It is a template, not a separate engine: the underlying runtime is still Pennington content discovery plus the shared ASP.NET request pipeline.

 
Reach for it when the blog *is* the site; a blog alongside docs stays on DocSite. [What the DocSite and BlogSite templates wire for you](https://usepennington.net/explanation/positioning/docsite-positioning.md) owns that decision rule and why the two templates cannot share a host.

 
### `Pennington.UI`

 
`Pennington.UI` is the Razor component library — table-of-contents and outline navigation, breadcrumbs, pagination, cards, badges, code blocks, callouts, the search modal, and the client-side SPA navigation script. DocSite and BlogSite reference it for you and pre-register the markdown-facing components, so you rarely call it directly on a template.

 
You meet it the moment you go bare-engine. `AddPennington` does not assume a layout, so a custom shell that wants the same navigation chrome or wants to drop components into markdown pulls these in itself. The components and their parameters are catalogued in the UI reference: [Content components](https://usepennington.net/reference/ui/content.md), [Navigation components](https://usepennington.net/reference/ui/navigation.md), and [Utility components](https://usepennington.net/reference/ui/utility.md). To use them inside markdown, see [Drop a Razor component into a markdown page](https://usepennington.net/how-to/rich-content/ui-components-in-markdown.md).

 
### `Pennington.TreeSitter`

 
`Pennington.TreeSitter` is the optional code-fragment extractor. It powers the `:symbol` fence — addressing a member by its name path so a code block shows one method instead of a whole file — across the languages tree-sitter parses.

 
It is opt-in: register it with `AddTreeSitter` and point `ContentRoot` at the root that holds the source you want to fence. Nothing else changes, so you add it only when a site embeds live source. The recipes live in [Embed focused code samples](https://usepennington.net/how-to/code-samples/focused-code-samples.md).

 
## Terms you will see

 
    Term Meaning     Host The ASP.NET app that registers Pennington and handles requests.   Content source A service that discovers routes and records for pages or generated artifacts.   Front matter Typed metadata parsed from the YAML block at the top of a markdown file.   Route The URL and output-file mapping for a page or endpoint.   Xref A symbolic link such as `<xref:tutorials.docsite.scaffold>` that resolves to the current route for a page or API member.   Response processor A hook that rewrites the HTTP response before it reaches the browser or static output folder.   Build report The diagnostics summary printed by `dotnet run -- build`.    
## What to read next

 
 - Build a bare host: [Create your first Pennington site](https://usepennington.net/tutorials/getting-started/first-site.md)
 - Scaffold a documentation site: [Scaffold a documentation site with DocSite](https://usepennington.net/tutorials/docsite/scaffold.md)
 - Understand why dev and build share one app: [Dev mode and build mode share one code path](https://usepennington.net/explanation/core/dev-vs-build.md)
 - Understand the content pipeline internals: [The content pipeline and union types](https://usepennington.net/explanation/core/content-pipeline.md)
 - See what DocSite and BlogSite wire for you: [What the DocSite and BlogSite templates wire for you](https://usepennington.net/explanation/positioning/docsite-positioning.md)
 
 
[Next
                    
                The content pipeline and union types](https://usepennington.net/explanation/core/content-pipeline.md)