6 Frontend
jlightner edited this page 2026-04-04 10:31:50 -05:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Frontend

React 18 + TypeScript + Vite SPA. No UI library, no state management library, no CSS framework.

Route Map

Route Page Component Auth Notes
/ Home Public Hero search, stats counters, popular topics, nav cards
/search SearchResults Public Sort, highlights, partial matches
/techniques/:slug TechniquePage Public v2 body sections, ToC sidebar, citations
/creators CreatorsBrowse Public Random default sort, genre filters
/creators/:slug CreatorDetail Public Avatar, stats, technique list, follow button, personality profile, chat widget
/topics TopicsBrowse Public 7 category cards, expandable sub-topics
/topics/:category/:subtopic SubTopicPage Public Creator-grouped techniques
/chat ChatPage Public Multi-message conversation UI with threading
/about About Public Static project info
/creator/highlights HighlightQueue Creator JWT Highlight review queue with filter tabs (M022/S01)
/creator/tiers CreatorTiers Creator JWT Free/Pro/Premium tier cards with Coming Soon modals (M022/S02)
/admin/reports AdminReports Admin* Content reports
/admin/pipeline AdminPipeline Admin* Pipeline management
/admin/techniques AdminTechniquePages Admin* Technique page admin
/creator/posts PostsList Creator JWT Creator post management — status badges, edit/delete (M023/S01)
/creator/posts/new PostEditor Creator JWT Tiptap rich text editor with file attachments (M023/S01)
/creator/posts/:postId/edit PostEditor Creator JWT Edit existing post (M023/S01)
/shorts/:token ShortPlayer Public Public short player outside ProtectedRoute — fetches via unauthenticated API (M024/S01)
/embed/:videoId EmbedPlayer Public Chrome-free embed player, registered before AppShell catch-all (M024/S03)
* → Redirect / SPA fallback

*Admin routes have no authentication gate.

Routing: All routes in a single <Routes> block in App.tsx. nginx returns the SPA shell for all paths; react-router-dom v6 handles client-side routing.

Shared Components

Component Purpose
SearchAutocomplete Global search with Ctrl+Shift+F shortcut (nav + mobile instances)
AdminDropdown Hover-open at desktop, tap-toggle on mobile
AppFooter Version, build date, GitHub link
TableOfContents Sticky sidebar ToC with IntersectionObserver scroll-spy
SortDropdown Reusable sort selector
TagList Tag/badge pills with +N overflow
CategoryIcons SVG icons per topic category
CreatorAvatar Avatar with fallback
CopyLinkButton Clipboard copy with tooltip
SocialIcons Social media link icons (9 platforms)
ReportIssueModal Content report submission
PostsFeed Published posts feed with Tiptap JSON→HTML rendering and file downloads (M023/S01)
ChatWidget Floating chat bubble on creator pages — SSE streaming, citations, suggested questions (M022/S03)
PersonalityProfile Collapsible creator personality display — 3 sub-cards (Teaching Style, Vocabulary, Style) (M022/S06)

Feature Pages (M022)

HighlightQueue (M022/S01)

Creator-scoped highlight review page at /creator/highlights.

  • Filter tabs — All / Shorts / Approved / Rejected
  • Candidate cards — Title, duration, composite score, status badge
  • Score breakdown bars — 10-dimension visual bars (fetched lazily on expand)
  • Action buttons — Approve / Discard with ownership verification
  • Inline trim panel — Validated trim_start / trim_end inputs
  • Files: HighlightQueue.tsx, HighlightQueue.module.css, highlights.ts (API)

CreatorTiers (M022/S02)

Tier configuration at /creator/tiers.

  • Three cards — Free (active), Pro, Premium
  • Coming Soon modals — Styled placeholders per D033 (Stripe deferred to Phase 3)
  • Files: CreatorTiers.tsx, CreatorTiers.module.css

ChatWidget (M022/S03)

Floating chat on creator detail pages.

  • Fixed-position bubble (bottom-right) → slide-up conversation panel
  • Creator-scoped — passes creatorName to streamChat() for retrieval cascade
  • Suggested questions — client-side from technique titles/categories
  • Streaming SSE — tokens, citations, typing indicator
  • Responsive — full-width below 640px, 400px panel on desktop
  • Conversation threading — conversationId via crypto.randomUUID(), resets on close
  • Files: ChatWidget.tsx, ChatWidget.module.css

