diff --git a/frontend/src/routes/[fam]/+layout.server.ts b/frontend/src/routes/[fam]/+layout.server.ts index c1728cf..628ece6 100644 --- a/frontend/src/routes/[fam]/+layout.server.ts +++ b/frontend/src/routes/[fam]/+layout.server.ts @@ -1,3 +1,4 @@ +import { redirect } from '@sveltejs/kit'; import { createPbClient } from '$lib/server/pocketbase'; import { createServices, type ChatActor } from '$lib/server/services'; import { ensureFamAccess } from '$lib/server/access'; @@ -63,6 +64,17 @@ export async function load(event) { fam = res.fam; famAccess = res.access; } + // Canonical URL: the [fam] segment must be the family SLUG, never the PB + // id. If someone lands on /{famId}/... (a stale shortcut, bookmark, or a + // login that fell back to the id), rewrite the first path segment to the + // slug so the id is replaced everywhere it'd otherwise persist. + const paramFam = event.params.fam; + const canonicalSlug = fam?.slug; + if (canonicalSlug && paramFam && paramFam !== canonicalSlug) { + const rest = event.url.pathname.replace(`/${paramFam}`, '') || '/'; + const qs = event.url.search; + throw redirect(303, `/${encodeURIComponent(canonicalSlug)}${rest}${qs}`); + } } return { diff --git a/frontend/src/routes/[fam]/+layout.svelte b/frontend/src/routes/[fam]/+layout.svelte index 47e4f7c..055a96d 100644 --- a/frontend/src/routes/[fam]/+layout.svelte +++ b/frontend/src/routes/[fam]/+layout.svelte @@ -117,7 +117,7 @@ $effect(() => { if (!page.data.session) return; recordShortcut({ - famSlug: page.params.fam || '', + famSlug: (page.data.fam?.slug as string) || page.params.fam || '', famName: (page.data.fam?.name as string) || page.params.fam || '', userName: page.data.role === 'parent' ? '' : page.params.username || '' });