Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ Full spec + rollout checklist: **`docs/refined-design-system.md`** (read this be

See `docs/refined-design-system.md`. Pattern for new pages: keep `Head`/`getStaticProps`/schema verbatim, wrap body in `<RefinedRoot>` (or the `RefinedPage` shell below — fonts load globally, do NOT add `<RefinedFonts/>`), rebuild sections with `.ohx-*` classes, one `<h1>`, preserve GA.

**Refined pages batch (Oct 2026):** `src/components/design/RefinedPage.js` is the shell for simple content pages — `RefinedPage` (RefinedRoot + `.ohx-wrap` section that clears the 64px NavBar; `narrow` for `.ohx-narrow`, `as="article"`), `PageMasthead` (eyebrow → the ONE `<h1>` with optional `italic` accent phrase → `.ohx-lead`), `BackLink`, `Prose` (`.ohx-prose` — Fraunces h2/h3, 70ch measure, accent list markers, navy underlined links; added to `refined.js`), `LinkRow` (one primary `.ohx-btn` + soft `.ohx-link`s) and `CtaBand` (navy closing band). Migrated with it: `/404` (random sleeping image in a reserved 4:3 card; GA `404_error` kept), `/contact` (form logic, reCAPTCHA, `?type=` prefill and the mentor/judge read-first Dialog untouched; MUI fields under `refinedFormTheme` + `refinedFieldSx`; submit is a native `.ohx-btn--primary`), `/feedback` (index), `/about/why` + `/about/why/[title]` (the `whyPages[slug].Content` MUI bodies render inside `Prose`, whose `.ohx-prose .MuiTypography-*` rules restyle their `h4`→Fraunces / `body1`→17px; the 10 `src/components/content/*Content.js` files now use `component="h2"` and no inline 14px), `/about/privacy-policy` (`LAST_UPDATED` constant = the date the policy TEXT last changed — it used to print today's date), `/hack/liability-waiver`, `/hack/photo-release`, `/praise/[id]`, `/hack/[event_id]/results` + `/hack/results` (chrome only; `HackathonResults`/`HackathonFunnel` unchanged), and the four `/about/success-stories/<slug>` case studies, which are now plain `story` data objects rendered by `src/components/SuccessStories/SuccessStoryLayout.js` (owns the Head: canonical `www`, fixed `og:url` — they pointed at a non-existent `/success-stories/…` path — Article + BreadcrumbList JSON-LD via `serializeJsonLd`, CDN `og:image`s). **Still not refined** (next batches): the SEO pillar pages (`/coding-for-nonprofits`, `/hackathon-for-social-good`, `/hackathon-judge-opportunities`, `/hackathon-judging-criteria`, `/volunteer/professional-development-volunteering`, `/about/hackers/software-engineering-career-path`, `/about/locations/asu-tempe-arizona`), the tutorial pages (`/about/judges/overview`, `/about/mentors/overview`, `/judge/overview`), `/about/hearts` + `/community-champions` (700-line components), `/blog/[blog_id]`, `/cert`, `/hack/[event_id]/{media,agenda}`, `/store/*`, `/signup2`, `/unsubscribe`; intentionally bespoke: `/12-years-of-social-good`, `/about/style-guide`, print pages (`/hack/flier`, `/hack/[event_id]/print-timeline`), the planning board (own theme), redirect stubs.
**Refined pages batch (Oct 2026):** `src/components/design/RefinedPage.js` is the shell for simple content pages — `RefinedPage` (RefinedRoot + `.ohx-wrap` section that clears the 64px NavBar; `narrow` for `.ohx-narrow`, `as="article"`), `PageMasthead` (eyebrow → the ONE `<h1>` with optional `italic` accent phrase → `.ohx-lead`), `BackLink`, `Prose` (`.ohx-prose` — Fraunces h2/h3, 70ch measure, accent list markers, navy underlined links; added to `refined.js`), `LinkRow` (one primary `.ohx-btn` + soft `.ohx-link`s) and `CtaBand` (navy closing band). Migrated with it: `/404` (random sleeping image in a reserved 4:3 card; GA `404_error` kept), `/contact` (form logic, reCAPTCHA, `?type=` prefill and the mentor/judge read-first Dialog untouched; MUI fields under `refinedFormTheme` + `refinedFieldSx`; submit is a native `.ohx-btn--primary`), `/feedback` (index), `/about/why` + `/about/why/[title]` (the `whyPages[slug].Content` MUI bodies render inside `Prose`, whose `.ohx-prose .MuiTypography-*` rules restyle their `h4`→Fraunces / `body1`→17px; the 10 `src/components/content/*Content.js` files now use `component="h2"` and no inline 14px), `/about/privacy-policy` (`LAST_UPDATED` constant = the date the policy TEXT last changed — it used to print today's date), `/hack/liability-waiver`, `/hack/photo-release`, `/praise/[id]`, `/hack/[event_id]/results` + `/hack/results` (chrome only; `HackathonResults`/`HackathonFunnel` unchanged), and the four `/about/success-stories/<slug>` case studies, which are now plain `story` data objects rendered by `src/components/SuccessStories/SuccessStoryLayout.js` (owns the Head: canonical `www`, fixed `og:url` — they pointed at a non-existent `/success-stories/…` path — Article + BreadcrumbList JSON-LD via `serializeJsonLd`, CDN `og:image`s). **Still not refined**: `/signup2`, `/unsubscribe`, `/census` (renders the shared `HackathonHeader` outside a `RefinedRoot`) — everything else from the old list shipped in batch 3 (see "Refined batch 3" below); intentionally bespoke: `/12-years-of-social-good`, `/about/style-guide`, print pages (`/hack/flier`, `/hack/[event_id]/print-timeline`), the planning board (own theme), redirect stubs.

## Refined batch 3 (Oct 2026) — pillar, tutorial, hearts, blog, cert, media/agenda, store

- **SEO pillar pages** (`/coding-for-nonprofits`, `/hackathon-for-social-good`, `/hackathon-judging-criteria`, `/hackathon-judge-opportunities`, `/volunteer/professional-development-volunteering`, `/about/hackers/software-engineering-career-path`, `/about/locations/asu-tempe-arizona`) follow the `recruit-tech-talent` pattern; `getStaticProps` output is unchanged (byte-identical on the first three). `FAQ_ITEMS` / rubric data are module-scope and feed BOTH the `<details>` accordions and the FAQPage JSON-LD — edit the array, not the schema. Fixed on the way: PDV + career-path canonicals pointed at `opportunityhack.org`; PDV's dead `/hackathon` CTA → `/hack`; career-path had no GA/OG/JSON-LD before. `/about/locations/asu-tempe-arizona` is a venue/logistics guide (no `useHackathonEvents`); its section ids `venue/transportation/parking/hotels/local-area` are share-link targets; Hayden Library photos live on `tours.asu.edu` (not in `remotePatterns`) so they stay raw `<img>` with dimensions.
- **Video tutorial routes** (`/about/judges/overview`, `/about/mentors/overview`, `/judge/overview`) render ONE module-scope `VideoGuidePage` template (named export from `src/pages/about/judges/overview.js`) from a per-route config (video, highlights, CTA band, resources, optional quick reference); per-route `getStaticProps`/OG/VideoObject verbatim. **GA gotcha fixed here and on `/about/judges`, `/about/hearts`:** `trackEvent` takes `({action, params})` — the positional `trackEvent("name", label)` form sent `undefined` as the event name. Stale VideoObject durations / `playerType: "HTML5 Flash"` were left as-is.
- **`/about/hearts` + `/community-champions`** are SSR now (page shells import statically; only the Instagram embed is `dynamic ssr:false`). Tiers + categories come ONLY from `src/lib/heartTiers.js`; `RewardStructure.js` `REWARD_LEVELS` is the single copy of the scoring criteria. Leaderboard `userId` is the Firestore doc id (`/profile/<userId>`); rank = position in the unfiltered `limit=50` payload.
- **`/blog/[blog_id]`:** `SingleNews.js` is the article body and renders ONLY inside `SingleBlogPost`'s `RefinedPage` (`.ohx-*` safe); tags render once in `SingleBlogPost` (`tags[]` wins, hashtag/channel extraction fallback); authored markdown headings are demoted one level so the title stays the only `<h1>`. **`/cert` + `/cert/[cert_id]`:** ISR/OG contract untouched; `CertInfoIndex` now gates its fetch on `cert_id` (it fetched `/api/certificates/undefined` during fallback) and has a not-found state; dead `Certificate.js`/`styles.js` were deleted.
- **`/hack/[event_id]/media` + `/agenda`** use `Shell` + `TeamBreadcrumbs` and `fetchForStaticProps` (media is `fallback:"blocking"` — it used to prerender every event at build time; agenda stays `fallback:true` per the getStaticPaths contract test, with an `isFallback` state). Agenda formats every time in the event timezone via `Intl` and keeps `now` null until mount — don't reintroduce date-fns `format` in host tz or render the clock during SSR.
- **Store** (`/store`, `/cart`, `/success`, `/products/[id]`) is fully refined. `CartItemList` calls `onRemoveItem(id, selectedVariations)` — the old `cartKey` lookup matched nothing, so variation items couldn't be removed. `products/[id]` has no `getStaticProps` (Product JSON-LD/OG are client-only, pre-existing); its "Added to cart" confirmation is an inline `role="status"` strip whose timeout effect sits ABOVE the early returns. **Catalog images `/images/store/*.png` never existed in the repo** (404 in prod) — thumbs fall back to a Fraunces initial via `onError`; add the PNGs or fix `store-products.json`. Store JSON-LD goes through `serializeJsonLd`.

The homepage and projects page were reimagined away from the old busy/multi-gradient look into a calm "civic editorial" system. Shared tokens + utility classes live in `src/components/design/refined.js`:

Expand Down
10 changes: 7 additions & 3 deletions docs/refined-design-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ visually, disable cache via CDP (`Network.setCacheDisabled` +
- [x] `/` (homepage)
- [x] `/projects`
- [x] Oct 2026 batch via `RefinedPage`: `/404`, `/contact`, `/feedback`, `/about/why` (+ `[title]`), `/about/privacy-policy`, `/hack/liability-waiver`, `/hack/photo-release`, `/praise/[id]`, `/hack/[event_id]/results`, `/hack/results`, the four `/about/success-stories/<slug>` case studies (`SuccessStoryLayout`)
- [x] Batch 3 (Oct 2026) — SEO pillar pages `/coding-for-nonprofits`, `/hackathon-for-social-good`, `/hackathon-judging-criteria`, `/hackathon-judge-opportunities`, `/volunteer/professional-development-volunteering`, `/about/hackers/software-engineering-career-path`, `/about/locations/asu-tempe-arizona` (recruit-tech-talent pattern: hero + Stat row, alternating bands, data-array cards, native `<details>` FAQ single-sourced into FAQPage JSON-LD, navy band, primary+ghost+link closers; `getStaticProps` output unchanged)
- [x] Batch 3 — video tutorials `/about/judges/overview`, `/about/mentors/overview`, `/judge/overview` share one `VideoGuidePage` template (masthead + 16:9 `.ohx-card` video + ghost Share w/ inline status, `--surface-2` highlight band, navy CTA band, resource tiles; hover copy-link section anchors kept)
- [x] Batch 3 — `/about/hearts` + `/community-champions` (both SSR now; hearts = editorial hero + tier ladder from `heartTiers.js` + `HEART_CATEGORIES` cards + `<details>` scoring guide + `CtaBand`; champions = framed hero photo, native search + toggle-tag tier filter, hairline `<table>`/grid with tier-dot tags — no avatar wall, no tier backgrounds — plus skeleton/error/empty states)
- [x] Batch 3 — `/blog/[blog_id]` (`RefinedPage as="article"`, `PageMasthead` h1, `Prose` markdown w/ demoted headings, one tag strip, related-posts card, `CtaBand`) and `/cert` + `/cert/[cert_id]` (masthead, framed 1:1 certificate, `Stat` tiles, one primary Download + soft share links)
- [x] Batch 3 — `/hack/[event_id]/media` + `/agenda` (`Shell` + `TeamBreadcrumbs`; media: carousel in a hairline card w/ navy controls + reserved 16:9, `.ohx-card--hover` coverage tiles, reserved Instagram embeds; agenda: shared `HackathonHeader` masthead + day-grouped hairline timeline in the event tz, sticky info/QR aside, print-only QR strip)
- [x] Batch 3 — `/store`, `/store/cart`, `/store/success`, `/store/products/[id]` (masthead + `--surface-2` browse band w/ native search + `aria-pressed` category tags, `ProductCard` grid w/ reserved 4:3 image box + `onError` initial fallback; cart = hairline rows + sticky order-summary card w/ ONE primary Checkout; product page = two-column masthead, native `<select>` variations, − / + stepper, inline `role="status"` confirmation; `FloatingCartButton` navy w/ var-fallbacks)
- [x] Global NavBar
- [x] `/nonprofits` — `NonProfitList` rewritten; new calm card
`NonProfitListTileRefined` (the original `NonProfitListTile` is still used
Expand Down Expand Up @@ -304,9 +310,7 @@ visually, disable cache via CDP (`Network.setCacheDisabled` +
(explicit-save bar; `saveDisabled` on validation errors) and the Hackers'
Choice results table is the 4th Judging subtab — both plain MUI (admin surfaces
aren't refined).
- [ ] (later) remaining pages — application forms, `/about/why`, `/about/hearts`,
`/contact`, etc. Deeper passes wanted on the own `/profile` editor (logged-in)
and the `/hack/[event_id]` event page (see the dedicated plan below).
- [ ] (later) `/signup2`, `/unsubscribe`, `/census`; `src/components/Profile/Sections/HeartsExplainer.jsx` (pink MUI Paper) is the last loud piece on the hearts surfaces.

## `/hack/[event_id]` — masthead-led refined pass (done, phase 1)
The event page (`src/pages/hack/[event_id].js`) now:
Expand Down
Loading
Loading