- name
- sentry-react-native-sdk
- description
- Full Sentry SDK setup for React Native and Expo. Use when asked to "add Sentry to React Native", "install @sentry/react-native", "setup Sentry in Expo", or configure error monitoring, tracing, profiling, session replay, or logging for React Native applications. Supports Expo managed, Expo bare, and vanilla React Native.
- license
- Apache-2.0
# Sentry React Native SDK
Opinionated wizard that scans your React Native or Expo project and guides you through complete Sentry setup — error monitoring, tracing, profiling, session replay, logging, and more.
## Invoke This Skill When
- User asks to "add Sentry to React Native" or "set up Sentry" in an RN or Expo app
- User wants error monitoring, tracing, profiling, session replay, or logging in React Native
- User mentions `@sentry/react-native`, mobile error tracking, or Sentry for Expo
- User wants to monitor native crashes, ANRs, or app hangs on iOS/Android
> **Note:** SDK versions and APIs below reflect current Sentry docs at time of writing (`@sentry/react-native` ≥6.0.0, minimum recommended ≥8.0.0).
> Always verify against [docs.sentry.io/platforms/react-native/](https://docs.sentry.io/platforms/react-native/) before implementing.
---
## Phase 1: Detect
Run these commands to understand the project before making any recommendations:
```bash
# Detect project type and existing Sentry
cat package.json | grep -E '"(react-native|expo|@expo|@sentry/react-native|sentry-expo)"'
# Distinguish Expo managed vs bare vs vanilla RN
ls app.json app.config.js app.config.ts 2>/dev/null
cat app.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print('Expo managed' if 'expo' in d else 'Bare/Vanilla')" 2>/dev/null
# Check Expo SDK version (important: Expo SDK 50+ required for @sentry/react-native)
cat package.json | grep '"expo"'
# Detect navigation library
grep -E '"(@react-navigation/native|react-native-navigation)"' package.json
# Detect state management (Redux → breadcrumb integration available)
grep -E '"(redux|@reduxjs/toolkit|zustand|mobx)"' package.json
# Check for existing Sentry initialization
grep -r "Sentry.init" src/ app/ App.tsx App.js _layout.tsx 2>/dev/null | head -5
# Detect Hermes (affects source map handling)
cat android/app/build.gradle 2>/dev/null | grep -i hermes
cat ios/Podfile 2>/dev/null | grep -i hermes
# Detect Expo Router
ls app/_layout.tsx app/_layout.js 2>/dev/null
# Detect backend for cross-link
ls backend/ server/ api/ 2>/dev/null
find . -maxdepth 3 \( -name "go.mod" -o -name "requirements.txt" -o -name "Gemfile" -o -name "package.json" \) 2>/dev/null | grep -v node_modules | head -10
```
**What to determine:**
| Question | Impact |
|----------|--------|
| `expo` in `package.json`? | Expo path (config plugin + `getSentryExpoConfig`) vs bare/vanilla RN path |
| Expo SDK ≥50? | `@sentry/react-native` directly; older = `sentry-expo` (legacy, do not use) |
| `app.json` has `"expo"` key? | Managed Expo — wizard is simplest; config plugin handles all native config |
| `app/_layout.tsx` present? | Expo Router project — init goes in `_layout.tsx` |
| `@sentry/react-native` already in `package.json`? | Skip install, jump to feature config |
| `@react-navigation/native` present? | Recommend `reactNavigationIntegration` for screen tracking |
| `react-native-navigation` present? | Recommend `reactNativeNavigationIntegration` (Wix) |
| Backend directory detected? | Trigger Phase 4 cross-link |
---
## Phase 2: Recommend
Present a concrete recommendation based on what you found. Don't ask open-ended questions — lead with a proposal:
**Recommended (core coverage — always set up these):**
- ✅ **Error Monitoring** — captures JS exceptions, native crashes (iOS + Android), ANRs, and app hangs
- ✅ **Tracing** — mobile performance is critical; auto-instruments navigation, app start, network requests
- ✅ **Session Replay** — mobile replay captures screenshots and touch events for debugging user issues
**Optional (enhanced observability):**
- ⚡ **Profiling** — CPU profiling on iOS (JS profiling cross-platform); low overhead in production
- ⚡ **Logging** — structured logs via `Sentry.logger.*`; links to traces for full context
- ⚡ **User Feedback** — collect user-submitted bug reports directly from your app
**Recommendation logic:**
| Feature | Recommend when... |
|---------|------------------|
| Error Monitoring | **Always** — non-negotiable baseline for any mobile app |
| Tracing | **Always for mobile** — app start, navigation, and network latency matter |
| Session Replay | User-facing production app; debug user-reported issues visually |
| Profiling | Performance-sensitive screens, startup time concerns, or production perf investigations |
| Logging | App uses structured logging, or you want log-to-trace correlation in Sentry |
| User Feedback | Beta or customer-facing app where you want user-submitted bug reports |
Propose: *"For your [Expo managed / bare RN] app, I recommend setting up Error Monitoring + Tracing + Session Replay. Want me to also add Profiling and Logging?"*
---
## Phase 3: Guide
### Determine Your Setup Path
| Project type | Recommended setup | Complexity |
|-------------|------------------|------------|
| Expo managed (SDK 50+) | Wizard CLI or manual with config plugin | Low — wizard does everything |
| Expo bare (SDK 50+) | Wizard CLI recommended | Medium — handles iOS/Android config |
| Vanilla React Native (0.69+) | Wizard CLI recommended | Medium — handles Xcode + Gradle |
| Expo SDK <50 | Use `sentry-expo` (legacy) | See [legacy docs](https://docs.sentry.io/platforms/react-native/manual-setup/expo/) |
---
### Path A: Wizard CLI (Recommended for all project types)
Run the wizard — it walks you through login, org/project selection, and auth token setup interactively. It then handles installation, native config, source map upload, and initial `Sentry.init()`:
```bash
npx @sentry/wizard@latest -i reactNative
```
**What the wizard creates/modifies:**
| File | Action | Purpose |
|------|--------|---------|
| `package.json` | Installs `@sentry/react-native` | Core SDK |
| `metro.config.js` | Adds `@sentry/react-native/metro` serializer | Source map generation |
| `app.json` | Adds `@sentry/react-native/expo` plugin (Expo only) | Config plugin for native builds |
| `App.tsx` / `_layout.tsx` | Adds `Sentry.init()` and `Sentry.wrap()` | SDK initialization |
| `ios/sentry.properties` | Stores org/project/token | iOS source map + dSYM upload |
| `android/sentry.properties` | Stores org/project/token | Android source map upload |
| `android/app/build.gradle` | Adds Sentry Gradle plugin | Android source maps + proguard |
| `ios/[AppName].xcodeproj` | Wraps "Bundle RN" build phase + adds dSYM upload | iOS symbol upload |
| `.env.local` | `SENTRY_AUTH_TOKEN` | Auth token (add to `.gitignore`) |
After the wizard runs, skip to [Verification](#verification).
---
### Path B: Manual — Expo Managed (SDK 50+)
**Step 1 — Install**
```bash
npx expo install @sentry/react-native
```
**Step 2 — `metro.config.js`**
```javascript
const { getSentryExpoConfig } = require("@sentry/react-native/metro");
const config = getSentryExpoConfig(__dirname);
module.exports = config;
```
If `metro.config.js` doesn't exist yet:
```bash
npx expo customize metro.config.js
# Then replace contents with the above
```
**Step 3 — `app.json` — Add Expo config plugin**
```json
{
"expo": {
"plugins": [
[
"@sentry/react-native/expo",
{
"url": "https://sentry.io/",
"project": "YOUR_PROJECT_SLUG",
"organization": "YOUR_ORG_SLUG"
}
]
]
}
}
```
> **Note:** Set `SENTRY_AUTH_TOKEN` as an environment variable for native builds — never commit it to version control.
**Step 4 — Initialize Sentry**
For **Expo Router** (`app/_layout.tsx`):
```typescript
import { Stack, useNavigationContainerRef } from "expo-router";
import { isRunningInExpoGo } from "expo";
import * as Sentry from "@sentry/react-native";
import React from "react";
const navigationIntegration = Sentry.reactNavigationIntegration({
enableTimeToInitialDisplay: !isRunningInExpoGo(), // disabled in Expo Go
});
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN ?? "YOUR_SENTRY_DSN",
sendDefaultPii: true,
// Tracing
tracesSampleRate: 1.0, // lower to 0.1–0.2 in production
// Profiling
profilesSampleRate: 1.0,
// Session Replay
replaysOnErrorSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
// Logging (SDK ≥7.0.0)
enableLogs: true,
// Navigation
integrations: [
navigationIntegration,
Sentry.mobileReplayIntegration(),
],
enableNativeFramesTracking: !isRunningInExpoGo(), // slow/frozen frames
environment: __DEV__ ? "development" : "production",
});
function RootLayout() {
const ref = useNavigationContainerRef();
React.useEffect(() => {
if (ref) {
navigationIntegration.registerNavigationContainer(ref);
}
}, [ref]);
return <Stack />;
}
export default Sentry.wrap(RootLayout);
```
For **standard Expo** (`App.tsx`):
```typescript
import { NavigationContainer, createNavigationContainerRef } from "@react-navigation/native";
import { isRunningInExpoGo } from "expo";
import * as Sentry from "@sentry/react-native";
const navigationIntegration = Sentry.reactNavigationIntegration({
enableTimeToInitialDisplay: !isRunningInExpoGo(),
});
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN ?? "YOUR_SENTRY_DSN",
sendDefaultPii: true,
tracesSampleRate: 1.0,
profilesSampleRate: 1.0,
replaysOnErrorSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
enableLogs: true,
integrations: [
navigationIntegration,
Sentry.mobileReplayIntegration(),
],
enableNativeFramesTracking: !isRunningInExpoGo(),
environment: __DEV__ ? "development" : "production",
});
const navigationRef = createNavigationContainerRef();
function App() {
return (
<NavigationContainer
ref={navigationRef}
onReady={() => {
navigationIntegration.registerNavigationContainer(navigationRef);
}}
>
{/* your navigation here */}
</NavigationContainer>
);
}
export default Sentry.wrap(App);
```
---
### Path C: Manual — Bare React Native (0.69+)
**Step 1 — Install**
```bash
npm install @sentry/react-native --save
cd ios && pod install
```
**Step 2 — `metro.config.js`**
```javascript
const { getDefaultConfig } = require("@react-native/metro-config");
const { withSentryConfig } = require("@sentry/react-native/metro");
const config = getDefaultConfig(__dirname);
module.exports = withSentryConfig(config);
```
**Step 3 — iOS: Modify Xcode build phase**
Open `ios/[AppName].xcodeproj` in Xcode. Find the **"Bundle React Native code and images"** build phase and replace the script content with:
```bash
# RN 0.81.1+
set -e
WITH_ENVIRONMENT="../node_modules/react-native/scripts/xcode/with-environment.sh"
SENTRY_XCODE="../node_modules/@sentry/react-native/scripts/sentry-xcode.sh"
/bin/sh -c "$WITH_ENVIRONMENT $SENTRY_XCODE"
```
**Step 4 — iOS: Add "Upload Debug Symbols to Sentry" build phase**
Add a new **Run Script** build phase in Xcode (after the bundle phase):
```bash
/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh
```
**Step 5 — iOS: `ios/sentry.properties`**
```properties
defaults.url=https://sentry.io/
defaults.org=YOUR_ORG_SLUG
defaults.project=YOUR_PROJECT_SLUG
auth.token=YOUR_ORG_AUTH_TOKEN
```
**Step 6 — Android: `android/app/build.gradle`**
Add before the `android {}` block:
```groovy
apply from: "../../node_modules/@sentry/react-native/sentry.gradle"
```
**Step 7 — Android: `android/sentry.properties`**
```properties
defaults.url=https://sentry.io/
defaults.org=YOUR_ORG_SLUG
defaults.project=YOUR_PROJECT_SLUG
auth.token=YOUR_ORG_AUTH_TOKEN
```
**Step 8 — Initialize Sentry (`App.tsx` or entry point)**
Auf GitHub ansehen