πŸ“ File path: apps/weshipit/pages/plan/2026-W26.md

React Native Roadmap 2026-W26

Week of June 22–June 28, 2026

Items This Week

#TitleLabelLink
1The React Native Rewind: Vercel Eve & Tauri Desktop Shells🟦 RNRead
2TWIR #287: Reanimated 4.5 β€” CSS pseudo-selectors on native🟦 RNRead
3TWIR #287: VisionCamera v5 β€” real-time frame processing🟦 RNRead
4TWIR #287: Fragment ref coming to React & React Native (v19.3)βš›οΈ REACTRead
5Expo Changelog: Maestro testing β€” insights, clearer results & faster retries🟧 EXPORead
6Expo Blog: iOS Widgets & Live Activities stable in Expo SDK 56🟧 EXPORead
7React Status #480: Writing Custom Renderers for React (Callstack/RNTL)βš›οΈ REACTRead

5-Day Action Plan

Β 


🟦 Chunk 1 β€” Implement Reanimated 4.5 CSS Pseudo-selector Animations

Goal: Deliver polished hover, active, and focus interaction states using Reanimated 4.5's new CSS pseudo-selectors, matching the browser experience on native iOS and Android.

Scope:

  • Upgrade react-native-reanimated to ^4.5.0
  • Replace Pressable/onPressIn/onPressOut workarounds with declarative :hover, :active, :focus CSS animation rules
  • Implement at least two interactive components (e.g. a primary button and a card) using the new pseudo-selector API
  • Verify behaviour on iOS, Android, and Web (Expo)

Out of scope:

  • Custom animation orchestration with useAnimatedStyle
  • Migration of all existing animations in the codebase
  • Gesture-based animations (swipe, drag)

Dependencies: React Native β‰₯ 0.83, New Architecture enabled, Reanimated 4.x already installed.

Acceptance criteria:

  • Pressing a button shows a visible :active state with a CSS transition (scale or opacity)
  • Hovering on web/iPad triggers a :hover state without any JS handler
  • Focus ring appears on keyboard navigation (web target)
  • No regression on existing animations

Estimated effort: S

Β 

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Add CSS pseudo-selector animation states (:hover, :active, :focus) to interactive UI components using Reanimated 4.5.

Files to create or modify:

  • package.json β€” bump react-native-reanimated to ^4.5.0
  • components/ui/Button.tsx β€” rewrite interaction states using Reanimated CSS pseudo-selectors
  • components/ui/Card.tsx β€” add :hover and :active states
  • app/(tabs)/index.tsx (or equivalent) β€” add a demo screen showcasing both components

Step-by-step instructions:

  1. Run npx expo install react-native-reanimated@^4.5.0
  2. In Button.tsx, import Animated from react-native-reanimated and replace the Pressable manual state tracking with a single AnimatedPressable component using the new CSS-style style prop supporting :active and :hover pseudo-selectors.
  3. Define styles using StyleSheet.create where :active reduces scale to 0.97 and changes backgroundColor opacity.
  4. In Card.tsx, apply :hover to elevate the shadow and scale to 1.02.
  5. Create a simple demo screen to showcase both components.
  6. Run npx expo start and test on iOS Simulator, Android Emulator, and Web.

Acceptance criteria checklist:

  • Tapping the button triggers a smooth :active scale/opacity transition
  • Hovering over a card on Web/iPad shows the elevated shadow state
  • No onPressIn/onPressOut manual state management remains
  • Animations run at 60 fps (no JS thread drops)
  • Existing Reanimated animations pass a smoke test

🟦 Chunk 2 β€” Build a VisionCamera v5 Real-time Frame Processor

Goal: Unlock real-time per-frame processing using VisionCamera v5's Frame.hasPixelBuffer / Frame.hasNativeBuffer APIs β€” enabling use cases like live filters, barcode scanning, or ML inference directly on the camera stream.

Scope:

  • Install / confirm react-native-vision-camera@^5.0.11 and react-native-worklets-core
  • Create a useFrameProcessor worklet that reads frame buffer availability via frame.hasPixelBuffer
  • Implement a simple real-time overlay (e.g. brightness meter or luma value) drawn from frame data
  • Display the processed value reactively in the UI using a shared value

Out of scope:

  • ML model integration (TensorFlow, CoreML, ONNX)
  • Photo / video capture flow
  • Multi-camera capture

Dependencies: Chunk is self-contained. Requires a physical device or simulator with camera support (physical recommended). New Architecture enabled.

Acceptance criteria:

  • Camera preview renders with no dropped frames
  • A per-frame numeric value (e.g. average brightness) updates in the UI at β‰₯30 fps
  • frame.hasPixelBuffer correctly gates the processing path on iOS
  • frame.hasNativeBuffer correctly gates the processing path on Android
  • No JS thread blockage (worklet runs on the camera thread)

Estimated effort: M

