Problem
The Timeline/List schedule filter sheet encodes the stages search param as raw stage UUIDs (e.g. stages=["11111111-1111-1111-1111-11111111111a"]), matching src/lib/searchSchemas.ts:41 (stages: z.array(z.string()).catch([])) and written via useTimelineUrlState.updateStages (src/hooks/useTimelineUrlState.ts:44-53).
This makes the URL both illegible to users (nothing readable in a shared/bookmarked link) and easy to get wrong when constructing URLs by hand (e.g. in tests) — a UUID silently fails schema validation if not JSON-array-encoded exactly as TanStack Router's default serializer expects, falling back to [] with no error.
stages already has a slug column (supabase/migrations/20250905000000_add_group_stage_slugs.sql), so switching the stages search param (and any other filter params keyed by UUID) to use slugs would make schedule filter URLs human-readable and more robust to construct/share, consistent with how festivalSlug/editionSlug already work in the route path.
Suggested scope
- Audit
src/lib/searchSchemas.ts and useTimelineUrlState/ScheduleFilterSheet for any other UUID-keyed filter params (stages is the one found so far).
- Serialize/deserialize
stages by slug instead of id, resolving to the underlying stage id internally where needed (e.g. StageFilterButtons.tsx, useScheduleData.ts).
- Update e2e tests that build filter URLs directly (
tests/e2e/schedule-filter-sheet.spec.ts) to use slugs.
Found while investigating an e2e flake in schedule-filter-sheet.spec.ts where a hand-built stages=<uuid> URL failed schema validation and silently reset to no stage filter.
Problem
The Timeline/List schedule filter sheet encodes the
stagessearch param as raw stage UUIDs (e.g.stages=["11111111-1111-1111-1111-11111111111a"]), matchingsrc/lib/searchSchemas.ts:41(stages: z.array(z.string()).catch([])) and written viauseTimelineUrlState.updateStages(src/hooks/useTimelineUrlState.ts:44-53).This makes the URL both illegible to users (nothing readable in a shared/bookmarked link) and easy to get wrong when constructing URLs by hand (e.g. in tests) — a UUID silently fails schema validation if not JSON-array-encoded exactly as TanStack Router's default serializer expects, falling back to
[]with no error.stagesalready has aslugcolumn (supabase/migrations/20250905000000_add_group_stage_slugs.sql), so switching thestagessearch param (and any other filter params keyed by UUID) to use slugs would make schedule filter URLs human-readable and more robust to construct/share, consistent with howfestivalSlug/editionSlugalready work in the route path.Suggested scope
src/lib/searchSchemas.tsanduseTimelineUrlState/ScheduleFilterSheetfor any other UUID-keyed filter params (stages is the one found so far).stagesby slug instead of id, resolving to the underlying stage id internally where needed (e.g.StageFilterButtons.tsx,useScheduleData.ts).tests/e2e/schedule-filter-sheet.spec.ts) to use slugs.Found while investigating an e2e flake in
schedule-filter-sheet.spec.tswhere a hand-builtstages=<uuid>URL failed schema validation and silently reset to no stage filter.