feat: Added /about page with three content sections (what, how, who) an…

- "frontend/src/pages/About.tsx"
- "frontend/src/App.tsx"
- "frontend/src/components/AppFooter.tsx"
- "frontend/src/App.css"

GSD-Task: S02/T01
This commit is contained in:
jlightner 2026-03-31 05:41:54 +00:00
parent a41efec4e4
commit 32114ec360
13 changed files with 524 additions and 3 deletions

View file

@ -6,6 +6,6 @@ The homepage is Chrysopedia's front door. Right now it's a search box — functi
## Slice Overview ## Slice Overview
| ID | Slice | Risk | Depends | Done | After this | | ID | Slice | Risk | Depends | Done | After this |
|----|-------|------|---------|------|------------| |----|-------|------|---------|------|------------|
| S01 | Homepage Hero & Value Proposition | medium | — | | Homepage shows tagline, value description, how-it-works steps, Start Exploring CTA, and popular topic quick-links above the fold | | S01 | Homepage Hero & Value Proposition | medium | — | | Homepage shows tagline, value description, how-it-works steps, Start Exploring CTA, and popular topic quick-links above the fold |
| S02 | About Page | low | — | ⬜ | About page at /about explains what Chrysopedia is, how content is extracted, and who maintains it. Link visible in footer. | | S02 | About Page | low | — | ⬜ | About page at /about explains what Chrysopedia is, how content is extracted, and who maintains it. Link visible in footer. |
| S03 | Featured Content & Content Teasers | low | S01 | ⬜ | Homepage shows a featured technique spotlight and Recently Added section with enriched cards | | S03 | Featured Content & Content Teasers | low | S01 | ⬜ | Homepage shows a featured technique spotlight and Recently Added section with enriched cards |

View file

@ -0,0 +1,81 @@
---
id: S01
parent: M009
milestone: M009
provides:
- Homepage hero section with tagline, value prop, how-it-works, CTA — S03 builds on this layout for featured content
requires:
[]
affects:
- S03
key_files:
- frontend/src/pages/Home.tsx
- frontend/src/App.css
key_decisions:
- Used cyan accent numbered circles for how-it-works steps to match existing design language
- Used uppercase secondary-text heading for Popular Topics to differentiate from primary content hierarchy
- Popular topics pills link to /search?q={topic}&scope=topics rather than a dedicated topic detail page
patterns_established:
- Homepage content sections use BEM naming under .home- prefix (home-hero__title, home-how-it-works__step, home-popular-topics)
- Optional data-driven sections (popular topics) silently hide on API error — no error UI for non-critical homepage enrichment
observability_surfaces:
- none
drill_down_paths:
- .gsd/milestones/M009/slices/S01/tasks/T01-SUMMARY.md
- .gsd/milestones/M009/slices/S01/tasks/T02-SUMMARY.md
duration: ""
verification_result: passed
completed_at: 2026-03-31T05:38:05.139Z
blocker_discovered: false
---
# S01: Homepage Hero & Value Proposition
**Homepage now shows tagline, value proposition, 3-step how-it-works grid, Start Exploring CTA, and popular topic quick-links — all above the fold.**
## What Happened
The homepage previously had an empty h1 and only a subtitle with search bar. Two tasks transformed it into a proper landing experience:
**T01** added the hero tagline "Production Knowledge, Distilled", a value proposition paragraph explaining what Chrysopedia does, a 3-column how-it-works grid (Creators Share Techniques → AI Extracts Key Moments → You Find Answers Fast) with cyan accent numbered circles, and a prominent "Start Exploring" CTA button linking to /topics. All styling uses existing CSS custom properties. Responsive stacking at 640px.
**T02** added a Popular Topics section that fetches from the existing topics API, flattens all sub_topics across categories, sorts by technique_count descending, takes the top 8, and renders them as clickable pill links navigating to /search?q={topic}&scope=topics. Section is hidden when no data or API error — graceful degradation. CSS uses the existing pill token system with bordered hover state.
Both tasks touched only Home.tsx and App.css. No new dependencies, no API changes, no backend work required.
## Verification
Frontend build passes with zero errors (46 modules transformed, 52KB CSS, 224KB JS). Verified all planned elements present in source: h1 tagline, value-prop paragraph, how-it-works grid with 3 steps, CTA link to /topics, popularTopics state/fetch/render, pill links with search scope. CSS classes confirmed present for all new components including responsive rules.
## Requirements Advanced
None.
## Requirements Validated
None.
## New Requirements Surfaced
None.
## Requirements Invalidated or Re-scoped
None.
## Deviations
T02 removed an unused TopicCategory type import that caused TS6133 — minor cleanup, no functional impact.
## Known Limitations
Popular topics section fetches the full topics list and filters client-side. Fine for current dataset size but would benefit from a dedicated API endpoint if topic count grows significantly.
## Follow-ups
None.
## Files Created/Modified
- `frontend/src/pages/Home.tsx` — Added hero tagline, value proposition, how-it-works grid, CTA button, and popular topics pill section with API fetch
- `frontend/src/App.css` — Added styles for value-prop, how-it-works grid, CTA button, popular topics pills, and responsive breakpoints