PersonalityProfile (M022/S06)

Collapsible personality display on creator detail pages.

  • Grid-template-rows animation — 0fr → 1fr for smooth expand/collapse
  • Three sub-cards: Teaching Style, Vocabulary, Style
  • Pill badges for phrases/terms, checkmark/cross for boolean markers
  • Gracefully hidden when profile is null
  • Files: PersonalityProfile.tsx, styles in App.css

PostEditor (M023/S01)

Rich text editor at /creator/posts/new and /creator/posts/:postId/edit.

  • Tiptap v3 with StarterKit + Link + Placeholder extensions
  • Formatting toolbar — bold, italic, lists, headings, links
  • File attachment zone — drag-and-drop with multipart upload to MinIO
  • Publish toggle — draft/published state
  • Sequential save flow — create post → upload files
  • Files: PostEditor.tsx, PostEditor.module.css

PostsList (M023/S01)

Creator post management at /creator/posts.

  • Status badges — Draft / Published
  • Edit/Delete actions with confirmation dialog
  • SidebarNav integration — accessible from creator dashboard
  • Files: PostsList.tsx, PostsList.module.css

Shorts UI (M023/S03, M024/S01, S04)

Shorts generation controls in HighlightQueue.

  • Generate button — visible on approved highlights with no in-progress shorts
  • Per-preset status badges — color-coded pending/processing/complete/failed with pulsing animation
  • Download links — open presigned MinIO URLs in new tab
  • 5s polling — while any shorts are processing, auto-stops when all settle
  • Share link + embed code copy buttons🔗 and 📋 icons on completed shorts with share_token (M024/S01)
  • Collapsible template config panel — intro/outro text, duration sliders, show/hide toggles, color picker, font selection (M024/S04)
  • Per-highlight captions toggle — checkbox to enable ASS subtitle generation (M024/S04)
  • Files: HighlightQueue.tsx, HighlightQueue.module.css (updated)

ShortPlayer (M024/S01)

Public short video player at /shorts/:token.

  • Unauthenticated — fetches via fetchPublicShort() (raw fetch(), no auth token injection)
  • Video rendering<video> element with presigned MinIO URL
  • Creator/highlight metadata — format, dimensions, duration, creator name, title
  • Share/embed buttons — copy share URL and iframe embed snippet to clipboard
  • Only renders share/embed when share_token is non-null (graceful for pre-migration shorts)
  • Files: ShortPlayer.tsx, ShortPlayer.module.css

EmbedPlayer (M024/S03)

Chrome-free embed player at /embed/:videoId.

  • No header/nav/footer — registered at top-level Routes before AppShell catch-all
  • Content-type-aware height — 120px for audio-only, 405px for video
  • "Powered by Chrysopedia" branding — link opens origin in new tab with noopener
  • Code-split — lazy-loaded via React.lazy + Suspense
  • Files: EmbedPlayer.tsx, EmbedPlayer.module.css

Personality Slider (M023/S02, S04)

ChatWidget personality control.

  • Range input (0.01.0, step 0.1) with gradient track fill via --slider-fill CSS custom property
  • Tier labels — Encyclopedic / Subtle Reference / Creator Tone / Creator Voice / Full Embodiment
  • Numeric display with tabular-nums for stable width
  • Labels match backend 5-tier interpolation boundaries (0.2/0.4/0.6/0.8)
  • Files: ChatWidget.tsx, ChatWidget.module.css (updated)

Shared Utilities (M024)

Utility Path Purpose
copyToClipboard utils/clipboard.ts Shared clipboard utility — navigator.clipboard with document.execCommand fallback (M024/S03)
parseChatCitations utils/chatCitations.tsx Shared citation parser replacing duplicate implementations in ChatPage and ChatWidget (M024/S05)
formatTime utils/formatTime.ts Shared hour-aware time formatter replacing duplicated implementations across 4+ files (M024/S05)

Hooks

Hook Purpose
useCountUp Animated counter for homepage stats
useSortPreference Persists sort preference in localStorage
useDocumentTitle Sets <title> per page (all pages instrumented)

State Management

Local component state only (useState/useEffect). No Redux, Zustand, Context providers, or external state management library. AuthProvider context for JWT auth state.