Β 

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Create a real-time camera frame processor using VisionCamera v5 that reads per-frame pixel data and displays a computed value in the UI.

Files to create or modify:

  • package.json β€” ensure react-native-vision-camera@^5.0.11 and react-native-worklets-core are installed
  • screens/CameraScreen.tsx β€” main camera screen with live overlay
  • hooks/useFrameBrightnessProcessor.ts β€” frame processor worklet logic
  • app.json / Info.plist / AndroidManifest.xml β€” camera permission configuration

Step-by-step instructions:

  1. Install: npx expo install react-native-vision-camera react-native-worklets-core
  2. Add camera permissions in app.json (iOS NSCameraUsageDescription, Android CAMERA).
  3. In useFrameBrightnessProcessor.ts, create a useFrameProcessor worklet:
    • Check frame.hasPixelBuffer (iOS) or frame.hasNativeBuffer (Android) before processing
    • Compute an average luma value by sampling pixel bytes
    • Write the result to a useSharedValue<number> via runOnJS
  4. In CameraScreen.tsx, render <Camera> with frameProcessor prop, and display the shared value using an Animated.Text connected via useAnimatedProps.
  5. Test on a physical device for real-time performance.

Acceptance criteria checklist:

  • Camera preview renders without lag
  • Brightness value updates at β‰₯30 fps
  • hasPixelBuffer / hasNativeBuffer guard prevents crashes on unsupported frames
  • Worklet runs off the JS thread (verified with Flipper / Xcode Instruments)
  • App does not crash on permission denial

🟧 Chunk 3 β€” Implement an iOS Widget with Expo SDK 56

Goal: Ship a production-ready iOS Home Screen widget using the now-stable expo-widget API in Expo SDK 56, surfacing key app data to users without opening the app.