View file

@ -0,0 +1,45 @@
# S01: Homepage Hero & Value Proposition — UAT
**Milestone:** M009
**Written:** 2026-03-31T05:38:05.139Z
## UAT: Homepage Hero & Value Proposition
### Preconditions
- Chrysopedia stack running (web UI accessible at configured URL)
- At least one topic with sub-topics exists in the database (for popular topics to render)
### Test 1: Hero Content Visible
1. Navigate to the homepage (/)
2. **Expected:** Page shows heading "Production Knowledge, Distilled"
3. **Expected:** Below the heading, a paragraph explains what Chrysopedia does — mentions extracting techniques from creator tutorials
4. **Expected:** Search bar remains visible and prominent
### Test 2: How-It-Works Grid
1. On the homepage, locate the how-it-works section
2. **Expected:** Three steps displayed in a row (desktop): (1) Creators Share Techniques, (2) AI Extracts Key Moments, (3) You Find Answers Fast
3. **Expected:** Each step has a numbered circle with cyan accent color and a short description
4. Resize browser to <640px width
5. **Expected:** Steps stack vertically
### Test 3: Start Exploring CTA
1. On the homepage, locate the "Start Exploring" button
2. Click the button
3. **Expected:** Navigates to /topics page
### Test 4: Popular Topics Pills
1. Navigate back to homepage (/)
2. **Expected:** A "Popular Topics" section appears with up to 8 pill/chip links
3. **Expected:** Pills are ordered by technique count (most popular first)
4. Click any topic pill
5. **Expected:** Navigates to /search?q={topic_name}&scope=topics with relevant results
### Test 5: Popular Topics — Empty State
1. If no topics exist in the database (or API is down), navigate to homepage
2. **Expected:** Popular Topics section is completely hidden — no heading, no empty container, no error message
### Test 6: Visual Hierarchy
1. On desktop (>768px), load the homepage
2. **Expected:** Hero title and search bar are visible without scrolling
3. **Expected:** How-it-works section and CTA are below but reachable with minimal scroll
4. **Expected:** Popular topics pills visually complement but don't compete with the search bar

View file

@ -0,0 +1,16 @@
{
"schemaVersion": 1,
"taskId": "T02",
"unitId": "M009/S01/T02",
"timestamp": 1774935430315,
"passed": true,
"discoverySource": "task-plan",
"checks": [
{
"command": "cd frontend",
"exitCode": 0,
"durationMs": 6,
"verdict": "pass"
}
]
}

View file