API Client

API modules:

  • public-client.ts (~600 lines) — typed request<T> helper for REST endpoints
  • chat.ts — SSE streaming client for POST /api/v1/chat using fetch() + ReadableStream, ChatDoneMeta type
  • videos.ts — chapter management functions
  • auth.ts — authentication + impersonation functions
  • highlights.ts
  • posts.ts — post CRUD and file upload/download functions (M023/S01)
  • shorts.ts — short generation, listing, and download functions (M023/S03); fetchPublicShort for unauthenticated access (M024/S01) — creator highlight review functions (M022/S01)
  • templates.ts — shorts template CRUD API client (M024/S04)
  • follows.ts — follow/unfollow/status/list functions (M022/S02)
  • creators.ts — creator detail with personality_profile and follower_count types (M022/S02, S06)

Relative /api/v1 base URL (nginx proxies to API container).

M025 Pages & Components

CreatorOnboarding (M025/S03)

  • Route: /creator/onboarding
  • File: frontend/src/pages/CreatorOnboarding.tsx + .module.css
  • Auth: ProtectedRoute (requires login)
  • Description: 3-step wizard (Welcome -> Consent Setup -> Dashboard Tour). Step 2 fetches real consent data. Stepper UI with numbered circles and connecting lines. Responsive at 375px.
  • Trigger: Login redirects here when onboarding_completed === false

AdminUsage (M025/S04)

  • Route: /admin/usage
  • File: frontend/src/pages/AdminUsage.tsx + .module.css
  • Auth: Admin only (via AdminDropdown menu)
  • Description: Token usage dashboard with summary cards (today/week/month totals), CSS bar chart for daily activity, and breakdown tables (top creators, top users).
  • API: GET /api/v1/admin/usage

CreatorTransparency (M025/S05)

  • Route: /creator/transparency
  • File: frontend/src/pages/CreatorTransparency.tsx + .module.css
  • Auth: ProtectedRoute (requires linked creator profile)
  • Description: Full entity graph viewer with tag summary bar and 4 collapsible sections: Technique Pages, Key Moments (grouped by source video), Cross-References, Source Videos. Uses grid-template-rows: 0fr/1fr animation for collapse/expand.
  • Nav: Sidebar link between Tiers and Posts on CreatorDashboard

ReadingHeader (M025/S10)

  • File: frontend/src/components/ReadingHeader.tsx
  • Description: Sticky section bar on technique pages. Fixed-position bar slides in via CSS transform when user scrolls past the title. Uses sentinel-based IntersectionObserver with callback ref pattern.
  • Integration: Rendered by TechniquePage.tsx, receives activeId from parent

Export My Data (M025/S07)

  • Location: Button on CreatorDashboard
  • API: exportCreatorData() in frontend/src/api/creator-dashboard.ts
  • Pattern: fetch with Bearer token -> response.blob() -> hidden anchor + URL.createObjectURL -> click -> revoke
  • UX: Loading spinner during download, inline error display on failure

CSS Architecture

Property Value
File frontend/src/App.css
Lines ~6,500+
Naming BEM (block__element--modifier)
Theme Dark-only (no light mode)
Custom properties 77 in :root (D017)
Accent color Cyan #22d3ee
Font stack System fonts
CSS Modules Used for new components (HighlightQueue, CreatorTiers, ChatWidget, ChatPage)

Breakpoints

Breakpoint Usage
480px Narrow mobile — compact cards
600px Wider mobile — grid adjustments
640px Small tablet / chat widget responsive break
768px Desktop ↔ mobile transition — sidebar collapse

Layout Patterns

  • Page max-width: 64rem (D019)
  • Technique page: CSS grid 2-column (1fr + 22rem sidebar), collapses at 768px
  • Card layouts: CSS grid with auto-fill, minmax(...) for responsive grids
  • Collapsible sections: grid-template-rows: 0fr/1fr animation
  • Sticky elements: ToC sidebar, reading header

Build

  • Bundler: Vite
  • Build-time constants: __APP_VERSION__, __BUILD_DATE__, __GIT_COMMIT__ via define (must use JSON.stringify)
  • Dev proxy: /apilocalhost:8001
  • Production: nginx serves static dist/ bundle, proxies /api to FastAPI container

See also: Architecture, API-Surface, Development-Guide