From 6756663a4a078167509cd7287681c94c12ff9077 Mon Sep 17 00:00:00 2001 From: adamsoffer Date: Sun, 6 Sep 2026 12:11:58 -0400 Subject: [PATCH 001/118] Rebuild the site shell on the Livepeer UI design system Peace Node's registry theme becomes the only token layer. The hand-rolled --color-* system, the Holographik grid, the hero classes, .blog-prose and seventeen bespoke keyframes go; globals.css keeps the type scale, the two theme roots, the prose classes and four live keyframes. The primer keeps its own scoped slice, deliberately unmigrated. The shell is the registry's: header (sticky, transparent at rest, glass on scroll, with opt-ins for sections that need it solid, inverted or glass from rest), footer, theme toggle, brand marks, and the shadcn primitives the pages compose. Page content is authored in-repo as typed objects matching the registry's content contracts, with the Sanity client stubbed by a static module the header expects. Share images render the registry's og card, one per segment with a twitter-image beside it. The legacy home, layout, blog and ecosystem components, the PascalCase ui/ visuals, the five use-case routes and their images are deleted; the redirects in next.config.ts serve those URLs. Discord is read live from the server's widget (lib/discord.ts) after discord.gg/livepeer was taken over, with livepeer.org/discord as the one owned URL for content. Co-Authored-By: Claude Fable 5.1 --- .gitignore | 2 + CLAUDE.md | 318 +- README.md | 57 +- app/discord/route.ts | 16 + app/globals.css | 1047 +-- app/layout.tsx | 50 +- app/not-found.tsx | 12 +- app/opengraph-image.tsx | 176 +- app/primer/twitter-image.tsx | 3 + app/sitemap.ts | 97 +- app/use-cases/ai-avatars-and-agents/page.tsx | 20 - .../composable-ai-pipelines/page.tsx | 20 - .../live-transcoding-and-streaming/page.tsx | 20 - .../real-time-video-analysis/page.tsx | 20 - .../synthetic-data-generation/page.tsx | 20 - brand-tokens.md | 251 - components.json | 24 + components/blog/BlogCategoryFilter.tsx | 33 - components/blog/BlogListingClient.tsx | 44 - components/blog/BlogPostCard.tsx | 71 - components/blog/BlogPostContent.tsx | 15 - components/blog/BlogPostHeader.tsx | 61 - components/brand-social-icons.tsx | 57 + components/brand.tsx | 222 + components/ecosystem/EcosystemDetail.tsx | 347 - .../ecosystem/EcosystemListingClient.tsx | 333 - components/ecosystem/SubmitAppForm.tsx | 171 - components/home/BuiltOnLivepeer.tsx | 750 -- components/home/Capabilities.tsx | 843 -- components/home/CommunityCTA.tsx | 247 - components/home/DeveloperCTA.tsx | 58 - components/home/Hero.tsx | 358 - components/home/LatestPosts.tsx | 116 - components/home/NetworkParticipants.tsx | 151 - components/home/NetworkSpirits.tsx | 695 -- components/home/NetworkStats.tsx | 113 - components/home/UseCases.tsx | 815 -- components/home/WhatIsLivepeer.tsx | 36 - components/home/WhyLivepeer.tsx | 302 - components/icons/LivepeerLogo.tsx | 148 - components/layout/Footer.tsx | 156 - components/layout/Header.tsx | 523 -- components/layout/ThemeToggle.tsx | 178 - components/livepeer-ui/contracts.ts | 254 + .../livepeer-ui/livepeer-org-footer.tsx | 90 + .../livepeer-ui/livepeer-org-header-nav.tsx | 506 ++ .../livepeer-ui/livepeer-org-header.tsx | 433 + components/livepeer-ui/livepeer-org-menu.tsx | 203 + .../livepeer-ui/mobile-navigation-menu.tsx | 103 + components/primer/PrimerContent.tsx | 3 +- components/static-assets.ts | 76 + components/theme-toggle.tsx | 139 + components/ui/AiVideoHero.tsx | 440 - components/ui/Badge.tsx | 27 - components/ui/Button.tsx | 61 - components/ui/Card.tsx | 17 - components/ui/Container.tsx | 15 - components/ui/CyclingWords.tsx | 61 - components/ui/FilterPill.tsx | 141 - components/ui/GenerativeCanvas.tsx | 314 - components/ui/GlowOverlay.tsx | 52 - components/ui/ImageMask.tsx | 149 - components/ui/LiveNetwork.tsx | 431 - components/ui/PageHero.tsx | 55 - components/ui/SectionHeader.tsx | 74 - components/ui/badge.tsx | 52 + components/ui/button.tsx | 56 + components/ui/card.tsx | 105 + components/ui/checkbox.tsx | 29 + components/ui/cta-arrow.tsx | 59 + components/ui/dropdown-menu.tsx | 271 + components/ui/external-arrow.tsx | 28 + components/ui/input.tsx | 20 + components/ui/label.tsx | 20 + components/ui/section-rule.tsx | 16 + components/ui/separator.tsx | 29 + components/ui/sheet.tsx | 139 + components/ui/textarea.tsx | 18 + components/ui/tooltip.tsx | 66 + content/roadmap-template.md | 95 + lib/constants.ts | 65 - lib/discord.ts | 72 + lib/fonts.ts | 12 +- lib/og.tsx | 374 + lib/site.ts | 141 + lib/useCountUp.ts | 64 - lib/utils.ts | 6 + livepeer-website-brief.md | 195 - next.config.ts | 74 +- package-lock.json | 7326 ----------------- package.json | 11 +- plans/use-cases-section.md | 118 - plans/world-models.md | 296 - pnpm-lock.yaml | 434 + public/images/blog/ai-x-open-media-forum.png | Bin 1929678 -> 0 bytes public/images/blog/ai-x-open-media-forum.svg | 36 - .../blog/builder-spotlight-frameworks.svg | 37 - .../builder-spotlight-mike-zupper-card.png | Bin 959254 -> 0 bytes .../blog/builder-spotlight-mike-zupper.png | Bin 589354 -> 0 bytes .../blog/introducing-livepeer-cascade.svg | 78 - .../introducing-the-livepeer-foundation.png | Bin 5014550 -> 0 bytes .../introducing-the-livepeer-foundation.svg | 49 - .../open-all-the-way-down.png | Bin 138810 -> 0 bytes .../open-all-the-way-down.svg | 118 - .../livepeer-incorporated-and-realtime-ai.png | Bin 4438018 -> 0 bytes .../livepeer-incorporated-and-realtime-ai.svg | 40 - .../blog/onchain-builders-streamplace.jpg | Bin 295042 -> 0 bytes .../blog/onchain-builders-streamplace.svg | 42 - .../blog/q1-2026-messari/websitepost.svg | 167 - .../blog/real-time-update-network-vision.png | Bin 4706719 -> 0 bytes .../blog/real-time-update-network-vision.svg | 51 - .../using-the-livepeer-community-treasury.svg | 55 - .../blog/why-delegation-still-matters.png | Bin 4480565 -> 0 bytes .../blog/why-delegation-still-matters.svg | 53 - sanity/lib/livepeer-org-navigation.ts | 27 + scripts/build-brand-kit.mjs | 2 +- 116 files changed, 4940 insertions(+), 18646 deletions(-) create mode 100644 app/discord/route.ts create mode 100644 app/primer/twitter-image.tsx delete mode 100644 app/use-cases/ai-avatars-and-agents/page.tsx delete mode 100644 app/use-cases/composable-ai-pipelines/page.tsx delete mode 100644 app/use-cases/live-transcoding-and-streaming/page.tsx delete mode 100644 app/use-cases/real-time-video-analysis/page.tsx delete mode 100644 app/use-cases/synthetic-data-generation/page.tsx delete mode 100644 brand-tokens.md create mode 100644 components.json delete mode 100644 components/blog/BlogCategoryFilter.tsx delete mode 100644 components/blog/BlogListingClient.tsx delete mode 100644 components/blog/BlogPostCard.tsx delete mode 100644 components/blog/BlogPostContent.tsx delete mode 100644 components/blog/BlogPostHeader.tsx create mode 100644 components/brand-social-icons.tsx create mode 100644 components/brand.tsx delete mode 100644 components/ecosystem/EcosystemDetail.tsx delete mode 100644 components/ecosystem/EcosystemListingClient.tsx delete mode 100644 components/ecosystem/SubmitAppForm.tsx delete mode 100644 components/home/BuiltOnLivepeer.tsx delete mode 100644 components/home/Capabilities.tsx delete mode 100644 components/home/CommunityCTA.tsx delete mode 100644 components/home/DeveloperCTA.tsx delete mode 100644 components/home/Hero.tsx delete mode 100644 components/home/LatestPosts.tsx delete mode 100644 components/home/NetworkParticipants.tsx delete mode 100644 components/home/NetworkSpirits.tsx delete mode 100644 components/home/NetworkStats.tsx delete mode 100644 components/home/UseCases.tsx delete mode 100644 components/home/WhatIsLivepeer.tsx delete mode 100644 components/home/WhyLivepeer.tsx delete mode 100644 components/icons/LivepeerLogo.tsx delete mode 100644 components/layout/Footer.tsx delete mode 100644 components/layout/Header.tsx delete mode 100644 components/layout/ThemeToggle.tsx create mode 100644 components/livepeer-ui/contracts.ts create mode 100644 components/livepeer-ui/livepeer-org-footer.tsx create mode 100644 components/livepeer-ui/livepeer-org-header-nav.tsx create mode 100644 components/livepeer-ui/livepeer-org-header.tsx create mode 100644 components/livepeer-ui/livepeer-org-menu.tsx create mode 100644 components/livepeer-ui/mobile-navigation-menu.tsx create mode 100644 components/static-assets.ts create mode 100644 components/theme-toggle.tsx delete mode 100644 components/ui/AiVideoHero.tsx delete mode 100644 components/ui/Badge.tsx delete mode 100644 components/ui/Button.tsx delete mode 100644 components/ui/Card.tsx delete mode 100644 components/ui/Container.tsx delete mode 100644 components/ui/CyclingWords.tsx delete mode 100644 components/ui/FilterPill.tsx delete mode 100644 components/ui/GenerativeCanvas.tsx delete mode 100644 components/ui/GlowOverlay.tsx delete mode 100644 components/ui/ImageMask.tsx delete mode 100644 components/ui/LiveNetwork.tsx delete mode 100644 components/ui/PageHero.tsx delete mode 100644 components/ui/SectionHeader.tsx create mode 100644 components/ui/badge.tsx create mode 100644 components/ui/button.tsx create mode 100644 components/ui/card.tsx create mode 100644 components/ui/checkbox.tsx create mode 100644 components/ui/cta-arrow.tsx create mode 100644 components/ui/dropdown-menu.tsx create mode 100644 components/ui/external-arrow.tsx create mode 100644 components/ui/input.tsx create mode 100644 components/ui/label.tsx create mode 100644 components/ui/section-rule.tsx create mode 100644 components/ui/separator.tsx create mode 100644 components/ui/sheet.tsx create mode 100644 components/ui/textarea.tsx create mode 100644 components/ui/tooltip.tsx create mode 100644 content/roadmap-template.md delete mode 100644 lib/constants.ts create mode 100644 lib/discord.ts create mode 100644 lib/og.tsx create mode 100644 lib/site.ts delete mode 100644 lib/useCountUp.ts create mode 100644 lib/utils.ts delete mode 100644 livepeer-website-brief.md delete mode 100644 package-lock.json delete mode 100644 plans/use-cases-section.md delete mode 100644 plans/world-models.md delete mode 100644 public/images/blog/ai-x-open-media-forum.png delete mode 100644 public/images/blog/ai-x-open-media-forum.svg delete mode 100644 public/images/blog/builder-spotlight-frameworks.svg delete mode 100644 public/images/blog/builder-spotlight-mike-zupper-card.png delete mode 100644 public/images/blog/builder-spotlight-mike-zupper.png delete mode 100644 public/images/blog/introducing-livepeer-cascade.svg delete mode 100644 public/images/blog/introducing-the-livepeer-foundation.png delete mode 100644 public/images/blog/introducing-the-livepeer-foundation.svg delete mode 100755 public/images/blog/livepeer-2-0-video-agent-platform/open-all-the-way-down.png delete mode 100755 public/images/blog/livepeer-2-0-video-agent-platform/open-all-the-way-down.svg delete mode 100644 public/images/blog/livepeer-incorporated-and-realtime-ai.png delete mode 100644 public/images/blog/livepeer-incorporated-and-realtime-ai.svg delete mode 100644 public/images/blog/onchain-builders-streamplace.jpg delete mode 100644 public/images/blog/onchain-builders-streamplace.svg delete mode 100644 public/images/blog/q1-2026-messari/websitepost.svg delete mode 100644 public/images/blog/real-time-update-network-vision.png delete mode 100644 public/images/blog/real-time-update-network-vision.svg delete mode 100644 public/images/blog/using-the-livepeer-community-treasury.svg delete mode 100644 public/images/blog/why-delegation-still-matters.png delete mode 100644 public/images/blog/why-delegation-still-matters.svg create mode 100644 sanity/lib/livepeer-org-navigation.ts diff --git a/.gitignore b/.gitignore index 219d8bd0..7073f836 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ img/ .vscode/ *.code-workspace .playwright-mcp/ +.env* +!.env.example diff --git a/CLAUDE.md b/CLAUDE.md index ba77e8b1..58ea7db1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,224 +1,122 @@ # CLAUDE.md -**Stack:** Next.js 15, React 19, TypeScript, Tailwind CSS v4, Framer Motion 11. Package manager: npm. No test framework. +**Stack:** Next.js 15 (App Router), React 19, TypeScript, Tailwind CSS v4. Package manager: **pnpm** (pinned via `packageManager` — use `corepack`). No test framework. -**Environment variables** (set in Vercel / `.env.local`): +This repo is mid-migration to the **Livepeer UI design system** (a shadcn registry). Read the "Design system" section below before touching UI — it overrides older habits. -- `THEGRAPH_API_KEY` — optional; authenticated subgraph requests for live protocol stats (falls back to hardcoded values) +## Design system — Livepeer UI (source of truth) -## Commands - -- `npm run dev` — start Next.js dev server on localhost:3000 -- `npm run build` — production build (use to verify changes compile) -- `npm run start` — start production server (requires prior build) -- `npm run lint` — run ESLint - -## Project Structure - -### `app/` - -- **Routes**: home (`/`), blog, blog/[slug], primer, foundation, brand -- **Redirects**: developers, lpt, community → `/` via `redirect()`; use-cases/world-models → `/` -- **API routes**: none currently active. -- **Use cases**: `use-cases/` has 7 sub-routes — all currently redirect to home. No `/use-cases` index page. -- **Layout**: `layout.tsx` wraps all pages with Header + Footer. Global metadata and font classes defined here. -- **SEO**: OG images generated via `next/og` at root and `/blog` levels. Primer and blog pages have per-page metadata. -- **Styling**: `globals.css` — Tailwind v4 `@theme` block, utility classes, keyframe animations. - -### `components/` - -- **`home/`** — self-contained homepage sections. Render order in `app/page.tsx`: Hero, BuiltOnLivepeer, CommunityCTA. (`NetworkParticipants.tsx` exists but is not currently rendered.) -- **`layout/`** — Header, Footer. Header has headroom behavior on `/primer` (hides on scroll down, reveals on scroll up). -- **`ui/`** — shared primitives (Button, Card, Container, SectionHeader, Badge, ImageMask, GlowOverlay, etc.). Reuse these; don't create new wrappers for the same purpose. Also contains canvas components: `GenerativeCanvas.tsx` (GLSL shader), `LiveNetwork.tsx` (Canvas 2D particle trails), `AiVideoHero.tsx` (Sobel edge detection on video texture). All canvas components follow `useEffect` + `useRef` + `requestAnimationFrame` + cleanup. -- **`blog/`** — blog listing page (`BlogListingClient`, `BlogCategoryFilter`, `BlogPostCard`) and post detail (`BlogPostHeader`, `BlogPostContent`). -- **`primer/`** — 10-chapter educational primer with chapter navigation, scroll-based background color transitions, and live protocol stats from subgraph. Primer uses a light theme override. Components: `PrimerContent`, `InflationMeter`, `MintingDiagram`. -- **`icons/`** — `LivepeerLogo.tsx` exports `LivepeerSymbol` (icon), `LivepeerWordmark` (text), `LivepeerLockup` (icon + text). - -### `lib/` - -- `constants.ts` — `NAV_ITEMS` and `EXTERNAL_LINKS` -- `fonts.ts` — Favorit Pro and Favorit Mono config via `next/font/local` -- `useCountUp.ts` — IntersectionObserver-triggered count-up animation hook -- `blog.ts` — blog content loading, markdown→HTML pipeline (gray-matter + unified/remark/rehype), reading time calculation -- `subgraph.ts` — fetches live protocol stats (inflation, participation, supply) from The Graph Livepeer subgraph with hardcoded fallbacks - -### `public/` - -- `images/` — static images and SVGs (including `primer/` and `blog/` subdirectories) -- `videos/` — MP4 files for hero backgrounds and visual effects -- `fonts/` — Favorit Pro (.woff2, .otf) and Favorit Mono (.woff2) - -### `content/` - -- `blog/` — markdown blog posts with YAML frontmatter (title, description, date, author, category, tags, image, draft). Draft posts are hidden in production. - -### Reference docs - -- `brand-tokens.md` — full brand spec (colors, typography, logo, gradients, greyscale ramp, graphic elements) -- `livepeer-website-brief.md` — project brief with messaging and positioning context - -## Conventions - -### Component patterns - -- All homepage sections and interactive components use `"use client"`. -- Scroll animations: Framer Motion `whileInView` with `viewport={{ once: true }}` and staggered children. Hero/brand pages use `initial`/`animate` (fires on mount) instead. -- Section headers: use the `SectionHeader` component with `label`, `title`, `description` props. -- Section dividers: `.divider-gradient` divs between sections. -- Imports: path alias `@/*` maps to repo root. Use `@/components/...`, `@/lib/...`. - -### Assets - -- Static files in `public/images/`, `public/videos/`, `public/fonts/`. -- Videos use `autoPlay muted loop playsInline`. -- `globals.css` includes `prefers-reduced-motion` to blanket-disable all animations. - -### Grid system — "Holographik" visual language - -The site's signature visual is a layered grid system that combines B&W video/imagery, geometric shapes, animated particle trails, and liquid glass effects. This creates an "outer space control room" aesthetic — technical, cinematic, and distinctly Livepeer. - -**Layer stack (bottom to top):** - -1. **Media layer** — B&W video or image with green tint, darkened (`ImageMask`) -2. **Tile grid** — 9-column square grid with 1px white borders, overlaid on the media -3. **Geometric shapes** — circles, crosshairs, and a starburst node positioned at grid intersections -4. **Pulse trail** — an animated dot that traverses the grid lines and shape edges via SVG `getPointAtLength()`, creating a living-network feel -5. **Liquid glass overlay** — frosted panel with subtle gradient fill, chromatic rainbow refraction, specular highlights, and corner crosshairs, snapped to grid lines -6. **Content** — text, CTAs, rendered on top of everything - -**`ImageMask`** (`components/ui/ImageMask.tsx`) — Pure CSS grid, the core brand component. Uses `container-type: inline-size` with `100cqw / cols` row heights so tiles stay square relative to their container (not the viewport). Columns are `1fr`. Used on the homepage hero and brand page hero. The homepage overlays geometric shapes positioned with `${N * TILE}vw` units (`Hero.tsx`); the brand page uses percentage-based positions inside an `aspect-ratio: 9/5` wrapper. **Do not cap tile size independently on the homepage** — the vw-based positions of every overlay element depend on tiles spanning the full viewport. To control tile size on wide screens, adjust the column count or constrain the section width. - -### Don't - -- **No `next/image`** — use raw `` tags. `ImageMask` needs direct CSS filter/absolute stacking that `next/image`'s wrapper breaks. Primer SVGs are incompatible with required width/height props. WebGL components use `