diff --git a/packages/stacks-docs-next/_redirects b/packages/stacks-docs-next/_redirects index 7ec3031777..470b841c97 100644 --- a/packages/stacks-docs-next/_redirects +++ b/packages/stacks-docs-next/_redirects @@ -2,22 +2,6 @@ https://alpha.stackoverflow.design/* https://stackoverflow.design/:splat 301 https://beta.stackoverflow.design/* https://stackoverflow.design/:splat 302 -# Section index pages → first child (mirrors Navigation.svelte L67) -/brand/ /brand/logo 302 - -/copy/ /copy/voice 302 -/copy/patterns/ /copy/patterns/messages 302 - -/system/ /system/develop/using-stacks 302 -/system/develop/ /system/develop/using-stacks 302 -/system/accessibility/ /system/accessibility/intro 302 -/system/foundation/ /system/foundation/color-fundamentals 302 -/system/base/ /system/base/backgrounds 302 -/system/forms/ /system/forms/checkbox 302 -/system/components/ /system/components/activity-indicator 302 - -/handbook/ /handbook/story 302 -/resources/ /resources/fonts 302 # Email section → v2 docs /email* https://v2.stackoverflow.design/email:splat 302 @@ -65,9 +49,6 @@ https://beta.stackoverflow.design/* https://stackoverflow.design/:s # General catch-all: all remaining /product/* → /system/* /product/* /system/:splat 302 -# Assets -/assets/img/logo-stacks@2x.png /assets/img/logos/so/logo-stacks@2x.png 302 - # Legacy /content paths (brand & copywriting, migrated Feb 2026) /content /copy 302 /content/guidelines/principles /copy 302 diff --git a/packages/stacks-docs-next/src/routes/[category]/+page.server.ts b/packages/stacks-docs-next/src/routes/[category]/+page.server.ts new file mode 100644 index 0000000000..274aff5b63 --- /dev/null +++ b/packages/stacks-docs-next/src/routes/[category]/+page.server.ts @@ -0,0 +1,9 @@ +import type { PageServerLoad } from "./$types"; +import { error } from "@sveltejs/kit"; + +export const load: PageServerLoad = async (event) => { + const parent = await event.parent(); + if (!parent.active) { + throw error(404, `No content found for /${event.params.category}`); + } +}; diff --git a/packages/stacks-docs-next/src/routes/[category]/[[section]]/[subsection]/+page.server.ts b/packages/stacks-docs-next/src/routes/[category]/[[section]]/[subsection]/+page.server.ts index 64f36de9f6..508c7a5618 100644 --- a/packages/stacks-docs-next/src/routes/[category]/[[section]]/[subsection]/+page.server.ts +++ b/packages/stacks-docs-next/src/routes/[category]/[[section]]/[subsection]/+page.server.ts @@ -1,5 +1,5 @@ import type { PageServerLoad } from "./$types"; -import { error } from "@sveltejs/kit"; +import { error, redirect } from "@sveltejs/kit"; import type { Component } from "svelte"; import { render } from "svelte/server"; import TurndownService from "turndown"; @@ -10,6 +10,13 @@ const turndownService = new TurndownService({ const mdFiles = import.meta.glob("$docs/**/*.md"); +type NavItem = { slug: string; items?: NavItem[] }; + +function firstLeafSlug(prefix: string, item: NavItem): string { + if (!item.items?.length) return `${prefix}/${item.slug}`; + return firstLeafSlug(`${prefix}/${item.slug}`, item.items[0]); +} + export const load: PageServerLoad = async (event) => { // SECURITY: Check auth first - don't load any content if unauthorized const parent = await event.parent(); @@ -56,5 +63,10 @@ export const load: PageServerLoad = async (event) => { }; } + // If the active item is a section (has children), redirect to the first leaf page + if (parent.active?.items?.length > 0) { + throw redirect(302, `/${firstLeafSlug(slug, parent.active.items[0])}`); + } + throw error(404, `No content found for ${slug}`); };