Persistent staging flow deployment pattern
The persistent staging flow is a deployment pattern that involves always having a version of your production app that points to a staging channel, allowing you to test updates before deploying to all end users.
Expo Atlas visualizes production bundle and identifies library contributions
Expo Atlas is a tool that visualizes the production JavaScript bundle and identifies which libraries contribute to the bundle size. It helps developers understand and improve bundle size by showing the impact of each dependency.
Enable Expo Atlas with dev server using EXPO_ATLAS environment variable
To use Expo Atlas with the local development server, set the EXPO_ATLAS=true environment variable when running npx expo start. This allows Atlas to update whenever code in the project changes.
Access Expo Atlas in dev tools plugin menu with keyboard shortcut
When the app is running on Android, iOS, or web with the local development server, open Expo Atlas through the dev tools plugin menu by pressing Shift + M.
Run Expo Atlas in production mode with --no-dev flag
To get a more accurate representation of the production bundle size, start the local development server in production mode by running EXPO_ATLAS=true npx expo start --no-dev. This disables optimizations that are disabled in development mode but enabled in production mode.
Expo Atlas generates .expo/atlas.jsonl file during export
When exporting a production bundle with EXPO_ATLAS=true npx expo export, Atlas generates a .expo/atlas.jsonl file that can be shared and opened without project access. This file contains the original and transformed source code of every bundled module, including inlined EXPO_PUBLIC_ environment variables. Treat it like source code and only share with trusted people.
Open exported Expo Atlas file with npx expo-atlas command
After exporting with EXPO_ATLAS=true npx expo export, open the generated .expo/atlas.jsonl file by running npx expo-atlas .expo/atlas.jsonl.
Specify platforms for Expo Atlas analysis with --platform option
When exporting, use the --platform option to specify which platforms Expo Atlas should analyze. Atlas will gather data for the exported platforms only.
Inspect transformed module details in Expo Atlas
Inside Expo Atlas, hold Cmd and click on a graph node to see the transformed module details. This shows how a module is transformed by Babel, which modules it imports, and which modules imported it, helping trace the origin of a module across the dependency graph.
source-map-explorer is alternative bundle analyzer for SDK 50 and earlier
The source-map-explorer library can be used to visualize and analyze production JavaScript bundles as an alternative method for SDK 50 and below. It is not recommended for SDK 51 and later, where Expo Atlas should be used instead.
Run Lighthouse CLI on exported web production build
After creating a production build with npx expo export -p web and serving it locally or in production, run Lighthouse by executing npx lighthouse <url> --view with the URL where the site is hosted.
JavaScript bundle size impacts web startup time and performance
For web browsers, which do not support precompiled bytecode, JavaScript bundle size is important for improving startup time and performance. The smaller the bundle, the faster it can be downloaded and parsed.
Export with --source-maps flag for source-map-explorer
When using source-map-explorer for SDK 50 or below, export the production JavaScript bundle with the --source-maps flag to include source maps that source-map-explorer requires.
Disable bytecode with --no-bytecode for analyzing Hermes bundles
For native apps using Hermes, use the --no-bytecode option when exporting with source maps to disable bytecode generation, allowing the JavaScript bundle to be analyzed without precompiled bytecode.
Do not publish source maps to production
Avoid publishing source maps to production as they can cause both security issues and performance issues, since browsers will download the large map files.
source-map-explorer NODE_OPTIONS workaround for Node.js 18+
If source-map-explorer shows the error 'You must provide the URL of lib/mappings.wasm by calling SourceMapConsumer.initialize' when using Node.js 18 and above, set the environment variable NODE_OPTIONS=--no-experimental-fetch before running the analyze script.
source-map-explorer warnings about unmapped bytes are normal
When source-map-explorer shows warnings like 'Unable to map 809/13787 bytes (5.87%)', this occurs because source maps exclude bundler runtime definitions. This value is consistent and not a reason for concern.
Lighthouse analyzes website performance, accessibility, and speed
Lighthouse is a tool that measures how fast, accessible, and performant a website is. It can be used through the Audit tab in Chrome DevTools or via the Lighthouse CLI.
Aptabase, Astrolytics, and PostHog work with Expo Go
The analytics services Aptabase, Astrolytics, and PostHog are compatible with Expo Go and do not require native code configuration or a development build.
Analytics SDKs available in Expo and React Native ecosystem
Common analytics providers available in the Expo and React Native ecosystem include: Google Firebase Analytics, Segment, Amplitude, AWS Amplify, Aptabase, Astrolytics, PostHog, and Dreambase. Some services (Aptabase, Astrolytics, PostHog) work with Expo Go without requiring a development build.
Supabase local development setup
Development runs locally with the Supabase CLI. Start Docker, then run 'npx supabase init', 'npx supabase start', and 'npx supabase status'. Replace the hosted values in .env.local with the API URL and publishable key that 'supabase status' prints. Variables you export in your shell take precedence over .env.local, so edit the file instead of exporting. The local database starts empty, so run your table SQL against it too. Re-running connect writes the hosted values back.
Supabase overview and how it works with Expo
Supabase is a Backend-as-a-Service (BaaS) app development platform built on Postgres. It generates a REST API from your database and uses row level security to protect data, allowing React Native apps to query the API directly with no server in between.
Creating Supabase client in Expo
Create a helper file that initializes the Supabase client from environment variables. The file src/lib/supabase.ts should import 'expo-sqlite/localStorage/install', then import createClient from @supabase/supabase-js. Use process.env.EXPO_PUBLIC_SUPABASE_URL and process.env.EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY to create the client with auth options: storage set to localStorage, autoRefreshToken true, persistSession true, and detectSessionInUrl false (since Android and iOS have no URL to read a session from).
Supabase client example code
import 'expo-sqlite/localStorage/install';
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL!;
const supabasePublishableKey = process.env.EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY!;
export const supabase = createClient(supabaseUrl, supabasePublishableKey, {
auth: {
storage: localStorage,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false,
},
});
expo-sqlite localStorage for Supabase sessions
Importing 'expo-sqlite/localStorage/install' provides the localStorage that Supabase uses to persist sessions on the device, which keeps users signed in across app launches.
Supabase SQL to create table with row level security
Example SQL to create a Supabase table with row level security:
create table public.todos (
id bigint generated always as identity primary key,
title text not null
);
alter table public.todos enable row level security;
create policy "Anyone can read todos" on public.todos for select using (true);
grant select on public.todos to anon, authenticated;
insert into public.todos (title) values ('Hello from Supabase');
Requests use the anon role when signed out and authenticated after sign-in. Without a policy, a select returns an empty array and no error. To let the app write, add an insert policy.
Supabase row level security grants behavior
The grant is a safeguard rather than a requirement. Hosted projects already grant select, insert, update, and delete on new tables in public to both anon and authenticated roles. However, Supabase is making those grants opt-in, and a project with them revoked fails with 'permission denied for table todos'. Granting a privilege the table already has changes nothing.
Verifying Supabase configuration in Expo
Replace the first screen with a query against a Supabase table to verify the configuration works. An example queries a todos table and displays results. Start the app with 'npx expo start'. If the screen shows the expected data, the client works. An empty screen means no policy allows the read. An error message means something else needs troubleshooting.
Testing Supabase in Expo Go versus development builds
You can test Supabase in Expo Go. You need a development build once you pass options to the expo-sqlite plugin or add other native libraries.
Supabase local stack address for physical device
The local Supabase URL points at your computer. A physical device or an Android Emulator cannot reach it, so use your computer's LAN address there instead of 127.0.0.1.
Manual Supabase setup steps
To manually set up Supabase without the connect command: create a project at database.new, copy the Project URL from API Settings and the Publishable key from API Keys, install the SDK with 'npx expo install @supabase/supabase-js expo-sqlite', add the expo-sqlite config plugin to your app config, set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY in .env.local, and create the client file.
Troubleshooting: Active project limit reached
The Free plan entitles each user to two active projects; an organization pools the entitlement of every owner and administrator in it. Paused projects do not count. To resolve: link a project you already have with --link, pause or delete one in the Supabase dashboard, upgrade the organization, or see Supabase's billing FAQ. --environment cannot be combined with --link, so on that path free a slot or set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY on the target environments yourself.
Troubleshooting: Project reference ID format
The project must belong to the Supabase organization you connected. The project reference ID is found under Project Settings > General. Accepted formats include the reference ID alone, a dashboard URL, or a project API URL. A project name does not work.
Troubleshooting: Environment variables not updating
After connect writes environment variables, reload the app so it picks up the new values. If the app still reads the old value, stop the development server and run 'npx expo start' again.
Troubleshooting: Table doesn't exist right after creation
Supabase caches your database schema, so a query right after you create a table can fail with 'Could not find the table in the schema cache'. Re-run it; the cache refreshes on its own.
Troubleshooting: Permission denied for a table
Add the grant your query needs for both roles, such as 'grant select on public.todos to anon, authenticated'. A policy alone is not enough. Unlike a missing policy, which returns an empty array, this fails with error.code 42501.
Troubleshooting: Supabase authorization stopped working
If you revoked Expo's access in Supabase, run 'eas integrations:supabase:connect --reauth'. This clears the stored connection and project link, reopens the browser, then asks whether to link a project or create one, so have your reference ID ready. Your Supabase projects are not affected. --reauth needs a browser, so it fails in non-interactive mode.
Troubleshooting: Extra project created without environment variables
If 'connect --environment' creates a project and then fails to write the environment variables, the command prints the project URL and publishable key. Save those values with 'eas env:set'. Do not re-run 'connect --environment', as it creates another project that counts against your plan limit.
Recommended resources after creating new Expo project
After creating a new Expo project, recommended learning resources include: Development tools (reference of Expo tools), Development builds (for full control over app build process and device testing), Development overview (high-level overview of development concepts and core development loop), Expo Router (navigation library), App icon and splash screen customization guides, app config reference for app.json properties, App distribution and submission guides for releasing to app stores, and Debugging tools for finding and fixing errors.
React and React Native learning fundamentals
Solid understanding of React is essential for using Expo to build apps. Recommended resources include React documentation's Quick Start section and Hooks section. For React Native, start with the React Native basics guide, then learn about View API reference, Text API reference, platform-specific code, and presenting data in lists.
Flexbox layout learning for React Native
Flexbox is used to layout React Native components. Recommended learning resources include Height and Width documentation and Layout with Flexbox documentation from React Native docs.
Gestures and animations in React Native
To implement gestures and animations in React Native, recommended resources are React Native Gesture Handler documentation and React Native Reanimated documentation (fundamentals and getting started sections).
LogRocket integration with EAS
LogRocket records user sessions and identifies bugs as users use your app. You can filter sessions by update IDs and connect to your LogRocket account on the EAS dashboard to get quick access to your app's session data.
Sentry crash reporting for Expo apps
Sentry is a crash reporting platform that notifies you of exceptions or errors your users run into while using your app. Reported exceptions automatically include stacktraces, device info, version, and other relevant context. You can provide additional context specific to your app, such as the current route and user ID.
BugSnag stability monitoring
BugSnag is a stability monitoring solution that provides rich, end-to-end error reporting and analytics. It supports the full stack with open-source libraries for more than 50 platforms, including React Native.
PostHog analytics platform with EAS integration
PostHog is a product analytics platform with session replay, feature flags, and error tracking. The EAS CLI integration provisions a PostHog project, wires up the SDK, and lets you tag events by EAS Update through release tagging so you can filter analytics and errors by release.
Post-release app monitoring overview
Once your app is released, you can track anonymized usage data to give you insights on how users use your app, including which updates are in use, when users experience bugs, and how the app performs in production.