React Server Components setup steps
To use React Server Components: 1. Install react-server-dom-webpack with 'npx expo install react-server-dom-webpack'. 2. Ensure the entry module is 'expo-router/entry' (default) in package.json. 3. Enable reactServerFunctions flag in app.json under expo.experiments. 4. Ensure 'origin' is not set to a boolean value anywhere in app config. 5. Create an initial route at app/index.tsx. 6. Create Server Functions in separate files marked with 'use server'.
web.output configuration for React Server Components
web.output must be set to 'single' in the app config during the React Server Components developer preview. Support for more output modes is coming soon.
Server Components capabilities and restrictions
Server Components run on the server and can access server APIs, Node.js built-ins (when running locally), and use async components. They cannot use hooks like useState, useEffect, or useContext, and cannot use browser or native APIs.
use server directive purpose
'use server' is not meant to mark a file as a server component. It is used to mark a file as having React Server Functions exported from it.
Server Components environment variable access
Server components have access to all environment variables as they run securely off the client.
Client Components in React Server Components
Client Components are marked with 'use client' directive at the top of the file. They are used to access native APIs or React Context which Server Components cannot access.
Passing props to Server Components
You cannot pass functions as props to Server Components. You can only pass serializable data.
React Server Functions definition
Server Functions are functions that run on the server and can be called from Client Components. They must always be async functions and are marked with 'use server' at the top of the function.
Server Functions serialization restrictions
Server Functions can only receive serializable data as arguments and can only return serializable data.
Server Functions DOM component limitation
Server Functions currently cannot be used inside of DOM components.
RSC payload format
React Server Functions in Expo Router render React components on the server and stream back an RSC payload, a custom JSON-like format maintained by the React team, for rendering on the client. This is similar to server-side rendering on the web.
EXPO_OS environment variable for platform detection
Use process.env.EXPO_OS to detect which platform code is bundled for, for example 'process.env.EXPO_OS === "ios"'. Prefer this to Platform.OS as react-native is not fully optimized for React Server Components yet.
Server vs client detection in Server Components
You can detect if code is running on the server by performing a 'typeof window === "undefined"' check. This will always return true on client devices and false on the server.
React 19 canary build for Server Components
To enable React Server Components, Expo CLI automatically uses a special canary build of React on all platforms. In the future, it will be removed when React 19 is enabled by default in React Native.
Metadata and meta tags in Server Components
React Server Components are a feature of React 19. You can use React 19 features such as placing <meta> tags anywhere in your app (web-only). Use process.env.EXPO_OS to conditionally render meta tags only on web.
Learn TypeScript with official resources
Start learning TypeScript with the official TypeScript Handbook at https://www.typescriptlang.org/docs/handbook/2/everyday-types.html. For TypeScript and React components, refer to the React TypeScript CheatSheet at https://github.com/typescript-cheatsheets/react to learn how to type React components in common situations.
Type check project with tsc command
To type check your project's files, run `tsc` command from the root of your project directory. Use one of these commands: `npm run tsc` (npm), `yarn run tsc` (yarn), `pnpm run tsc` (pnpm), or `bun run tsc` (bun).
Generate tsconfig.json base configuration
Generate a base tsconfig.json file by running `npx expo customize tsconfig.json` (npm), `yarn expo customize tsconfig.json` (yarn), `pnpm expo customize tsconfig.json` (pnpm), or `bun expo customize tsconfig.json` (bun). The generated tsconfig.json should extend 'expo/tsconfig.base' by default.
Enable strict type checking in tsconfig.json
To enable strict type checking and reduce chances of runtime errors, add `"strict": true` under `compilerOptions` in tsconfig.json. This configuration is optional but encouraged for better type safety.
Enable absolute imports with compilerOptions.baseUrl
To enable absolute imports from the project's root directory, set `"baseUrl": "./"` under compilerOptions in tsconfig.json. This allows importing modules like `import Button from 'src/components/Button';` without relative paths. Restarting Expo CLI is necessary after modifying baseUrl. Absolute imports are only supported by Metro (including Metro web), not by @expo/webpack-config.
Path aliases in tsconfig.json
Expo CLI supports path aliases in tsconfig.json automatically. To use path aliases, define `baseUrl` and `paths` in compilerOptions. For example, to import a component with alias @/components/Button from src/components/Button.tsx, set baseUrl to "." and add "@/*": ["src/*"] in paths. Restart Expo CLI after modifying tsconfig.json to update path aliases. Path aliases add additional resolution time and are only supported by Metro (including Metro web), not by deprecated @expo/webpack-config.
Type generation in Expo libraries
Some Expo libraries provide both static types and type generation capabilities. These types are automatically generated when the project builds or by running `npx expo customize tsconfig.json` command.
Disable path aliases in app.json
Path aliases are enabled by default via tsconfigPaths. To disable path aliases, set "tsconfigPaths" to false under "experiments" in the expo configuration in app.json.
Metro setup for existing React Native projects
Existing React Native projects require additional setup for path aliases and absolute imports. See the Metro setup guide at /versions/latest/config/metro#existing-react-native-apps for more information.
jsconfig.json as alternative to tsconfig.json
If not using TypeScript, jsconfig.json can serve as an alternative to tsconfig.json for path aliases and absolute imports configuration.
TypeScript language features requiring configuration
Some TypeScript language features may require additional configuration in tsconfig.json. For example, to use decorators, add the `experimentalDecorators` option under compilerOptions. For more information on available compiler options, see the TypeScript compiler options documentation.
baseUrl resolution order and priority
compilerOptions.baseUrl is resolved before node modules. This means if you have a file named ./path.ts, it can be imported instead of a node module named path. compilerOptions.paths are resolved relative to baseUrl if it is defined, otherwise they're resolved against the project root directory.
Create new Expo project with TypeScript template
To create a new Expo project with TypeScript support, use the default template (SDK 57) with one of these commands: `npx create-expo-app@latest --template default@sdk-57` (npm), `yarn create expo-app --template default@sdk-57` (yarn), `pnpm create expo-app --template default@sdk-57` (pnpm), or `bun create expo --template default@sdk-57` (bun). The default template includes base TypeScript configuration, example code, and basic navigation structure.
Rename files to .tsx or .ts for TypeScript migration
When migrating a JavaScript project to TypeScript, rename files to use .tsx or .ts extensions. Use .tsx if the file contains React components (JSX), and use .ts if the file does not contain any JSX. For example, rename App.js to App.tsx using `mv App.js App.tsx`.
Configure app.config.ts with TypeScript
app.config.ts is supported by default but does not support external TypeScript modules or tsconfig.json customization. To use TypeScript in app.config.ts, import tsx/cjs and define the ExpoConfig type: `import 'tsx/cjs'; import { ExpoConfig } from 'expo/config'; const config: ExpoConfig = { name: 'my-app', slug: 'my-app', }; export default config;`
Configure metro.config.js with TypeScript
To use TypeScript with Metro configuration, update metro.config.js to require tsx/cjs and import metro.config.ts: `require('tsx/cjs'); module.exports = require('./metro.config.ts');` Then create metro.config.ts with configuration like: `import { getDefaultConfig } from 'expo/metro-config'; const config = getDefaultConfig(__dirname); module.exports = config;`
Use tsx for TypeScript in config files
To use TypeScript for configuration files like metro.config.js or app.config.js, install tsx as a dev dependency and use its tsx/cjs require hook to import TypeScript files within JavaScript configuration files. This allows TypeScript imports while keeping the root file as JavaScript. Install tsx using: `npx expo install tsx --dev` (npm), `yarn expo install tsx --dev` (yarn), `pnpm expo install tsx --dev` (pnpm), or `bun expo install tsx --dev` (bun). On Windows, add "--" before --dev for npm, yarn, and pnpm.
Install TypeScript dev dependencies
To add TypeScript support to an existing Expo project, install typescript and @types/react as dev dependencies. On macOS/Linux use: `npx expo install typescript @types/react --dev` (npm), `yarn expo install typescript @types/react --dev` (yarn), `pnpm expo install typescript @types/react --dev` (pnpm), or `bun expo install typescript @types/react --dev` (bun). On Windows, add "--" before --dev for npm, yarn, and pnpm. Alternatively, running `npx expo start` will automatically install these dependencies.
Create new Expo project with Bun
To create a new Expo project with Bun, run the command: bun create expo-app my-app
Run package.json scripts with Bun
Any package.json script can be run with Bun using the command: bun run [script-name]. For example, bun run ios.
Install Expo libraries with Bun
To install Expo libraries with Bun, use the command: bun expo install [package-name]. For example, bun expo install expo-audio.
Bun trusted dependencies for postinstall scripts
Unlike other package managers, Bun does not automatically execute lifecycle scripts from installed libraries as a security measure. If a package has a postinstall script that needs to run, explicitly include that library in the 'trustedDependencies' array in package.json. For example: {"trustedDependencies": ["your-dependency"]}. After adding trusted dependencies, remove the lockfile and node_modules folder, then run 'bun install' again.
Sentry with Bun on EAS Build
When using sentry-expo or @sentry/react-native with Bun on EAS Build, the build may fail because @sentry/cli has a postinstall script that must run for the source map upload feature to work. Add '@sentry/cli' to the trustedDependencies array in package.json: {"trustedDependencies": ["@sentry/cli"]}
Using Bun as JavaScript runtime with Expo
Bun is a JavaScript runtime and drop-in alternative for Node.js that can be used in Expo projects to install npm packages and run Node.js scripts. Benefits include faster package installation than npm, pnpm, or Yarn, and at least 4x faster startup time compared to Node.js.
Prerequisites for using Bun with Expo
Bun must be installed on your machine. Node.js (LTS version) is still required for the 'bun create expo' and 'bun expo prebuild' commands, which use npm pack to download project templates.
Feature flags definition and purpose
A feature flag, also known as a feature gate, is a mechanism that enables and disables features remotely. They provide a safe way to roll out new features to app users without deploying additional code. Feature flags can be used for testing in production, A/B testing, or shipping new app features such as UI elements.
Feature flag services compatibility with Expo
Feature flag services documented for Expo support Continuous Native Generation (CNG) and config plugins for seamless integration in Expo apps. The services with documented support for Expo apps include PostHog, Statsig, LaunchDarkly, and Firebase Remote Config.
PostHog feature flagging capabilities
PostHog is an open-source product analytics platform that provides comprehensive feature flagging capabilities alongside analytics, session recordings, and A/B testing. It supports real-time feature toggles with user segmentation and instant feature rollback. It includes built-in A/B testing and multivariate testing functionality, allowing you to run experiments directly through feature flags while collecting detailed analytics on feature adoption and performance metrics. The service supports bootstrap flags to eliminate loading states and improve user experience.
Statsig feature management platform
Statsig is a feature management platform designed for data-driven product development that provides advanced statistical analysis, gradual rollouts, and sophisticated targeting capabilities with built-in metrics and performance monitoring for feature releases. The platform offers a robust SDK for React Native and Expo, with automatic event logging and dynamic configurations, making it particularly well-suited for teams focused on rigorous experimentation and data-driven decision-making.
LaunchDarkly feature management platform
LaunchDarkly is an enterprise-grade feature management platform that enables instant feature toggles and targeted rollouts with comprehensive dashboard controls, advanced user targeting, and robust experimentation tools that provide real-time flag updates. The SDK includes advanced features such as hooks for React integration, context identification and modification, comprehensive logging, support for multiple environments in development workflows, private attributes for handling sensitive data, and relay proxy configuration for enhanced security and performance.
Firebase Remote Config service
Firebase Remote Config is a cloud service that allows you to change the appearance and functionality of your app without requiring an app update. Remote Config values are managed through the Firebase console and accessed via a JavaScript API, which gives you full control over when and how these values affect your app. The service supports conditional targeting based on user properties, app versions, custom attributes and real-time updates.
ConvexProvider setup in Expo Router
To add a Convex provider in an Expo Router project, update src/app/_layout.tsx. Import ConvexProvider and ConvexReactClient from 'convex/react', import Stack from 'expo-router'. Create a ConvexReactClient instance with process.env.EXPO_PUBLIC_CONVEX_URL and the option unsavedChangesWarning set to false. Wrap the Stack component in ConvexProvider with the client prop.
Using Convex useQuery hook
Call Convex query functions from your app with the useQuery hook from 'convex/react'. Import the api object from '@/convex/_generated/api', then call useQuery(api.tasks.get) to fetch data. The hook returns the data or undefined while loading.
Convex provider example code
import { ConvexProvider, ConvexReactClient } from 'convex/react';
import { Stack } from 'expo-router';
const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!, {
unsavedChangesWarning: false,
});
export default function RootLayout() {
return (
<ConvexProvider client={convex}>
<Stack />
</ConvexProvider>
);
}
Convex integration with EAS CLI
EAS CLI can create and connect a Convex project automatically. The integration replaces manual setup steps of installing the package, creating a Convex team and project, copying deployment URLs, and configuring EAS environment variables.
eas integrations:convex:connect command
Run 'eas integrations:convex:connect' from your Expo project directory to connect Convex with EAS. The command prompts for a Convex deployment region, project name, and team name when needed. It only asks for a team name when it needs to create a new Convex team connection. You can pass values explicitly with flags: --region aws-us-east-1 --team-name "Your-team-name" --project-name "your-app"
What eas integrations:convex:connect does
The integration command: installs the convex package with 'npx expo install convex'; creates a Convex team connection for your EAS account or reuses an existing one; creates a Convex project and deployment for the current Expo app; writes CONVEX_DEPLOY_KEY and EXPO_PUBLIC_CONVEX_URL to .env.local; creates or updates the EXPO_PUBLIC_CONVEX_URL EAS project environment variable for production, preview, and development environments; sends an invitation to your verified email so you can claim the Convex team and open the Convex dashboard.
Start Convex dev server
After the EAS integration command finishes, start the Convex dev server with 'npx convex dev' (npm), 'yarn dlx convex dev' (yarn), 'pnpm dlx convex dev' (pnpm), or 'bunx convex dev' (bun). This creates the local convex directory if your project does not have one yet, generates the typed API files, and syncs your Convex functions with your deployment while it runs.
Convex query function example
import { query } from './_generated/server';
export const get = query({
args: {},
handler: async ctx => {
return await ctx.db.query('tasks').collect();
},
});
Convex useQuery example code
import { api } from '@/convex/_generated/api';
import { useQuery } from 'convex/react';
import { Text, View } from 'react-native';
export default function Index() {
const tasks = useQuery(api.tasks.get);
return (
<View>
{tasks?.map(task => (
<Text key={task._id}>{task.text}</Text>
))}
</View>
);
}
Manage Convex integration commands
Use these EAS CLI commands to inspect or manage the Convex integration later: 'eas integrations:convex:project', 'eas integrations:convex:dashboard', 'eas integrations:convex:team', 'eas integrations:convex:team:invite'.
Remove Convex integration
Use 'eas integrations:convex:project:delete' or 'eas integrations:convex:team:delete' to remove the link. EAS removes its integration metadata with these commands, but they do not destroy resources on Convex.
Convex team invitation email mismatch troubleshooting
The Convex team invitation is sent to the verified email on your Expo account, but Convex only supports signing in with Google or GitHub. If your Google or GitHub email differs from your verified Expo email, the invitation page shows the invited email has not been added to your Convex account. To accept the invite from your existing Convex account: click Add email on the invitation page or in the Convex dashboard's profile settings and enter the invited email address; open the verification email Convex sends to that address and verify it; return to the invitation link and reload the page, or sign out and open the invitation link again; accept the invite and the team and project will appear in your Convex account.
Legacy config Node.js environment example
Example of using eslint-env comment in metro.config.js:
/* eslint-env node */
const { getDefaultConfig } = require('expo/metro-config');
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
module.exports = config;
Install Prettier and ESLint integration packages
Run npx expo install prettier eslint-config-prettier eslint-plugin-prettier --dev (or yarn, pnpm, bun equivalents) to install Prettier and integration packages. On Windows, use "--" before --dev flag.