Build apps with Sentry
Sentry crash reporting is wired into every Goodspeed app with null-safe init, breadcrumb helpers, and sensitive-key redaction. Goodspeed generates Sentry as a standard part of every app, so the output is a working codebase from day one, not a scaffold you have to finish yourself.
WHAT GETS GENERATED
Built into every Sentry build
Every app Goodspeed generates with Sentry includes these production-ready patterns, wired together from the first build.
| Item | Description | Strength |
|---|---|---|
| lib/sentry.ts null-safe initialization | Sentry.init only runs when EXPO_PUBLIC_SENTRY_DSN is set and gasConfig.features.analytics.crashReporting is true. Empty DSN makes all exports no-ops. | Reliability |
| sanitizeData sensitive-key redaction | sanitizeData redacts any property key matching a regex of 30+ sensitive patterns (password, token, secret, apiKey, etc.) before the event is sent to Sentry. | Security |
| Breadcrumb helpers for UI, API, auth, navigation | addBreadcrumb(category, message) writes a typed breadcrumb. Callers across lib/posthog.ts, lib/revenuecat.ts, and services/ use it to produce readable event trails. | Debugging |
| User context enrichment | setSentryUser sets scope.user with the subscription tier, app version, and device model after auth. clearSentryUser clears it on sign-out. | Context |
| Transaction and span support | captureTransaction wraps expensive operations (image upload, sync replay) in Sentry transactions for performance monitoring. | Performance |
Source: the Goodspeed generation pipeline · Error Monitoring
REAL GENERATED CODE
A snippet from a Sentry app the studio shipped
This pattern comes straight out of the production groundwork every Goodspeed app is generated on. The studio generates Sentry code like this for every app in the pipeline, not a hello-world sample you have to grow into a real app.
Null-safe init + redaction
// lib/sentry.ts: null-safe Sentry init const dsn = process.env.EXPO_PUBLIC_SENTRY_DSN ?? ''; const isEnabled = gasConfig.features.analytics.crashReporting && !!dsn; if (isEnabled) { Sentry.init({ dsn, tracesSampleRate: 0.2 }); } export function sanitizeData(data: Record<string, unknown>) { const SENSITIVE = /password|token|secret|apiKey|authorization/i; return Object.fromEntries( Object.entries(data).map(([k, v]) => [k, SENSITIVE.test(k) ? '[REDACTED]' : v] ) ); }
Today's log