All skills
expo avatar

/expo-web-to-native

@5c8f62e official
by expoexpo/skills2.6k stars
156

Framework (OSS). Migrate an existing web React app to a native iOS/Android app with Expo. Use when the user wants to turn a website into a mobile app, port a Next.js/Vite/CRA React codebase to React Native, reuse web code on native incrementally, or asks how web idioms (the DOM, CSS, React Router, localStorage, window) map to native. This is the end-to-end migration guide; use the `expo-dom` skill for the DOM-component mechanism itself.

Use this Skill: https://skilld.dev/gh/expo/skills/expo-web-to-native

This session only. Nothing lands on disk.

referencesverify-on-device.md

≈1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Verify a migrated screen against the running web app

Disclosed reference for expo-web-to-native, steps 3–4. Verification means running both apps and comparing the same screen - the native port beside the web original. A clean compile or a green expo export proves nothing - a screen can build and still render blank or mis-render. This parity check is the gate the strangle loop runs each iteration.

Two agents drive it, and this skill is opinionated: it requires both and installs them rather than falling back to manual screenshots.

  • Web side — agent-browser (vercel-labs, a Rust browser CLI): open <url>, snapshot --json (accessibility tree with refs), screenshot <path>, read (rendered DOM/text).
  • Native side — argent (@swmansion/argent): drives the simulator — describe (a11y tree), debugger-component-tree (RN tree), gesture-tap/keyboard, flow to record a check and replay it each pass. Invoke as argent run <tool> --udid <udid> (get the udid from argent run list-devices).

Setup — install if missing (don't skip, don't fall back to manual)

Check both are on PATH; if either is absent, ask the user, then install before proceeding:

which agent-browser || (npm i -g agent-browser && agent-browser install)   # web agent (+ its Chrome)
which argent        || npm i -g @swmansion/argent                          # device agent

The workflow

A. Capture the web original with agent-browser — the source of truth for parity. Run the web app (its pnpm dev server, or the deployed URL if local setup needs DB/auth env), then:

agent-browser open "<web-url>/<route>?<params>"
agent-browser snapshot --json      # structure to diff
agent-browser screenshot web.png   # visual reference

Tip: capture web baselines for every screen once, up front, then diff against them instead of re-opening the web app each iteration.

B. Capture the native screen (iOS shown via simctl; Android note below):

  1. Run the app: npx expo start --ios (Expo Go). On SDK 56+ both @expo/ui and DOM components run in Expo Go — no dev build, no react-native-webview to install; reach for a dev build (the expo-dev-client skill) only for custom native modules. Stale-bundle trap: a CI-mode Metro + cached Expo Go can show an old build — terminate Expo Go and add --clear if a change doesn't appear.
  2. Boot a sim: xcrun simctl boot <udid> (xcrun simctl list devices available); open -a Simulator.
  3. Open the route: deep-link xcrun simctl openurl booted "exp://<lan-ip>:8081/--/<route>?<params>", or argent launch-app + gesture-tap.
  4. Capture: xcrun simctl io booted screenshot native.png, or argent run describe --udid <udid> for structure.

Android: simctl / expo run:ios are iOS-only. Use an Android emulator + adb — adb exec-out screencap -p > native.png, adb shell am start -a android.intent.action.VIEW -d "<deep-link>", adb shell screenrecord for motion — or npx expo run:android for a dev build.

C. Compare the two for the same route — layout, content, behavior. Diff the structures (agent-browser snapshot against argent describe / debugger-component-tree), not just pixels. Pass only on parity: same data, and params passed into a DOM webview must produce the same result.

Feel needs motion, not a still. For a nativized screen with transitions, gestures, or haptics, a screenshot can't catch a janky push or wrong easing — capture a short recording (iOS xcrun simctl io booted recordVideo feel.mov; Android adb shell screenrecord; or an argent flow) and confirm it moves like a native app (see native-patterns.md → Feel).

What "pass" looks like

  • DOM-shelled screen (step 3): the web UI renders inside the native header/shell; params from the native route drive it the same as on web.
  • Nativized screen (step 4): native primitives only, no webview; matches the web original screen.

Source: SKILL.md on GitHub

No alerts23d3 checks · Risk SAFE
  • Gen Agent Trust Hub23d

    The skill provides a comprehensive guide for migrating web React applications to Expo. It uses standard development tools and commands for verification and feedback, fetching resources from trusted and well-known sources.

  • Socket23d

    No alerts

  • Snyk23d

    Risk: LOW · No issues

Signed by skilld at 5c8f62e. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 days ago.

Activeupdated 2 months ago
version
1.0.0

README badge

README badge for expo/skills/expo-web-to-native