Overhaul cookbook-v2: homepage, GL inspector, navigation, docs#453
Conversation
Homepage: - Add MotionBlur + Rotate + HelloGL animated demo with live code display - Show gl-react tagline and logo - Canvas background matches code panel (#111827) GL Inspector: - Full port from old cookbook (1500 lines Flow/JS → TypeScript/hooks) - Bottom panel with resize handle (drag to resize, drag down to close) - Floating toggle button + canvas hover inspect button - Icon toolbar (capture, animate, minimize, physics, lose/restore GL context) - SVG connection lines with math-based bezier animation (no DOM getPointAtLength) - Physics-based auto-layout enabled by default Navigation: - Remove sidebar, use full-width layout - Add breadcrumb component with example select dropdown - Add prev/next arrows on example detail pages - Add react-router v7 future flags Dependencies: - Update vite 6.4.1, typescript 5.9.3, @vitejs/plugin-react 4.7.0 - Update heroicons, lodash, prismjs, postcss, autoprefixer, etc. - Add buffer shim for gl-texture2d browser compat Examples: - Add educational inline comments to all 44 examples - Document GLSL concepts, uniforms, composition, backbuffering, etc. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR modernizes cookbook-v2’s UI/UX and tooling by introducing a new animated homepage hero, adding a full GL Inspector panel, and reshaping navigation (breadcrumbs + prev/next) while also updating key frontend dependencies.
Changes:
- Adds a new animated homepage demo with live code rendering.
- Introduces a resizable bottom-panel GL Inspector and simplifies the overall app layout.
- Reworks examples navigation with breadcrumbs and prev/next controls; updates various examples with clarifying inline comments.
Reviewed changes
Copilot reviewed 39 out of 40 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Updates locked dependency versions to match the cookbook-v2 overhaul. |
| packages/cookbook-v2/vite.config.ts | Adds a Vite alias for a browser buffer shim. |
| packages/cookbook-v2/src/shims/buffer.ts | Adds a minimal buffer module shim for browser builds. |
| packages/cookbook-v2/src/pages/HomePage.tsx | Replaces homepage with animated shader hero + live code display. |
| packages/cookbook-v2/src/pages/ExamplesPage.tsx | Replaces title header with breadcrumb-based navigation. |
| packages/cookbook-v2/src/pages/ExampleDetailPage.tsx | Adds breadcrumb + fixed prev/next arrow navigation; adjusts page layout. |
| packages/cookbook-v2/src/pages/ApiPage.tsx | Updates API page copy to use “gl-react” naming. |
| packages/cookbook-v2/src/main.tsx | Enables React Router future flags on BrowserRouter. |
| packages/cookbook-v2/src/examples/video.tsx | Updates/clarifies comments around video helpers. |
| packages/cookbook-v2/src/examples/transitions.tsx | Removes outdated comments above transition shaders. |
| packages/cookbook-v2/src/examples/saturation.tsx | Adds an explanatory inline comment for luminance weights. |
| packages/cookbook-v2/src/examples/pixeleditor.tsx | Removes a stale preload comment. |
| packages/cookbook-v2/src/examples/paint.tsx | Adds an explanatory comment for discard usage. |
| packages/cookbook-v2/src/examples/ibex.tsx | Removes header comment and trims inline comments in data/init logic. |
| packages/cookbook-v2/src/examples/hellogl.tsx | Adds educational comments about shaders/surface/node. |
| packages/cookbook-v2/src/examples/helloblue.tsx | Adds educational comments about uniforms. |
| packages/cookbook-v2/src/examples/heart.tsx | Adds a brief comment describing a spring hook. |
| packages/cookbook-v2/src/examples/golrotscu.tsx | Adds a comment about memoization intent. |
| packages/cookbook-v2/src/examples/golglider.tsx | Refines comments + clarifies backbuffer initialization. |
| packages/cookbook-v2/src/examples/gol.tsx | Adds comments explaining neighbor counting and refresh behavior. |
| packages/cookbook-v2/src/examples/glsledit.tsx | Adds comments explaining dynamic shader compilation and error suppression. |
| packages/cookbook-v2/src/examples/diamondhello.tsx | Adds comment about nested Node composition. |
| packages/cookbook-v2/src/examples/diamondcrop.tsx | Adds comments explaining diamond distance + child uniform mapping. |
| packages/cookbook-v2/src/examples/demotunnel.tsx | Adds comment explaining superellipse distance usage. |
| packages/cookbook-v2/src/examples/demodesertcrt.tsx | Moves/adapts CRT shader attribution into a clearer comment. |
| packages/cookbook-v2/src/examples/colorscale.tsx | Adds comment explaining grayscale-to-gradient LUT mapping. |
| packages/cookbook-v2/src/examples/blurxydownscale.tsx | Adds comment explaining downscale blur performance tradeoff. |
| packages/cookbook-v2/src/examples/blurxy.tsx | Adds comments explaining connectSize and separable blur passes. |
| packages/cookbook-v2/src/examples/blurvideo.tsx | Removes an outdated comment about ref stability. |
| packages/cookbook-v2/src/examples/blurmulti.tsx | Adds comment describing multi-pass blur intent. |
| packages/cookbook-v2/src/examples/blurmap.tsx | Adds comments clarifying direction cycling and map-scaled blur. |
| packages/cookbook-v2/src/examples/blurimgtitle.tsx | Adds comments describing average-color pass and canvas text texture. |
| packages/cookbook-v2/src/examples/blurfeedback.tsx | Adds comments clarifying tick usage and backbuffer feedback behavior. |
| packages/cookbook-v2/src/examples/behindasteroids.tsx | Removes large header comment and consolidates shader uniform declarations. |
| packages/cookbook-v2/src/examples/animated.tsx | Refines/adjusts comments and clarifies UV conversion. |
| packages/cookbook-v2/src/components/Layout.tsx | Replaces sidebar layout with a full-width layout + bottom GL Inspector panel integration. |
| packages/cookbook-v2/src/components/GLInspector.tsx | Adds the ported GL Inspector implementation (TypeScript/hooks) and visitor integration. |
| packages/cookbook-v2/src/components/GLInspector.css | Adds styles for the GL Inspector UI (boxes, connections, preview, etc.). |
| packages/cookbook-v2/src/components/Breadcrumb.tsx | Adds breadcrumb nav + grouped example selector dropdown. |
| packages/cookbook-v2/package.json | Updates cookbook-v2 dependencies/devDependencies (vite, TS, eslint tooling, etc.). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return ( | ||
| <div className="space-y-8"> | ||
| <div> | ||
| <h1 className="text-3xl font-bold text-gray-900">Examples</h1> | ||
| </div> | ||
| <Breadcrumb /> | ||
|
|
There was a problem hiding this comment.
ExamplesPage no longer renders an <h1> for the page title (it used to be "Examples"). This is likely to break existing Playwright expectations (e2e/examples.spec.ts asserts on h1) and is also a regression for document semantics/accessibility. Consider keeping an <h1> (it can be visually subtle) alongside the breadcrumb.
| const html = Prism.highlight(code, Prism.languages.jsx, "jsx"); | ||
|
|
||
| return ( | ||
| <pre className="bg-gray-900 rounded-lg p-4 text-sm font-mono leading-relaxed overflow-hidden h-[200px] flex items-center"> | ||
| <code dangerouslySetInnerHTML={{ __html: html }} /> |
There was a problem hiding this comment.
Prism.highlight() runs on every render of LiveCode, and HeroDemo re-renders every animation frame via useTimeLoop(). Doing syntax highlighting at ~60fps is expensive and can hurt animation smoothness. Consider memoizing/throttling the highlighted HTML (e.g., update only when the displayed rounded values change, or at a lower cadence).
| <div className="space-y-4 relative"> | ||
| <Breadcrumb exampleId={example.id} /> | ||
|
|
||
| {/* Title */} | ||
| <div> | ||
| <h1 className="text-2xl font-bold text-gray-900">{example.title}</h1> | ||
| <p className="mt-1 text-gray-600">{example.description}</p> | ||
| </div> | ||
| <p className="text-gray-600">{example.description}</p> | ||
|
|
There was a problem hiding this comment.
ExampleDetailPage no longer renders an <h1> for the example title (it’s now only in the breadcrumb/select). This is a semantic/accessibility regression and also appears to break the existing Playwright check that expects an h1 to be visible on example pages (e2e/examples.spec.ts). Consider restoring an <h1> (even if visually smaller) for the example title.
| {prev && ( | ||
| <button | ||
| onClick={() => navigate(`/examples/${prev.id}`)} | ||
| className="fixed left-2 top-1/2 -translate-y-1/2 z-30 p-2 rounded-full bg-white/80 hover:bg-white text-gray-400 hover:text-gray-700 shadow border border-gray-200 transition-colors hidden xl:block" | ||
| title={prev.title} |
There was a problem hiding this comment.
The new prev/next buttons use navigate() which keeps ExampleDetailPage mounted. Since controlValues is initialized only once with useState(() => getDefaults(...)), switching examples this way can keep the previous example’s controls and pass wrong props to the next example. Consider resetting controlValues in an effect keyed on id/example.id (and/or example.controls).
| const dy = anchorPos[1] - hookPos[1]; | ||
| const magn = Math.sqrt(dx * dx + dy * dy); | ||
| const dist = magn + 0.1; | ||
| const dir: [number, number] = [dx / magn, dy / magn]; | ||
| const m = 8 / (dist * dist); |
There was a problem hiding this comment.
spring() divides by magn to compute dir, but magn can be 0 when anchor/hook positions overlap. That will produce Infinity/NaN forces and can poison boxPos/boxVel. Add a guard for magn === 0 before computing dir.
| box1pos[1] + | ||
| box1size[1] / 2 - | ||
| (box2pos[1] + box2size[1]); | ||
| const magn = Math.sqrt(dx * dx + dy * dy); |
There was a problem hiding this comment.
Similarly, the box repulsion logic computes dir as [dx / magn, dy / magn] without guarding magn === 0. If two boxes overlap exactly (e.g., initial placement), this can introduce NaN positions. Add a zero-distance guard before dividing.
| const magn = Math.sqrt(dx * dx + dy * dy); | |
| const magn = Math.sqrt(dx * dx + dy * dy); | |
| if (magn === 0) { | |
| continue; | |
| } |
| className={`p-1.5 rounded transition-colors ${animated ? 'bg-gray-400/30 text-gray-900' : 'text-gray-400 hover:text-gray-700'}`} | ||
| title={animated ? "Pause animation" : "Resume animation"} | ||
| > | ||
| {animated ? <PlayIcon className="h-4 w-4" /> : <PauseIcon className="h-4 w-4" />} |
There was a problem hiding this comment.
The play/pause icon logic appears inverted: when animated is true the tooltip says "Pause animation" but the component renders PlayIcon (and vice-versa). Swap the icons so the rendered glyph matches the state/action.
| {animated ? <PlayIcon className="h-4 w-4" /> : <PauseIcon className="h-4 w-4" />} | |
| {animated ? <PauseIcon className="h-4 w-4" /> : <PlayIcon className="h-4 w-4" />} |
| setConsoleLogsOn((prev) => { | ||
| const next = !prev; | ||
| Visitors.remove(inspectorVisitorLogger); | ||
| if (next) Visitors.add(inspectorVisitorLogger); | ||
| return next; |
There was a problem hiding this comment.
When toggling console logs, inspectorVisitorLogger is added to Visitors, but there’s no unmount cleanup to remove it if the inspector panel is closed while logging is enabled. This can leave a global visitor attached and keep logging unexpectedly. Add a cleanup that always removes inspectorVisitorLogger on unmount.
| import { Node, Shaders, GLSL, Uniform, LinearCopy } from "gl-react"; | ||
| import Prism from "prismjs"; | ||
| import "prismjs/components/prism-jsx"; | ||
| import { useTimeLoop } from "../hooks/useTimeLoop"; |
There was a problem hiding this comment.
The homepage uses Prism to generate token markup, but no Prism theme CSS is imported on this route (the theme is only imported in ExampleDetailPage). Without a theme, the live code display will likely render unstyled tokens. Consider importing a Prism theme globally (or in HomePage) so syntax highlighting is consistently styled.
Summary
Test plan
yarn build— all packages compileyarn test— 40/40 tests passyarn vite build(cookbook-v2) — builds successfully🤖 Generated with Claude Code