@ -1,6 +1,10 @@
# S02: About Page # S02: About Page
**Goal:** Project credibility — users can learn who made this and why **Goal:** About page at /about explains what Chrysopedia is, how content is extracted, and who maintains it. Footer link navigates to it.
**Demo:** After this: About page at /about explains what Chrysopedia is, how content is extracted, and who maintains it. Link visible in footer. **Demo:** After this: About page at /about explains what Chrysopedia is, how content is extracted, and who maintains it. Link visible in footer.
## Tasks ## Tasks
- [x] **T01: Added /about page with three content sections (what, how, who) and an About link in the footer** — Create the About.tsx page component with three content sections (what Chrysopedia is, how content is extracted, who maintains it), add a /about route in App.tsx, add an About link in AppFooter.tsx, and add .about-* styles in App.css following existing BEM and CSS custom property patterns.
- Estimate: 30m
- Files: frontend/src/pages/About.tsx, frontend/src/App.tsx, frontend/src/components/AppFooter.tsx, frontend/src/App.css
- Verify: cd frontend && npx tsc --noEmit && npm run build

View file

@ -0,0 +1,40 @@
# S02 Research — About Page
## Summary
Static informational page at `/about` explaining what Chrysopedia is, how content is extracted, and who maintains it. No backend work. Three changes: new page component, new route in App.tsx, footer link.
## Recommendation
Follow existing page patterns exactly. This is the simplest possible slice — a single static React component with CSS, wired into the router and linked from the footer.
## Implementation Landscape
### Files to Create
- `frontend/src/pages/About.tsx` — static page component
### Files to Modify
- `frontend/src/App.tsx` — add `<Route path="/about" element={<About />} />`
- `frontend/src/components/AppFooter.tsx` — add "About" link (use react-router-dom `Link`, not `<a>`)
- `frontend/src/App.css` — add `.about-*` styles
### Existing Patterns to Follow
- **Page structure:** Wrap in a container div with page-specific class (e.g. `<div className="about">`). See Home.tsx for hero/section pattern.
- **Routing:** App.tsx uses `react-router-dom` `Routes`/`Route`. Import lazy or direct, add `<Route path="/about" element={<About />} />`.
- **Footer:** `AppFooter.tsx` currently has version info, build date, commit hash, and GitHub link. Add an "About" `<Link to="/about">` before or after the GitHub link, with the same `app-footer__sep` separator pattern.
- **CSS variables:** All colors use `var(--color-*)` custom properties defined in `:root` in App.css (77 tokens per D017). Use `--color-text-primary`, `--color-text-secondary`, `--color-text-muted`, `--color-surface-secondary`, `--color-accent`, `--color-border` etc.
- **BEM-ish naming:** Classes follow `block__element` pattern (e.g. `home-hero__title`, `nav-card__desc`).
### Content for the About Page
The roadmap specifies three content areas:
1. **What Chrysopedia is** — a knowledge base of music production techniques extracted from creator tutorials
2. **How content is extracted** — mirrors the Home "how it works" 3-step flow (creators share → AI extracts → you search), but with more detail about the pipeline (transcription, LLM extraction, review, synthesis)
3. **Who maintains it** — link to xpltdco GitHub org, note it's an XPLTD project
### Verification
- `cd frontend && npx tsc --noEmit` — zero TypeScript errors
- `cd frontend && npm run build` — production build succeeds
- Visual: navigate to `/about` in browser, confirm content renders, confirm footer link works
### Natural Task Decomposition
This is a single-task slice. Creating the component, adding the route, adding the footer link, and adding CSS are tightly coupled and trivial — splitting further adds overhead without value. One task: "Implement About page with route and footer link."

View file

