diff --git a/crates/treehouse/src/cli/serve.rs b/crates/treehouse/src/cli/serve.rs
index 4f2f0db..38279a5 100644
--- a/crates/treehouse/src/cli/serve.rs
+++ b/crates/treehouse/src/cli/serve.rs
@@ -2,7 +2,6 @@
 mod live_reload;
 mod picture_upload;
 
-use std::fmt::Write;
 use std::{net::Ipv4Addr, sync::Arc};
 
 use axum::http::header::LOCATION;
@@ -22,9 +21,9 @@ use tracing::{error, info, instrument};
 
 use crate::dirs::Dirs;
 use crate::sources::Sources;
+use crate::state::Source;
 use crate::vfs::asynch::AsyncDir;
 use crate::vfs::{self, VPath};
-use crate::{html::EscapeHtml, state::Source};
 
 mod system {
     use crate::vfs::VPath;
@@ -76,6 +75,12 @@ struct VfsQuery {
 #[instrument(skip(state))]
 async fn get_static_file(path: &str, query: &VfsQuery, state: &Server) -> Option<Response> {
     let vpath = VPath::try_new(path).ok()?;
+
+    if let Some(target) = state.sources.config.redirects.path.get(vpath) {
+        let url = vfs::url(&state.sources.config.site, state.target.sync(), target)?;
+        return Some((StatusCode::MOVED_PERMANENTLY, [(LOCATION, url)]).into_response());
+    }
+
     let content = state.target.content(vpath).await?;
     let content_type = HeaderValue::from_str(content.kind()).inspect_err(
         |err| error!(?err, content_type = ?content.kind(), "content type cannot be used as an HTTP header"),
diff --git a/crates/treehouse/src/config.rs b/crates/treehouse/src/config.rs
index 5570f17..67d7493 100644
--- a/crates/treehouse/src/config.rs
+++ b/crates/treehouse/src/config.rs
@@ -88,9 +88,9 @@ pub struct Feed {
 
 #[derive(Debug, Clone, Deserialize, Serialize)]
 pub struct Redirects {
-    /// Page redirects. When a user navigates to a page, if they navigate to `url`, they will
-    /// be redirected to `page[url]`.
-    pub page: HashMap<String, String>,
+    /// Path redirects. When a user requests a path, if they request `p`, they will be redirected
+    /// to `path[p]` with a `301 Moved Permanently` status code.
+    pub path: HashMap<VPathBuf, VPathBuf>,
 }
 
 #[derive(Debug, Clone, Deserialize, Serialize)]