Scope:

  • Confirm project is on Expo SDK 56 with expo-widget dependency
  • Create a Small widget variant (2Γ—2) displaying a piece of dynamic app data (e.g. today's stats, latest notification)
  • Wire up widget data refresh via WidgetKit background tasks through Expo's native bridge
  • Preview the widget in the iOS Simulator widget gallery

Out of scope:

  • Medium/Large widget variants
  • Android widgets (different API)
  • Live Activities (separate task)
  • Custom widget fonts or complex animations

Dependencies: Expo SDK 56, Xcode 16+, physical device or iOS Simulator 18+. EAS Build required for a device build (local Expo Go cannot run widgets).

Acceptance criteria:

  • Widget appears in the iOS widget picker under the app name
  • Widget displays real data (not placeholder) after the first background refresh
  • Tapping the widget deep-links into the correct screen in the app
  • Widget preview renders correctly in Xcode widget simulator

Estimated effort: M

Β 

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Create a small iOS Home Screen widget using the stable expo-widget API from Expo SDK 56 that displays dynamic app data.

Files to create or modify:

  • package.json β€” ensure expo@^56.0.0 and expo-widget are installed
  • widget/SmallWidget.tsx β€” widget UI component (SwiftUI-like declarative syntax via Expo Widget API)
  • widget/index.ts β€” widget entry point registering the widget family
  • app/(tabs)/index.tsx β€” trigger widget data refresh on app foreground
  • eas.json β€” ensure iOS build profile targets iOS 17+

Step-by-step instructions:

  1. Run npx expo install expo-widget and ensure SDK is ^56.0.0.
  2. Create widget/SmallWidget.tsx using WidgetView, Text, and Link from expo-widget.
  3. Define a TimelineEntry interface with the data shape your widget will display.
  4. Implement a getTimeline function that fetches data from shared UserDefaults/App Group and returns an array of entries.
  5. Register the widget in widget/index.ts with registerWidget({ families: ['small'], component: SmallWidget }).
  6. In the main app, call Widget.reloadAll() when relevant data changes.
  7. Build with eas build --platform ios --profile preview and install on device/simulator.

Acceptance criteria checklist:

  • Widget appears in the iOS widget picker
  • Small widget renders the correct data shape
  • Tapping the widget opens the correct in-app screen
  • Widget.reloadAll() triggers a visible data refresh within 60 seconds
  • No crash on cold widget load (no app running in background)

🟧 Chunk 4 β€” Configure Maestro E2E Testing with EAS Insights Dashboard

Goal: Set up Maestro end-to-end tests integrated with EAS, and activate the new Insights dashboard to track flaky tests and regressions across the team over time.

Scope:

  • Install Maestro CLI and write 2–3 critical user journey flows (e.g. onboarding, login, core action)
  • Add an EAS Workflow step that runs Maestro tests on every pull request
  • Enable the new EAS Maestro Insights dashboard for the project
  • Configure retry policy for flaky tests using the new faster-retry feature

Out of scope:

  • Visual regression testing
  • Android E2E (focus on iOS first)
  • Full coverage of all screens

Dependencies: EAS account with Workflows enabled (Free or paid plan), Maestro CLI installed locally, an existing Expo app buildable with EAS.

Acceptance criteria:

  • At least 2 Maestro .yaml flow files committed to the repo
  • EAS Workflow triggers Maestro tests on every PR (visible in the EAS dashboard)
  • Insights tab shows historical test run data after the first CI run
  • Flaky test is identified correctly by the Insights dashboard (can be simulated with a known flaky assertion)
  • Tests complete in under 5 minutes per run

Estimated effort: S

Β 

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Add Maestro E2E test flows integrated with EAS Workflows and activate the EAS Maestro Insights dashboard for test monitoring.

Files to create or modify:

  • .maestro/onboarding.yaml β€” Maestro flow for the onboarding screen
  • .maestro/login.yaml β€” Maestro flow for the login flow
  • .eas/workflows/pr-checks.yml β€” EAS Workflow definition that runs Maestro on PRs
  • eas.json β€” ensure a preview build profile exists for simulator builds

Step-by-step instructions:

  1. Install Maestro: curl -Ls "https://get.maestro.mobile.dev" | bash
  2. Create .maestro/onboarding.yaml: use launchApp, assertVisible, tapOn, and assertVisible to test the onboarding screens.
  3. Create .maestro/login.yaml: input credentials, tap login, assert the home screen is visible.
  4. In .eas/workflows/pr-checks.yml, add a maestro job step pointing to your .maestro/ folder, targeting the preview build artifact.
  5. Set retries: 2 in the EAS Workflow maestro step to leverage the faster-retry feature.
  6. Push a PR and verify the Workflow runs in the EAS dashboard.
  7. Navigate to EAS β†’ your project β†’ Testing β†’ Insights to verify the dashboard is populated.

Acceptance criteria checklist:

  • Both .yaml flows pass locally with maestro test .maestro/onboarding.yaml
  • EAS Workflow triggers automatically on PR creation
  • Test results appear in the EAS Insights tab after the first run
  • Failed/flaky tests are highlighted with a distinct status
  • Total CI time for both flows is under 5 minutes

βš›οΈ Chunk 5 β€” Prepare Codebase for Fragment Ref API (React 19.3 / RN canary)

Goal: Refactor at least one composite component to leverage the upcoming <Fragment ref> API (available in React canary), enabling cleaner cross-component DOM/native node access without wrapper <View> nodes.

Scope:

  • Upgrade to React 19 canary (react@canary) in a feature branch
  • Identify one composite component that currently uses a wrapper <View> solely to expose a ref
  • Refactor it to use <Fragment ref> and FragmentInstance to access first-level children
  • Write a unit test verifying ref access via the new API
  • Document the pattern in a docs/fragment-ref.md file for the team

Out of scope:

  • Migrating all ref-using components
  • Production deployment of canary React (exploration only)
  • Full feature parity evaluation between React and React Native implementations

Dependencies: This is an exploratory chunk. React 19.3 canary must be installed (npm install react@canary react-dom@canary). No production deployment required.

Acceptance criteria:

  • The refactored component renders correctly without the wrapper <View>
  • ref.current via FragmentInstance correctly references the first child node
  • Unit test passes with @testing-library/react-native
  • docs/fragment-ref.md clearly explains the before/after pattern
  • A PR is opened with the exploration, tagged as [RFC] for team review

Estimated effort: S

Β 

Copy/paste this prompt:

Implement the following React Native chunk for your mobile app:

Goal: Refactor a composite component to use the upcoming <Fragment ref> API (React 19.3 canary) and document the pattern for the team.

Files to create or modify:

  • package.json β€” add react@canary override in a feature branch only
  • components/ui/AnimatedList.tsx β€” refactor to remove wrapper <View> using Fragment ref
  • components/ui/__tests__/AnimatedList.test.tsx β€” unit test verifying ref access
  • docs/fragment-ref.md β€” documentation of the pattern

Step-by-step instructions:

  1. Create a new git branch: git checkout -b explore/fragment-ref
  2. Install React canary: npm install react@canary react-dom@canary --save-exact
  3. Identify a component that wraps children in a <View ref={ref}> solely to expose a measurement or layout ref.
  4. Refactor: replace <View ref={ref}> with <Fragment ref={ref}>. TypeScript: type the ref as React.RefObject<React.FragmentInstance>.
  5. Access the first child via ref.current.children[0] for measurements.
  6. Write a test using renderHook + useRef<React.FragmentInstance>() to assert ref.current is not null after mount.
  7. Create docs/fragment-ref.md with a before/after code example and a note that this targets React 19.3.
  8. Open a PR titled [RFC] Explore Fragment ref API for component composition.

Acceptance criteria checklist:

  • Component renders without the extra wrapper <View> node
  • ref.current is a FragmentInstance after mount
  • ref.current.children[0] resolves to the first child native node
  • Unit test passes with jest --testPathPattern=AnimatedList
  • docs/fragment-ref.md is committed and explains the pattern clearly
  • Branch is mergeable with no TypeScript errors