feat(mobile): add expo-observe update health tracking

Install expo-observe (56.0.29, matching the SDK 56 line) and configure
its endpoint under expo.extra.eas.observe in app.json, alongside the
existing EAS projectId. Leave dispatchInDebug and sampleRate at their
defaults.

Log an app_started custom event once per cold start from the root
layout's existing "run once" startup effect, and install a global JS
error handler that logs xprem_js_crash and then always delegates to
whatever handler was previously registered, so existing Crashlytics
reporting is unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jjbruntonandClaude Fable 5 committed 2026-08-31 11:11:43 +01:00
1 parent 6bc4e31719
commit 659cee76b6
4 files changed
+197 -21

No files matched your search

+20 -14
View File
@@ -5,6 +5,11 @@ import "../src/polyfills/web";
import { initCrashlytics, setUserContext, clearUserContext } from "../src/lib/crashlytics";
initCrashlytics();
// Install the Observe global JS error handler after Crashlytics so it wraps
// (and always calls) whatever handler is already registered.
import { installObserveGlobalErrorHandler, logAppStarted } from "../src/lib/observe";
installObserveGlobalErrorHandler();
// Analytics imports (initialization deferred until app mounts)
import { initAnalytics, setUserId, clearUserId, logScreenView, Events } from "../src/lib/analytics";
@@ -73,6 +78,7 @@ export default function RootLayout() {
analyticsInitialized.current = true;
initAnalytics();
Events.appOpened("cold");
logAppStarted();
}
}, []);
@@ -115,15 +121,15 @@ export default function RootLayout() {
// Fetch user on mount
fetchUser();
// Handle initial URL if app was opened via deep link
const handleDeepLink = async (url: string | null) => {
if (!url) return;
// Handle initial URL if app was opened via deep link
const handleDeepLink = async (url: string | null) => {
if (!url) return;
// Invite links (https://sauci.app/join/{code} or app.sauci://join?code={code})
// are handled separately from the Supabase auth deep link flow below.
const inviteLink = parseInviteLinkCode(url);
if (inviteLink) {
Events.inviteLinkOpened(inviteLink.source);
const inviteLink = parseInviteLinkCode(url);
if (inviteLink) {
Events.inviteLinkOpened(inviteLink.source);
await stashPendingInviteCode(inviteLink.code);
const { isAuthenticated, user } = useAuthStore.getState();
@@ -200,15 +206,15 @@ export default function RootLayout() {
}
};
// Get initial URL
Linking.getInitialURL().then((url) => {
handleDeepLink(url);
});
// Get initial URL
Linking.getInitialURL().then((url) => {
handleDeepLink(url);
});
// Listen for new deep links while app is open
const linkingSubscription = Linking.addEventListener("url", (event) => {
handleDeepLink(event.url);
});
// Listen for new deep links while app is open
const linkingSubscription = Linking.addEventListener("url", (event) => {
handleDeepLink(event.url);
});
// Set up push notification response listener (for taps while app is running)
const notificationSubscription = setupNotificationResponseListener();