diff --git a/src/html.rs b/src/html.rs
index d67e943..6b58ced 100644
--- a/src/html.rs
+++ b/src/html.rs
@@ -1,9 +1,6 @@
-//! An HTML renderer that takes an iterator of [`Event`]s and emits HTML.
-
 use std::collections::HashMap;
 
 use anyhow::anyhow;
-use anyhow::bail;
 use chrono::DateTime;
 use chrono::TimeZone;
 use jotdown::Alignment;
@@ -15,6 +12,7 @@ use jotdown::OrderedListNumbering::*;
 use jotdown::SpanLinkType;
 
 use crate::metadata::PageMetadata;
+use crate::metadata::PageRoute;
 use crate::template;
 use crate::template::TemplateRenderer;
 
@@ -185,7 +183,9 @@ impl<'s> Writer<'s> {
 					Container::Table => out.write_str("<table")?,
 					Container::TableRow { .. } => out.write_str("<tr")?,
 					Container::Section { id } => match self.metadata {
-						Some(meta) if &meta.title.id == id => {
+						Some(meta)
+							if &meta.title.id == id && matches!(meta.route, PageRoute::Post(_)) =>
+						{
 							let renderer = template!("templates/post.html", &mut out)?;
 							assert_eq!(renderer.current(), Some("attrs"));
 							self.states.push(State::Article(renderer));
@@ -432,9 +432,12 @@ impl<'s> Writer<'s> {
 					Container::Table => out.write_str("</table>")?,
 					Container::TableRow { .. } => out.write_str("</tr>")?,
 					Container::Section { id, .. } => match self.metadata {
-						Some(meta) if &meta.title.id == id => {
+						Some(meta)
+							if &meta.title.id == id
+								&& matches!(self.states.last(), Some(State::Article(_))) =>
+						{
 							let Some(State::Article(renderer)) = self.states.pop() else {
-								bail!("Arrived at the end of the main <section> element without being in the `Article` state.")
+								unreachable!()
 							};
 
 							renderer.finish(&mut out)?;
@@ -471,7 +474,7 @@ impl<'s> Writer<'s> {
 											write!(&mut out, "Posted on ")?;
 											write_datetime(&d, &mut out)?;
 										} else {
-											write!(&mut out, "Still being conjured ")?;
+											write!(&mut out, "Being conjured by ")?;
 										}
 									} else if label == "updated_on" {
 										write_datetime(&meta.last_modified, &mut out)?;
diff --git a/src/metadata.rs b/src/metadata.rs
index 0c7e1de..37d212a 100644
--- a/src/metadata.rs
+++ b/src/metadata.rs
@@ -1,5 +1,7 @@
-#![allow(dead_code)]
-use std::{fmt::Write, path::PathBuf, process::Command};
+use std::ffi::OsStr;
+use std::fmt::Write;
+use std::path::{Component, Path, PathBuf};
+use std::process::Command;
 
 use anyhow::{anyhow, bail, Context};
 use chrono::{DateTime, FixedOffset};
@@ -31,14 +33,53 @@ impl PageConfig {
 	}
 }
 
+#[derive(Debug)]
+pub enum PageRoute {
+	Home,
+	Posts,
+	#[allow(dead_code)]
+	Post(String),
+}
+
+impl PageRoute {
+	fn from_path(path: &Path) -> anyhow::Result<Self> {
+		let Some(Component::Normal(first)) = path.components().nth(1) else {
+			bail!("Path is too short");
+		};
+
+		let result = if first == OsStr::new("index.dj") {
+			Self::Home
+		} else if first == OsStr::new("posts") {
+			if let Some(Component::Normal(second)) = path.components().nth(2) {
+				let mut slice = second.to_str().unwrap();
+				if slice.ends_with(".dj") {
+					slice = slice.strip_suffix(".dj").unwrap();
+				}
+
+				Self::Post(slice.to_owned())
+			} else {
+				Self::Posts
+			}
+		} else {
+			bail!("Cannot convert path '{:?}' to page route", path);
+		};
+
+		Ok(result)
+	}
+}
+
 #[derive(Debug)]
 pub struct PageMetadata {
 	pub title: Heading,
 	pub config: PageConfig,
-	pub toc: Vec<Heading>,
 	pub word_count: usize,
-	pub path: PathBuf,
 	pub last_modified: DateTime<FixedOffset>,
+	pub route: PageRoute,
+
+	#[allow(dead_code)]
+	pub toc: Vec<Heading>,
+	#[allow(dead_code)]
+	pub path: PathBuf,
 }
 
 impl PageMetadata {
@@ -72,17 +113,19 @@ impl PageMetadata {
 
 		Ok(Self {
 			title: title.to_owned(),
+			route: PageRoute::from_path(&path)?,
 			config: w.config,
 			toc: w.toc,
 			word_count: w.word_count,
-			path,
 			last_modified,
+			path,
 		})
 	}
 }
 
 #[derive(Debug, Clone)]
 pub struct Heading {
+	#[allow(dead_code)]
 	pub level: u8,
 	pub id: String,
 	pub text: String,