Una arquitectura de referencia compuesta para un cliente móvil B2C subscription SaaS - colaboración en equipo, seguimiento de hábitos o CRM ligero. La stack está fijada a Expo SDK 57 (expo ~57.0.4), React Native 0.86.0 y React 19.2.3. No es un producto enviado; destila patrones que recorren aplicaciones SaaS de producción en EAS.
┌─────────────────────────────────────────────────────────────────────────┐│ B2C SaaS - capas lógicas │├─────────────────────────────────────────────────────────────────────────┤│ app/ (Expo Router) ││ (auth)/sign-in, sign-up ← grupo de rutas sin autenticar ││ (app)/(tabs)/home|inbox|settings ← shell autenticado ││ (app)/paywall/[sku] ← presentación modal │├─────────────────────────────────────────────────────────────────────────┤│ src/features/* ← pantallas, hooks, APIs de features││ src/api/client.ts ← envolvente fetch + encabezado auth│├─────────────────────────────────────────────────────────────────────────┤│ TanStack Query (estado del servidor)← caché, staleTime, mutaciones ││ MMKV (prefs, flags) ← tema, última pestaña, alternancias│├─────────────────────────────────────────────────────────────────────────┤│ expo-secure-store ← solo token de actualización │├─────────────────────────────────────────────────────────────────────────┤│ EAS Build (binarios) development | preview | production ││ EAS Update (JS OTA) canal por perfil, runtimeVersion │└─────────────────────────────────────────────────────────────────────────┘
Ruta de solicitud (lectura autenticada):
Montaje de pantalla → useQuery(key) → ¿Impacto de caché Query? ├─ sí + fresco → renderizar ├─ sí + obsoleto → renderizar + refetch de fondo └─ no → client.ts fetch → API → escritura de caché → renderizar
Ruta de lanzamiento:
Etiqueta Git v2.4.0 → eas build --profile production → envío a store │ └─ mismo runtime → eas update --channel production (corrección de JS)
El inicio en frío carga la raíz _layout.tsx, que lee la sesión desde SecureStore, hidrata Query queryClient y redirige entre grupos (auth) y (app). Los archivos de ruta se mantienen finos - re-exportan pantallas de features según Fundamentos de Arquitectura Móvil.
// app.config.ts (fragmento) - runtime vincula OTA a la versión de storeexport default { version: "2.4.0", runtimeVersion: { policy: "appVersion" }, updates: { url: "https://u.expo.dev/<project-id>" },};
Cuándo encaja esta referencia: Aplicaciones de consumidor por suscripción con pestañas con puerta de auth, backends REST y trenes de lanzamiento gestionados por EAS.
Cuándo divergir: Colas de mutación offline, datos regulados o shells nativos brownfield - consulta casos de estudio hermanos en esta sección.
Una reversión de producción en el primer trimestre - copia de paywall incorrecta; apuntador de canal revertido en 12 minutos
Clase de incidente evitada
Sin extraños desajustes de runtimeVersion después de adoptar la política appVersion
La ruta modal de paywall (presentation: "modal") se envió sin cambios de JSX de navegador - el producto podría hacer A/B de parámetros SKU a través de OTA mientras que la configuración nativa de StoreKit se mantuvo estable.
Fija SDK 57 en la narrativa y en package.json. Las notas de actualización pertenecen a ADRs; los casos de estudio sin fijaciones de versión envejecen mal - anota cada diagrama de arquitectura con el SDK que lo moldeó.
Rutas finas, features gordas. La mayor rotación fue src/features/inbox/, no app/(app)/(tabs)/inbox.tsx. La incorporación mejoró cuando los nuevos ingenieros aprendieron el sistema de archivos solo para URLs.
Los canales son ambientes, no ingenieros. Cambiar el nombre de jane-dev a preview eliminó publicaciones accidentales de OTA de producción.
staleTime de Query es un botón de producto. Inbox a 30s obsoleto, configuración a 5m - un staleTime global causó drenaje de batería innecesario.
Reconstruye clientes de dev después de bumps que afecten nativos. SDK 57 Reanimated y actualizaciones de expo-image requirieron nuevos binarios de perfil development; las actualizaciones solo de Metro mintieron sobre el comportamiento nativo.
Documenta lo que OTA no puede cambiar. Marketing una vez solicitó un nuevo permiso de cámara a través de OTA - bloqueado hasta la compilación de store; ahora listado en la lista de verificación de lanzamiento Tier 1.