@ -0,0 +1,27 @@
---
estimated_steps: 1
estimated_files: 4
skills_used: []
---
# T01: Implement About page with route and footer link
Create the About.tsx page component with three content sections (what Chrysopedia is, how content is extracted, who maintains it), add a /about route in App.tsx, add an About link in AppFooter.tsx, and add .about-* styles in App.css following existing BEM and CSS custom property patterns.
## Inputs
- ``frontend/src/App.tsx` — existing routing structure to add /about route`
- ``frontend/src/components/AppFooter.tsx` — existing footer to add About link`
- ``frontend/src/App.css` — existing CSS custom properties and BEM patterns`
- ``frontend/src/pages/Home.tsx` — reference for page component structure and hero/section patterns`
## Expected Output
- ``frontend/src/pages/About.tsx` — new About page component with three content sections`
- ``frontend/src/App.tsx` — modified with /about route and About import`
- ``frontend/src/components/AppFooter.tsx` — modified with About link using react-router-dom Link`
- ``frontend/src/App.css` — modified with .about-* styles`
## Verification
cd frontend && npx tsc --noEmit && npm run build

View file

@ -0,0 +1,81 @@
---
id: T01
parent: S02
milestone: M009
provides: []
requires: []
affects: []
key_files: ["frontend/src/pages/About.tsx", "frontend/src/App.tsx", "frontend/src/components/AppFooter.tsx", "frontend/src/App.css"]
key_decisions: ["Used CSS counter-based numbered pipeline steps rather than manual numbering for the extraction pipeline section"]
patterns_established: []
drill_down_paths: []
observability_surfaces: []
duration: ""
verification_result: "npx tsc --noEmit passed with zero errors. npm run build produced the production bundle successfully (47 modules, no warnings)."
completed_at: 2026-03-31T05:41:48.153Z
blocker_discovered: false
---
# T01: Added /about page with three content sections (what, how, who) and an About link in the footer
> Added /about page with three content sections (what, how, who) and an About link in the footer
## What Happened
---
id: T01
parent: S02
milestone: M009
key_files:
- frontend/src/pages/About.tsx
- frontend/src/App.tsx
- frontend/src/components/AppFooter.tsx
- frontend/src/App.css
key_decisions:
- Used CSS counter-based numbered pipeline steps rather than manual numbering for the extraction pipeline section
duration: ""
verification_result: passed
completed_at: 2026-03-31T05:41:48.153Z
blocker_discovered: false
---
# T01: Added /about page with three content sections (what, how, who) and an About link in the footer
**Added /about page with three content sections (what, how, who) and an About link in the footer**
## What Happened
Created About.tsx with three sections: what Chrysopedia is, a five-step pipeline breakdown explaining how content is extracted, and a maintainer section linking to the xpltd GitHub org and repo. Added the /about route in App.tsx between admin routes and the fallback. Added an About link as the last item in AppFooter.tsx using react-router-dom Link. Added .about-* styles in App.css following existing BEM and custom property patterns, including a responsive breakpoint for the hero title.
## Verification
npx tsc --noEmit passed with zero errors. npm run build produced the production bundle successfully (47 modules, no warnings).
## Verification Evidence
| # | Command | Exit Code | Verdict | Duration |
|---|---------|-----------|---------|----------|
| 1 | `cd frontend && npx tsc --noEmit` | 0 | ✅ pass | 2200ms |
| 2 | `cd frontend && npm run build` | 0 | ✅ pass | 1200ms |
## Deviations
None.
## Known Issues
None.
## Files Created/Modified
- `frontend/src/pages/About.tsx`
- `frontend/src/App.tsx`
- `frontend/src/components/AppFooter.tsx`
- `frontend/src/App.css`
## Deviations
None.
## Known Issues
None.

View file

