Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Loaded automatically when its description matches the active task. Read only the reference section that matches the current sub-task — Pattern 2 layout means you never need to scan the full skill.
Use this skill when
Bootstrapping a new Expo app (create-expo-app, TypeScript template, expo-dev-client)
Designing or refactoring navigation with Expo Router (Stack, Tabs, Drawer, dynamic segments, typed routes, modals, redirects)
Setting up EAS Build profiles (development, preview, production), env vars, secrets, build resources, monorepo configs
Shipping OTA updates via EAS Update — channels, branches, runtime version, fingerprint policy, rollback, code signing
Submitting to App Store / Google Play with EAS Submit (ASC API key, internal track, production track)
Writing Expo Modules (Swift / Kotlin) or config plugins that modify Info.plist / AndroidManifest at prebuild
Implementing OAuth / deep links with expo-auth-session (PKCE) and expo-linking (custom scheme, universal links, app links)
Requesting native permissions (camera, location, contacts, notifications) and adding matching plist/manifest entries via plugins
Migrating to or debugging New Architecture (Fabric, TurboModules, bridgeless) on RN 0.85
Diagnosing Metro errors, Hermes crashes, native Gradle/Xcode build failures, EAS build log issues
Do not use this skill when
The codebase is plain React for the web — use react
Working in Next.js App Router — use nextjs
The project is Flutter / Dart, Capacitor, or native-only Swift/Kotlin — out of scope
The question is about generic TypeScript type system design — use
typescript
Setting up Better Auth on the server — use better-auth (Expo only consumes the OAuth/session it exposes)
Purpose
Expo SDK 55 is the latest stable release built on React Native 0.85, where the New Architecture is the default (Fabric renderer, TurboModules, bridgeless mode). The SDK pairs the OSS framework with EAS — managed builds, OTA updates, and store submission — so a single codebase ships to iOS, Android, and (optionally) web.
This skill covers the full mobile lifecycle: project creation, file-based routing with Expo Router, native customisation through config plugins and the Expo Modules API, push notifications, OAuth deep links, and the EAS pipeline from local prebuild to TestFlight / Play Console. It hands off to react for component patterns and to typescript for type-system specifics.
Capabilities
Project bootstrap and dev workflow
create-expo-app scaffolds a TypeScript + Expo Router project. The default workflow is a development build (expo-dev-client) — a customizable shell that supersedes Expo Go for anything beyond the SDK surface. Use Expo Go only for very early prototypes that touch zero custom native code.
eas.json defines build profiles (development, preview, production). Profiles control distribution (internal vs store), developmentClient, resource class, env vars, and platform-specific overrides. eas build:configure initialises the file. npx expo prebuild materialises native ios//android/ directories for inspection or CNG-managed workflows.
Push JS-only updates to installed binaries. Updates are scoped by channel (mapped to a build profile) and runtime version (must match between binary and update). The fingerprint policy hashes native dependencies so an OTA never lands on an incompatible binary. eas update:roll-back-to-embedded reverts to the shipped JS.
eas submit --platform <ios|android> ships a finished build to the store. iOS uses an ASC API key (appleId, ascAppId, appleTeamId); Android uses a service-account JSON. The track knob controls Play Console rollout (internal, alpha, beta, production).
Two layers of native customisation: Expo Modules API (Swift/Kotlin module with declarative requireNativeModule JS binding) and config plugins (Node functions that mutate Info.plist, AndroidManifest.xml, Gradle, Podfile at prebuild). Use withInfoPlist, withAndroidManifest, withDangerousMod from expo/config-plugins.
Camera, location, contacts, notifications, microphone, photos. Two-step pattern: declare usage strings via config plugin (Info.plist key + Android <uses-permission>), then call the module's requestPermissionsAsync() at runtime. Never call native APIs without a fallback for denied/limited states.
expo-notifications registers a device, fetches an Expo push token, sets a foreground handler, and listens for received/responded events. On Android, channels (setNotificationChannelAsync) are required before the permissions prompt. Production sends go via Expo's push service (proxy to FCM + APNs) or directly via FCM/APNs.
expo-auth-session implements OAuth + PKCE flows; expo-linking parses incoming URLs and builds redirect URIs. scheme in app config plus associatedDomains (iOS) and intentFilters (Android) wire universal/app links. Always test both cold-start and warm-resume link handling.
Fabric (concurrent renderer), TurboModules (lazy native modules), and bridgeless mode are on by default. Legacy Paper-only libraries are now opt-in via newArchEnabled: false — discouraged. Common gotchas: layout-effect timing changes, third-party libs missing TurboModule shims, Reanimated/Skia version pins.
Routing prompts that validate the skill loads when expected (Expo Router refactor, EAS Build setup, push token registration) and stays out when it shouldn't (web-only React, Next.js, Flutter).
Reaches for development builds (expo-dev-client) over Expo Go on every non-trivial project — Expo Go's native surface is fixed and blocks most production features
Pins runtime version with the fingerprint policy so OTA updates never collide with an incompatible binary
Treats app.config.ts as the source of truth — never hand-edits files under ios/ / android/ unless the project is intentionally bare-workflow
Models permissions as declare-via-plugin + request-via-API in one PR; never one without the other
Wraps push-token registration in Device.isDevice and gracefully degrades on simulators
Reads EXPO_PUBLIC_* env vars at build time only — secrets go to EAS Secrets, never bundled into JS
Writes config plugins as typed ConfigPlugin<Props> from expo/config-plugins and validates with expo prebuild --clean before pushing
Verifies New Architecture compatibility for every third-party native lib before adding it (TurboModule support matrix)
Splits navigation by _layout.tsx boundary — auth-gated stacks live behind (auth) groups with <Redirect> in their layout
Uses typed routes (experiments.typedRoutes: true) on every new project — eliminates an entire class of broken links
Important Constraints
NEVER hand-edit ios/ or android/ in a managed/CNG project — those are derived artifacts; encode the change as a config plugin and re-run prebuild
NEVER ship secrets in JS — EXPO_PUBLIC_* is public; sensitive values belong in EAS Secrets or a backend
NEVER call Updates.reloadAsync() in Expo Go or dev mode — it rejects; gate with Updates.isEnabled
NEVER mismatch runtime versions across a binary and its OTA — clients ignore incompatible updates silently
NEVER assume notifications work on a simulator — push tokens require a physical device on both platforms
NEVER disable the New Architecture without a documented reason — it's the default on RN 0.85 and most libraries have dropped Paper-only support
NEVER commit google-services.json / GoogleService-Info.plist with production keys to a public repo — load via EAS file env vars
ALWAYS pair a config plugin change with npx expo prebuild --clean in CI to catch native drift
ALWAYS test deep links from both cold-start (app killed) and warm-resume (app backgrounded) — they hit different code paths
ALWAYS validate that a third-party native dependency declares Expo Modules / autolinking support before adopting it
Related Skills
Active skills only; cascade markers omitted.
Language and core framework
✓ react — composition patterns, hooks, Suspense, useOptimistic — all apply on RN