From aeb033bae51984b61ec4e20572ca1b11f0a17344 Mon Sep 17 00:00:00 2001 From: Josh Date: Mon, 18 May 2026 11:18:35 -0700 Subject: [PATCH] feat(routing): redirect section landings + harden 404 / no directory listings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - astro.config.mjs: section-only URLs now redirect to the first article in that section. /whp/admin/ used to render Apache's directory listing because no index.html existed; now it serves a meta-refresh to /whp/admin/overview/. Same for /whp/, /whp/getting-started/, /whp/how-to/, /whp/site-builder/, /whp/reference/, /whp/add-ons/. - public/.htaccess: ships in dist, disables Options Indexes + MultiViews (defense in depth so any future section without a redirect doesn't leak a listing), and routes 404/403 to /404.html. - src/content/docs/404.md: replaces the bare 'check the URL' tagline with two explicit actions — 'Go to the knowledge base home' and 'WHP getting started'. --- astro.config.mjs | 12 ++++++++++++ public/.htaccess | 15 +++++++++++++++ src/content/docs/404.md | 17 +++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 public/.htaccess create mode 100644 src/content/docs/404.md diff --git a/astro.config.mjs b/astro.config.mjs index 97090df..0c26271 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -7,6 +7,18 @@ import { fileURLToPath } from 'node:url'; // https://astro.build/config export default defineConfig({ site: 'https://kb.anhonesthost.com', + // Send section-only URLs to the first article in that section. Without these, + // hitting e.g. /whp/admin/ would render the Apache directory listing because + // there is no index.html in that folder. + redirects: { + '/whp/': '/whp/getting-started/welcome/', + '/whp/getting-started/': '/whp/getting-started/welcome/', + '/whp/how-to/': '/whp/how-to/add-a-domain/', + '/whp/site-builder/': '/whp/site-builder/overview/', + '/whp/reference/': '/whp/reference/service-hostnames/', + '/whp/add-ons/': '/whp/add-ons/overview/', + '/whp/admin/': '/whp/admin/overview/', + }, vite: { resolve: { alias: { diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..0753aab --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,15 @@ +# Static-HTML site hardening for kb.anhonesthost.com. +# Lands in dist/ at build time and is uploaded with the rest of the site. + +# Never expose a directory listing to visitors. +Options -Indexes + +# Astro emits both /path/ (with index.html) and /path.html for every route. +# Default to the trailing-slash form; Apache MultiViews can sometimes serve +# /path.html for /path/, which Pagefind doesn't index — disable it. +Options -MultiViews + +# Send anything that doesn't resolve to a file to /404.html. +# Starlight builds a real 404 page; this just makes Apache serve it. +ErrorDocument 404 /404.html +ErrorDocument 403 /404.html diff --git a/src/content/docs/404.md b/src/content/docs/404.md new file mode 100644 index 0000000..415d861 --- /dev/null +++ b/src/content/docs/404.md @@ -0,0 +1,17 @@ +--- +title: Page not found +description: That URL doesn't exist on our knowledge base. +template: splash +editUrl: false +hero: + title: '404' + tagline: That URL doesn't exist on our knowledge base. + actions: + - text: Go to the knowledge base home + link: / + icon: right-arrow + variant: primary + - text: WHP getting started + link: /whp/getting-started/welcome/ + variant: secondary +---