@ -3354,3 +3354,126 @@ a.app-footer__repo:hover {
gap: 0.3rem; gap: 0.3rem;
text-decoration: none; text-decoration: none;
} }
/* ── About page ───────────────────────────────────────────────────────────── */
.about {
max-width: 44rem;
margin: 0 auto;
padding: 2rem 1.5rem 3rem;
}
.about-hero {
text-align: center;
margin-bottom: 2.5rem;
}
.about-hero__title {
font-size: 2rem;
font-weight: 700;
color: var(--color-text-primary);
margin: 0 0 0.5rem;
}
.about-hero__subtitle {
font-size: 1.05rem;
color: var(--color-text-secondary);
margin: 0;
}
.about-section {
margin-bottom: 2rem;
}
.about-section__heading {
font-size: 1.25rem;
font-weight: 600;
color: var(--color-text-primary);
margin: 0 0 0.75rem;
}
.about-section__text {
color: var(--color-text-secondary);
line-height: 1.7;
margin: 0 0 0.75rem;
}
.about-pipeline {
list-style: none;
counter-reset: pipeline;
padding: 0;
margin: 1rem 0;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.about-pipeline__step {
counter-increment: pipeline;
display: flex;
align-items: baseline;
gap: 0.75rem;
color: var(--color-text-secondary);
line-height: 1.6;
padding: 0.75rem 1rem;
background: var(--color-bg-surface);
border-radius: 0.5rem;
border: 1px solid var(--color-border);
}
.about-pipeline__step::before {
content: counter(pipeline);
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.5rem;
height: 1.5rem;
font-size: 0.75rem;
font-weight: 700;
color: var(--color-accent);
background: var(--color-accent-subtle);
border-radius: 50%;
flex-shrink: 0;
}
.about-pipeline__step strong {
color: var(--color-text-primary);
}
.about-link {
color: var(--color-accent);
text-decoration: none;
transition: color 0.15s;
}
.about-link:hover {
color: var(--color-accent-hover);
}
.about-cta {
text-align: center;
margin-top: 2.5rem;
}
.about-cta__btn {
display: inline-block;
}
/* Footer about link */
.app-footer__about {
color: var(--color-text-muted);
text-decoration: none;
transition: color 0.15s;
}
a.app-footer__about:hover,
.app-footer__about:hover {
color: var(--color-accent);
}
@media (max-width: 600px) {
.about-hero__title {
font-size: 1.5rem;
}
}

View file

@ -7,6 +7,7 @@ import CreatorDetail from "./pages/CreatorDetail";
import TopicsBrowse from "./pages/TopicsBrowse"; import TopicsBrowse from "./pages/TopicsBrowse";
import AdminReports from "./pages/AdminReports"; import AdminReports from "./pages/AdminReports";
import AdminPipeline from "./pages/AdminPipeline"; import AdminPipeline from "./pages/AdminPipeline";
import About from "./pages/About";
import AdminDropdown from "./components/AdminDropdown"; import AdminDropdown from "./components/AdminDropdown";
import AppFooter from "./components/AppFooter"; import AppFooter from "./components/AppFooter";
@ -43,6 +44,9 @@ export default function App() {
<Route path="/admin/reports" element={<AdminReports />} /> <Route path="/admin/reports" element={<AdminReports />} />
<Route path="/admin/pipeline" element={<AdminPipeline />} /> <Route path="/admin/pipeline" element={<AdminPipeline />} />
{/* Info routes */}
<Route path="/about" element={<About />} />
{/* Fallback */} {/* Fallback */}
<Route path="*" element={<Navigate to="/" replace />} /> <Route path="*" element={<Navigate to="/" replace />} />
</Routes> </Routes>

View file

@ -1,5 +1,7 @@
const REPO_URL = "https://github.com/xpltdco/chrysopedia"; const REPO_URL = "https://github.com/xpltdco/chrysopedia";
import { Link } from "react-router-dom";
export default function AppFooter() { export default function AppFooter() {
const commitUrl = const commitUrl =
__GIT_COMMIT__ !== "dev" __GIT_COMMIT__ !== "dev"
@ -37,6 +39,10 @@ export default function AppFooter() {
> >
GitHub GitHub
</a> </a>
<span className="app-footer__sep">·</span>
<Link to="/about" className="app-footer__about">
About
</Link>
</footer> </footer>
); );
} }

View file

@ -0,0 +1,94 @@
import { Link } from "react-router-dom";
export default function About() {
return (
<div className="about">
<section className="about-hero">
<h1 className="about-hero__title">About Chrysopedia</h1>
<p className="about-hero__subtitle">
A structured knowledge base for music production techniques
</p>
</section>
<section className="about-section">
<h2 className="about-section__heading">What Is Chrysopedia?</h2>
<p className="about-section__text">
Chrysopedia turns long-form music production tutorials into a
searchable, structured knowledge base. Instead of scrubbing through
hours of video looking for the one technique you need, you can search
by topic, creator, or keyword and jump straight to the insight.
</p>
<p className="about-section__text">
The name comes from <em>chrysopoeia</em> the art of transmutation.
We transmute raw video content into distilled, accessible knowledge.
</p>
</section>
<section className="about-section">
<h2 className="about-section__heading">How Content Is Extracted</h2>
<p className="about-section__text">
Videos are processed through a multi-stage pipeline that transcribes
audio, identifies key moments, classifies topics, and generates
structured technique pages all using a combination of speech
recognition and large language models.
</p>
<ol className="about-pipeline">
<li className="about-pipeline__step">
<strong>Transcription</strong> Audio is converted to timestamped
text
</li>
<li className="about-pipeline__step">
<strong>Key Moment Detection</strong> The transcript is analyzed
to find discrete techniques and insights
</li>
<li className="about-pipeline__step">
<strong>Topic Classification</strong> Each moment is tagged with
categories and sub-topics
</li>
<li className="about-pipeline__step">
<strong>Page Generation</strong> Structured technique pages are
written with context, steps, and creator attribution
</li>
<li className="about-pipeline__step">
<strong>Indexing</strong> Content is embedded for semantic search
</li>
</ol>
<p className="about-section__text">
Every technique page links back to its source video and creator,
preserving attribution throughout.
</p>
</section>
<section className="about-section">
<h2 className="about-section__heading">Who Maintains This</h2>
<p className="about-section__text">
Chrysopedia is built and maintained by{" "}
<a
href="https://github.com/xpltdco"
className="about-link"
target="_blank"
rel="noopener noreferrer"
>
xpltd
</a>
. The project is open source on{" "}
<a
href="https://github.com/xpltdco/chrysopedia"
className="about-link"
target="_blank"
rel="noopener noreferrer"
>
GitHub
</a>
.
</p>
</section>
<div className="about-cta">
<Link to="/" className="btn about-cta__btn">
Start Exploring
</Link>
</div>
</div>
);
}

View file

@ -1 +1 @@
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/public-client.ts","./src/components/AdminDropdown.tsx","./src/components/AppFooter.tsx","./src/components/CategoryIcons.tsx","./src/components/CopyLinkButton.tsx","./src/components/CreatorAvatar.tsx","./src/components/ReportIssueModal.tsx","./src/pages/AdminPipeline.tsx","./src/pages/AdminReports.tsx","./src/pages/CreatorDetail.tsx","./src/pages/CreatorsBrowse.tsx","./src/pages/Home.tsx","./src/pages/SearchResults.tsx","./src/pages/TechniquePage.tsx","./src/pages/TopicsBrowse.tsx"],"version":"5.6.3"} {"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/public-client.ts","./src/components/AdminDropdown.tsx","./src/components/AppFooter.tsx","./src/components/CategoryIcons.tsx","./src/components/CopyLinkButton.tsx","./src/components/CreatorAvatar.tsx","./src/components/ReportIssueModal.tsx","./src/pages/About.tsx","./src/pages/AdminPipeline.tsx","./src/pages/AdminReports.tsx","./src/pages/CreatorDetail.tsx","./src/pages/CreatorsBrowse.tsx","./src/pages/Home.tsx","./src/pages/SearchResults.tsx","./src/pages/TechniquePage.tsx","./src/pages/TopicsBrowse.tsx"],"version":"5.6.3"}