---
id: S01
parent: M010
milestone: M010
provides:
  - GET /topics/{category_slug}/{subtopic_slug} endpoint for filtered technique retrieval
  - SubTopicPage component and route at /topics/:category/:subtopic
  - Breadcrumb CSS pattern reusable by other pages
  - fetchSubTopicTechniques API client function
requires:
  []
affects:
  - S03
key_files:
  - backend/routers/topics.py
  - backend/tests/test_public_api.py
  - frontend/src/pages/SubTopicPage.tsx
  - frontend/src/api/public-client.ts
  - frontend/src/App.tsx
  - frontend/src/pages/TopicsBrowse.tsx
  - frontend/src/App.css
key_decisions:
  - Used PostgreSQL ARRAY contains (@>) for tag matching — simpler than unnest/ANY since tags are stored lowercase
  - Route registered before /{category_slug} to prevent FastAPI path conflict
  - Grouped techniques by creator with Map-based first-appearance ordering
  - Breadcrumb pattern: nav.breadcrumbs with link/text/current spans for reuse
patterns_established:
  - Sub-topic page pattern: URL params → API fetch → group by creator → render sections. Reusable for any filtered collection page.
  - Breadcrumb nav component pattern using nav.breadcrumbs CSS class with link/text/current span variants
observability_surfaces:
  - none
drill_down_paths:
  - .gsd/milestones/M010/slices/S01/tasks/T01-SUMMARY.md
  - .gsd/milestones/M010/slices/S01/tasks/T02-SUMMARY.md
duration: ""
verification_result: passed
completed_at: 2026-03-31T06:04:33.352Z
blocker_discovered: false
---

# S01: Dedicated Sub-Topic Pages

**Added dedicated sub-topic pages at /topics/:category/:subtopic with backend filtering endpoint, breadcrumb navigation, and creator-grouped technique listings.**

## What Happened

This slice added full-stack sub-topic browsing to Chrysopedia. Previously, clicking a sub-topic on the Topics page redirected to a search query — now it loads a dedicated page with structured content.

**Backend (T01):** Added `GET /topics/{category_slug}/{subtopic_slug}` endpoint to `routers/topics.py`. Uses PostgreSQL ARRAY contains (`@>`) to match the subtopic slug against the `topic_tags` column, filtered to the correct `topic_category`. Eager-loads the creator relation for `creator_name`/`creator_slug` fields. Returns `PaginatedResponse[TechniquePageRead]`. Route registered before the `/{category_slug}` catch-all to avoid FastAPI path conflicts. Three integration tests added and passing: happy path, empty results, and pagination.

**Frontend (T02):** Created `SubTopicPage.tsx` following the existing `CreatorDetail` pattern. Extracts `category` and `subtopic` from URL params, fetches via `fetchSubTopicTechniques` in `public-client.ts`, groups techniques by `creator_name` using Map-based ordering. Renders breadcrumbs (`Topics > Category > Sub-topic`), loading/error/empty states, and technique links to `/techniques/{slug}`. Route registered in `App.tsx`. Updated `TopicsBrowse.tsx` to link sub-topics to `/topics/{cat}/{subtopic}` instead of `/search?q=...`. Added breadcrumb CSS to `App.css`. Fixed a pre-existing TS strict error in `Home.tsx`.

## Verification

Frontend: `npx tsc --noEmit` passes (0 errors), `npm run build` succeeds (48 modules, 870ms). Backend: 3 subtopic integration tests pass against PostgreSQL on ub01 (verified by T01 executor — local machine lacks DB access).

## Requirements Advanced

- R008 — Sub-topics now have dedicated pages instead of redirecting to search. Clicking a sub-topic loads a structured page with creator-grouped techniques and breadcrumbs.

## Requirements Validated

None.

## New Requirements Surfaced

None.

## Requirements Invalidated or Re-scoped

None.

## Deviations

Fixed pre-existing ProcessingStatus.extracted → ProcessingStatus.complete in test seed helper. Fixed pre-existing TS strict error in Home.tsx. Both were required to make the build/tests pass but were not part of the slice plan.

## Known Limitations

Backend subtopic tests require PostgreSQL on ub01 (port 5433) — cannot run from this dev machine. Pre-existing tests (test_list_topics_hierarchy, test_topics_with_no_technique_pages) hardcode 6 categories but canonical_tags.yaml now has 7.

## Follow-ups

Fix hardcoded category count in pre-existing topic tests. Consider adding pytest-timeout to backend dev dependencies.

## Files Created/Modified

- `backend/routers/topics.py` — Added get_subtopic_techniques endpoint with ARRAY contains tag matching
- `backend/tests/test_public_api.py` — Added 3 subtopic integration tests, fixed ProcessingStatus enum in seed helper
- `frontend/src/pages/SubTopicPage.tsx` — New page component: breadcrumbs, creator-grouped technique list, loading/error/empty states
- `frontend/src/api/public-client.ts` — Added fetchSubTopicTechniques function
- `frontend/src/App.tsx` — Registered /topics/:category/:subtopic route before catch-all
- `frontend/src/pages/TopicsBrowse.tsx` — Updated sub-topic links to use dedicated page routes
- `frontend/src/App.css` — Added breadcrumb and sub-topic page styles
- `frontend/src/pages/Home.tsx` — Fixed pre-existing TS strict error
