Skip to content

Add cookbook-expo-camera — SDK 54 / React 19 / RN 0.81#484

Merged
gre merged 1 commit into
masterfrom
feat/cookbook-expo-camera
May 1, 2026
Merged

Add cookbook-expo-camera — SDK 54 / React 19 / RN 0.81#484
gre merged 1 commit into
masterfrom
feat/cookbook-expo-camera

Conversation

@gre
Copy link
Copy Markdown
Owner

@gre gre commented Apr 29, 2026

Summary

Adds a new workspace package packages/cookbook-expo-camera/ — a real-time camera + GL effects demo, modern equivalent of the legacy examples/expo-gl-react-camera-effects/ (SDK 45 / React 17). Targets Expo SDK 54 / expo-gl 16 / expo-camera 17 / React 19 / RN 0.81.

Verified working in Expo Go on Android: live camera frames running through Blur → Contrast → Saturation → Brightness → Negative → HueRotate → Sepia → FlyEye → ColorMatrix.

What's in the box

  • App.tsx, GLCamera.tsx, Field.tsx, effects/* ported from the old example.
  • metro.config.js configured for monorepo (watchFolders, singleton resolution for react/react-dom/react-native, stubs for Node-only deps unconditionally imported by gl-react: ndarray, typedarray-pool, etc.).
  • .yarnrc.yml with nodeLinker: node-modules — Metro is incompatible with Yarn PnP, mirrors the working packages/cookbook-expo/.

Workspace bumps

All workspace packages and the cookbook now consume webgltexture-loader@2.1.0 (was 2.0.0 / various alphas during bring-up):

  • gl-react, tests: webgltexture-loader, webgltexture-loader-ndarray2.1.0
  • gl-react-dom: webgltexture-loader-dom2.1.0
  • gl-react-expo, gl-react-native: webgltexture-loader-expo2.1.0
  • cookbook-expo-camera: webgltexture-loader{,-expo,-expo-camera}2.1.0

The SDK 54 fixes (CameraView duck-type + requireNativeModule bypass of expo-gl's broken GLViewRef.createCameraTextureAsync + new WebGLTexture() then .id = assignment) all landed in webgltexture-loader-expo-camera@2.1.0 upstream — no inline workaround left in the cookbook.

Test plan

  • yarn install at monorepo root
  • cd packages/cookbook-expo-camera && yarn start, scan QR with Expo Go on Android
  • Camera renders, all 8 sliders produce visible effects on the live feed
  • iOS validation (Expo Go + simulator)

🤖 Generated with Claude Code

@gre
Copy link
Copy Markdown
Owner Author

gre commented May 1, 2026

@copilot review

Copy link
Copy Markdown
Contributor

Copilot AI commented May 1, 2026

@copilot review

Here's a summary of the review:

CI: Previous failures on commits 26e0307/ff38b5a were due to webgltexture-loader@2.1.0 not being fully published yet. The current HEAD passes CI tests ✅ and cookbook-v2 ✅ (iOS build in progress).

Fixes applied (commit 062a954): Applied prettier formatting to 4 files — App.tsx, Field.tsx, effects/Blur.tsx, metro.config.js (trailing commas, line lengths).

Review findings (no blockers for WIP):

  • GLCamera.tsx: The requestAnimationFrame + forceUpdate loop is the correct pattern for live camera texture updates in gl-react; useRef<any> could be typed as React.ElementRef<typeof CameraView> but any is consistent with the stub types in gl-react.d.ts
  • GLCamera.tsx: Camera texture size hint (CAMERA_W=720, CAMERA_H=1280, 9:16) doesn't match the Surface display ratio (3:4) — the camera feed will be stretched slightly; easy to fix post-WIP by changing the Surface style to match
  • metro.config.js: The ./index special-case redirect is extra vs cookbook-expo's config — needed for this package's Expo root resolution, and there's a pending edge case with monorepoRoot + "/." path matching
  • package.json: react-dom is included consistent with cookbook-expo (needed for web platform / Metro singleton deduplication)

CodeQL scan: 0 security alerts.

Copilot finished work on behalf of gre May 1, 2026 09:16
@gre gre changed the title Add cookbook-expo-camera (WIP) — SDK 54 / React 19 / RN 0.81 Add cookbook-expo-camera — SDK 54 / React 19 / RN 0.81 May 1, 2026
@gre gre marked this pull request as ready for review May 1, 2026 11:17
Copilot AI review requested due to automatic review settings May 1, 2026 11:17
New workspace at packages/cookbook-expo-camera/ — a real-time camera +
GL effects demo, modern equivalent of examples/expo-gl-react-camera-effects/
(legacy SDK 45 / React 17). Targets Expo SDK 54, expo-gl 16, expo-camera 17,
React 19, RN 0.81.

Verified on Android Expo Go: live camera frames running through Blur →
Contrast/Saturation/Brightness → Negative → HueRotate → Sepia → FlyEye →
ColorMatrix.

Bumps webgltexture-loader{,-dom,-expo,-expo-camera,-ndarray} from 2.0.0 to
2.1.2 across the gl-react workspaces. 2.1.x adds the SDK 54 camera fixes
upstream (CameraView duck-type, requireNativeModule bypass of expo-gl's
broken GLViewRef.createCameraTextureAsync, post-hoc WebGLTexture.id
assignment) so no inline workaround is needed in the cookbook.

webgltexture-loader-ndarray@2.1.x dropped the second `texture` arg from
drawNDArrayTexture — the function now operates on the currently-bound
texture. Adapted packages/tests/utils.js accordingly.

Adds installConfig.hoistingLimits=workspaces on cookbook-expo (SDK 53)
and cookbook-expo-camera (SDK 54) so each keeps its own metro/expo-cli
node_modules. SDK 53 needs metro-cache@0.82.x's `./src/*` exports; SDK
54 needs 0.83.x. Without this, yarn hoists one version to the project
root and breaks the other cookbook's bundle.
@gre gre force-pushed the feat/cookbook-expo-camera branch from b0d52a5 to e1e8cbe Compare May 1, 2026 11:18
@gre gre merged commit efff9dd into master May 1, 2026
2 of 3 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Expo SDK 54 “cookbook” demo app package (packages/cookbook-expo-camera/) showcasing real-time camera frames processed through a chain of gl-react shader effects, while updating workspace dependencies to use webgltexture-loader@2.1.2 and aligning tests with the updated ndarray loader API.

Changes:

  • Added packages/cookbook-expo-camera/ (Expo app + GL camera component, effect components, Metro monorepo config, Expo config, and assets).
  • Bumped workspace packages to webgltexture-loader* 2.1.2 and updated tests for the webgltexture-loader-ndarray@2.1.x API.
  • Added installConfig.hoistingLimits=workspaces to the existing Expo cookbook package to better isolate installs.

Reviewed changes

Copilot reviewed 25 out of 33 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
yarn.lock Locks new Expo SDK 54 / RN 0.81 / React 19 dependencies and updates webgltexture-loader* to 2.1.2.
packages/tests/utils.js Updates ndarray texture creation to match the webgltexture-loader-ndarray@2.1.x draw helper signature.
packages/tests/package.json Bumps webgltexture-loader and webgltexture-loader-ndarray to 2.1.2 for tests.
packages/gl-react/package.json Bumps webgltexture-loader and webgltexture-loader-ndarray to 2.1.2.
packages/gl-react-native/package.json Bumps webgltexture-loader-expo to 2.1.2.
packages/gl-react-expo/package.json Bumps webgltexture-loader-expo to 2.1.2.
packages/gl-react-dom/package.json Bumps webgltexture-loader-dom to 2.1.2.
packages/cookbook-expo/package.json Adds installConfig.hoistingLimits=workspaces for Metro-friendly dependency isolation.
packages/cookbook-expo-camera/package.json New Expo app workspace package targeting Expo SDK 54 / React 19 / RN 0.81 with relevant GL + camera deps.
packages/cookbook-expo-camera/tsconfig.json New strict TS config extending Expo defaults.
packages/cookbook-expo-camera/metro.config.js Custom Metro config for monorepo watchFolders, singleton React resolution, and module stubbing.
packages/cookbook-expo-camera/index.ts Expo entrypoint registering the root component.
packages/cookbook-expo-camera/App.tsx Main UI: permission gate, GL surface, camera toggle, and effect controls.
packages/cookbook-expo-camera/GLCamera.tsx GL node that sources frames from expo-camera and applies a Y-flip shader.
packages/cookbook-expo-camera/Field.tsx Slider row component for controlling effect parameters.
packages/cookbook-expo-camera/effects/index.tsx Effect pipeline composition (Blur → CSB → Negative → HueRotate → FlyEye → ColorMatrix).
packages/cookbook-expo-camera/effects/Blur.tsx Multi-pass blur implementation using connectSize.
packages/cookbook-expo-camera/effects/ContrastSaturationBrightness.tsx CSB shader node.
packages/cookbook-expo-camera/effects/Negative.tsx Negative/invert shader node.
packages/cookbook-expo-camera/effects/HueRotate.tsx Hue rotation shader node.
packages/cookbook-expo-camera/effects/FlyEye.tsx Fly-eye distortion shader node.
packages/cookbook-expo-camera/effects/ColorMatrix.tsx Color matrix shader node (used for sepia mix).
packages/cookbook-expo-camera/app.json Expo app configuration (camera permissions, icons, adaptive icon config).
packages/cookbook-expo-camera/gl-react.d.ts Local module declarations to satisfy TS for gl-react/gl-react-expo usage in this demo.
packages/cookbook-expo-camera/empty-module.js Empty stub module used by Metro resolver.
packages/cookbook-expo-camera/.yarnrc.yml Forces nodeLinker: node-modules for Metro compatibility when running yarn in this workspace.
packages/cookbook-expo-camera/.gitignore Ignores Expo/Metro/native build outputs for this new app package.
packages/cookbook-expo-camera/assets/splash-icon.png New splash asset.
packages/cookbook-expo-camera/assets/favicon.png New favicon asset.
packages/cookbook-expo-camera/assets/android-icon-background.png New adaptive icon background asset.
packages/cookbook-expo-camera/assets/android-icon-monochrome.png New adaptive icon monochrome asset.
packages/cookbook-expo-camera/assets/android-icon-foreground.png New adaptive icon foreground asset.
packages/cookbook-expo-camera/assets/icon.png New app icon asset.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +21 to +30
const percentagePrint = (v: number) => (v * 100).toFixed(0) + "%";
const radiantPrint = (r: number) => ((180 * r) / Math.PI).toFixed(0) + "°";

// prettier-ignore
const fields = [
{ id: "blur", name: "Blur", min: 0, max: 6, step: 0.1, prettyPrint: (blur: number) => blur.toFixed(1) },
{ id: "contrast", name: "Contrast", min: 0, max: 4, step: 0.1, prettyPrint: percentagePrint },
{ id: "brightness", name: "Brightness", min: 0, max: 4, step: 0.1, prettyPrint: percentagePrint },
{ id: "saturation", name: "Saturation", min: 0, max: 10, step: 0.1, prettyPrint: percentagePrint },
{ id: "hue", name: "HueRotate", min: 0, max: 2 * Math.PI, step: 0.1, prettyPrint: radiantPrint },
Comment on lines +26 to +35
// With watchFolders = [monorepoRoot], Metro resolves the entry "./index"
// from the monorepo root instead of this package. Redirect to our index.ts.
if (
moduleName === "./index" &&
context.originModulePath === monorepoRoot + "/."
) {
return {
type: "sourceFile",
filePath: path.resolve(projectRoot, "index.ts"),
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants