---
id: S05
parent: M014
milestone: M014
provides:
  - V2 format-aware technique page rendering (TOC, nested sections, citations) for S07 deep linking
requires:
  - slice: S03
    provides: body_sections_format and source_videos fields in API response schema
affects:
  - S07
key_files:
  - frontend/src/pages/TechniquePage.tsx
  - frontend/src/components/TableOfContents.tsx
  - frontend/src/utils/citations.tsx
  - frontend/src/api/public-client.ts
  - frontend/src/App.css
key_decisions:
  - Subsection IDs use compound slugs (sectionSlug--subSlug) to avoid anchor collision between sections and subsections
  - D024 enforced: sections with subsections skip empty content paragraph
  - Invalid citation indices render as plain text rather than broken links
patterns_established:
  - Format-discriminated rendering: body_sections_format field selects v1 (dict) or v2 (array) renderer, keeping both paths independent
  - Citation parsing as a standalone utility (parseCitations) reusable for any component rendering technique page content
observability_surfaces:
  - none
drill_down_paths:
  - .gsd/milestones/M014/slices/S05/tasks/T01-SUMMARY.md
  - .gsd/milestones/M014/slices/S05/tasks/T02-SUMMARY.md
duration: ""
verification_result: passed
completed_at: 2026-04-03T01:47:43.749Z
blocker_discovered: false
---

# S05: Frontend — Nested Rendering, TOC, Citations

**Format-2 technique pages render with nested H2/H3 sections, a clickable TOC, and citation superscript links; format-1 pages unchanged; deployed to production.**

## What Happened

Built format-aware rendering in TechniquePage.tsx that detects body_sections_format=2 (list-of-objects) vs format=1 (dict) and renders accordingly. V2 path renders a TableOfContents component with CSS-counter-numbered nested anchor links, H2 sections with slugified IDs, H3 subsections with compound slug IDs (sectionSlug--subSlug), and citation parsing. The parseCitations utility in citations.tsx converts [N] and [N,M] markers to superscript anchor links targeting key moment IDs; invalid indices render as plain text. V1 dict rendering is completely untouched.

TypeScript types updated with BodySectionV2, BodySubSectionV2 interfaces, body_sections_format discriminator, and source_videos field. snapshotToOverlay updated to pass through list-format body_sections.

CSS additions: TOC card with sticky positioning, subsection left-border styling, citation superscript links with hover states, scroll-margin-top on anchored sections for smooth scrolling past the fixed header.

Deployed to ub01 production: pushed 11 commits, built chrysopedia-web container (56 modules, 0 Vite/TS errors), verified HTTP 200 on site root and /health. No v2 pages exist in production yet (S04 populated them on test data), so v2 rendering is verified structurally via the TypeScript build. V1 pages render unchanged.

## Verification

Frontend build: `cd frontend && npm run build` exits 0, 56 modules, no errors. Production: curl http://ub01:8096/ returns 200. Health: curl http://ub01:8096/health returns 200. JS bundle hash matches build output.

## Requirements Advanced

- R006 — Technique page display now supports v2 nested sections with TOC and citations in addition to existing v1 format

## Requirements Validated

None.

## New Requirements Surfaced

None.

## Requirements Invalidated or Re-scoped

None.

## Deviations

Docker Compose service name is chrysopedia-web, not chrysopedia-web-8096 as listed in the slice plan verify command. The plan's verify command had shell quoting issues. T02 used the correct service name.

## Known Limitations

V2 rendering only verified structurally (TypeScript build) — no live v2 pages exist in production yet. Visual verification of TOC, citations, and nested sections requires S04 to populate v2 pages first. ub01 has a stashed git state with local backend edits from prior work.

## Follow-ups

Visual QA of v2 rendering once S04 data is in production. Review stashed edits on ub01.

## Files Created/Modified

- `frontend/src/pages/TechniquePage.tsx` — Format-aware rendering: v2 array → TOC + nested H2/H3 sections + citation links; v1 dict unchanged
- `frontend/src/components/TableOfContents.tsx` — New component: CSS-counter-numbered nested anchor link list for v2 sections
- `frontend/src/utils/citations.tsx` — New utility: parseCitations converts [N] and [N,M] markers to superscript anchor links
- `frontend/src/api/public-client.ts` — Added BodySectionV2, BodySubSectionV2 types, body_sections_format, source_videos fields
- `frontend/src/App.css` — TOC card styles, subsection borders, citation superscripts, scroll-margin-top for anchored sections
