---
estimated_steps: 16
estimated_files: 4
skills_used: []
---

# T02: Frontend — Hash scroll handler + section search result rendering

Extend TechniquePage hash scrolling to handle section anchors (not just #km-). Update search result components to display and link technique_section results. Add section_anchor and section_heading to the TypeScript SearchResultItem type.

## Steps

1. **Add `section_anchor` and `section_heading` to SearchResultItem** in `frontend/src/api/public-client.ts`. Both optional strings.

2. **Generalize hash scroll in TechniquePage.tsx**. The existing useEffect (line ~175) only scrolls for `#km-` hashes. Change it to scroll to ANY hash fragment after technique data loads: `const hash = window.location.hash.slice(1); if (hash) { const el = document.getElementById(hash); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' }); }`. This handles both key moment hashes and section anchors.

3. **Add `technique_section` branch to `getSearchResultLink()`** in `frontend/src/pages/SearchResults.tsx`. If `item.type === 'technique_section'`, return `/techniques/${item.technique_page_slug}#${item.section_anchor}`. Place this before the existing `key_moment` branch.

4. **Update `SearchResultCard` badge display** — add a 'Section' label for technique_section type. Show section_heading as subtitle context if present.

5. **Update `SearchAutocomplete` autocomplete results** in `frontend/src/components/SearchAutocomplete.tsx`. The type label map (line ~165) needs `technique_section: 'Section'`. The link at line ~221 (`/techniques/${item.slug}`) needs the same section-aware logic: if type is technique_section, link to `/techniques/${item.technique_page_slug}#${item.section_anchor}`.

6. **Update result filtering** in SearchResults.tsx PartialMatchResults — add technique_section to the filter groups (currently only filters technique_page and key_moment).

7. **Build and verify** — `cd frontend && npm run build` must pass with zero errors.

## Must-Haves

- [ ] Hash scroll works for section anchors (e.g., #grain-position-control)
- [ ] Hash scroll still works for key moment anchors (e.g., #km-some-moment)
- [ ] technique_section results link to /techniques/{slug}#{anchor}
- [ ] Badge shows 'Section' for technique_section results
- [ ] Autocomplete links section results correctly
- [ ] Frontend builds with zero TypeScript errors

## Inputs

- ``frontend/src/api/public-client.ts` — existing SearchResultItem interface`
- ``frontend/src/pages/TechniquePage.tsx` — existing #km- hash scroll useEffect at line ~175`
- ``frontend/src/pages/SearchResults.tsx` — existing getSearchResultLink and SearchResultCard`
- ``frontend/src/components/SearchAutocomplete.tsx` — existing type label map and result links`
- ``backend/schemas.py` — T01 output: section_anchor and section_heading fields on SearchResultItem`

## Expected Output

- ``frontend/src/api/public-client.ts` — SearchResultItem with section_anchor and section_heading`
- ``frontend/src/pages/TechniquePage.tsx` — generalized hash scroll handling for any anchor`
- ``frontend/src/pages/SearchResults.tsx` — technique_section link routing, badge, and filter handling`
- ``frontend/src/components/SearchAutocomplete.tsx` — technique_section type label and link routing`

## Verification

cd frontend && npm run build 2>&1 | tail -5 && echo 'Build OK'
