Page Choreography
This document explains how each major route is assembled, what motion sequencing it uses, and where page-level orchestration versus shared component concerns live.
For the motion primitive catalog, see Motion architecture. For the component layer, see Component architecture.
Route assembly overview
Home (/)
The home page is the most orchestration-heavy route. It renders a faux-VS Code IDE as an interactive hero element.
Assembly
Entrance sequence
Page-owned state
| State | Purpose |
|---|---|
ideWindowState | normal / minimized / expanded |
ideWindowSize | width × height for resize |
| Drag constraints | Bound to hero container via heroBoundsRef |
| Typewriter playing | Triggered by HeroMotionPath completion |
| Scroll transforms | heroScale and heroOpacity from scroll progress |
| Welcome sequence | Managed by useHomeWelcomeSequence() hook |
IDE window interactions
CV (/cv)
The CV page has two modes: a default grid layout and an immersive story viewer.
Default mode — assembly
Section layout metadata
src/pages/cvPageLayout.ts defines per-section placement and motion timing:
| Section | Desktop region | Desktop delay | Desktop triggerOnView | Mobile order |
|---|---|---|---|---|
| about | top | 0ms | false (immediate) | 0 |
| experience | main | 120ms | true | 1 |
| education | main | 240ms | true | 2 |
| volunteering | main | 360ms | true | 3 |
| github | sidebar | 120ms | true | 4 |
| certificates | sidebar | 240ms | true | 5 |
| coding | main | 480ms | true | 6 |
On mobile, all sections stack vertically with delayMs: 0 and most use triggerOnView: true (viewport-triggered reveal).
Within each section
Each CVSection* component wraps a CVSectionCard which contains:
SectionHeading(overline + title)- Feature content (list, profile card, GitHub panel, etc.)
- Internal
AnimatedContentListfor repeated entries (with per-item stagger) - Optional
TabPanel/AnimatedSlideListfor expandable detail
Story mode (?mode=story)
Activated via query parameter. Replaces the grid layout with CVStoryViewer, a fullscreen scroll container that renders the ordered story chapters from buildCVStoryItems().
Climbing (/climbing)
Assembly
useFuzzySearch()provides route/location filtering across both DataGrid tables- initial load shows only the typed
CLIMBINGeyebrow; the analytics and tables stay deferred until the user scrolls far enough to hide the header - once unlocked, the main climbing card enters with the same spring-style card motion used by the deferred CV sections
- Analytics panels use
SectionPanelfor dense data display
Photography (/photography)
Assembly
AlbumCardwraps inMotionTiltCardon desktop for 3D tilt parallaxStaggerChildrenorchestrates sequential reveal across album cards- Image load state tracked to prevent layout shift during loading
Category detail (/photography/:slug)
- Quilted layout uses MUI
ImageListwith responsive column counts ImmersiveLightboxis a full-screen overlay with keyboard navigation, download, and close- Legacy slug redirects handled in the component for backward compatibility
Blog (/blog)
Public route rendered as part of the standard route set.
Assembly
BlogHerousesContentCardwith display-scale typography (editorial exception)BlogPostListrendersBlogPostCarditems in a responsive grid- Tag filtering is page-local state driven by
useBlogData().tags
Post detail (/blog/:slug)
BlogArticleBodyrenders typedBlogContentBlock[]: text, code, image, callout, blockquoteBlogCodeBlockprovides syntax highlighting with copy-to-clipboard- Not-found slugs render
RouteRecoveryPanelwith contextual suggestions