Uma arquitetura de referência composta para um cliente móvel SaaS de assinatura B2C - colaboração em equipe, rastreamento de hábitos ou CRM leve. A stack está fixada no Expo SDK 57 (expo ~57.0.4), React Native 0.86.0 e React 19.2.3. Este não é um produto publicado; ele destila padrões que recorrem em aplicativos SaaS de produção no EAS.
┌─────────────────────────────────────────────────────────────────────────┐│ SaaS B2C - camadas lógicas │├─────────────────────────────────────────────────────────────────────────┤│ app/ (Expo Router) ││ (auth)/sign-in, sign-up ← grupo de rotas não autenticado ││ (app)/(tabs)/home|inbox|settings ← shell autenticado ││ (app)/paywall/[sku] ← apresentação modal │├─────────────────────────────────────────────────────────────────────────┤│ src/features/* ← telas, hooks, APIs de recursos ││ src/api/client.ts ← wrapper fetch + header de auth │├─────────────────────────────────────────────────────────────────────────┤│ TanStack Query (estado do servidor) ← cache, staleTime, mutações ││ MMKV (prefs, flags) ← tema, última aba, toggles de recurso │├─────────────────────────────────────────────────────────────────────────┤│ expo-secure-store ← apenas token de atualização │├─────────────────────────────────────────────────────────────────────────┤│ EAS Build (binários) development | preview | production ││ EAS Update (JS OTA) canal por perfil, runtimeVersion │└─────────────────────────────────────────────────────────────────────────┘
Caminho da requisição (leitura autenticada):
Montagem da tela → useQuery(chave) → Cache de Query atingido? ├─ sim + fresco → renderizar ├─ sim + obsoleto → renderizar + refetch em segundo plano └─ não → fetch de client.ts → API → escrita no cache → renderizar
Caminho de lançamento:
Tag Git v2.4.0 → eas build --profile production → envio para loja │ └─ mesmo runtime → eas update --channel production (hotfix JS)
A inicialização a frio carrega o _layout.tsx raiz, que lê a sessão do SecureStore, hidrata o queryClient do Query e redireciona entre os grupos (auth) e (app). Arquivos de rota permanecem finos - eles reexportam telas de recursos por Noções Básicas de Arquitetura Mobile.
// app.config.ts (excerto) - runtime vincula OTA à versão da lojaexport default { version: "2.4.0", runtimeVersion: { policy: "appVersion" }, updates: { url: "https://u.expo.dev/<project-id>" },};
Quando esta referência se encaixa: Aplicativos de consumo por assinatura com abas protegidas por autenticação, backends REST e trens de lançamento gerenciados pelo EAS.
Quando divergir: Filas de mutação offline, dados regulamentados ou shells nativos brownfield - veja estudos de caso irmãos nesta seção.
Um rollback de produção no primeiro trimestre - cópia incorreta do paywall; ponteiro de canal revertido em 12 minutos
Classe de incidente evitada
Nenhum travamento por incompatibilidade de runtimeVersion após a adoção da política appVersion
A rota modal do paywall (presentation: "modal") foi lançada sem alterações no JSX do navegador - o produto pôde fazer A/B de parâmetros SKU via OTA enquanto a configuração nativa do StoreKit permaneceu estável.
Fixe o SDK 57 na narrativa e no package.json. Notas de atualização pertencem a ADRs; estudos de caso sem pinos de versão envelhecem mal - anote cada diagrama de arquitetura com o SDK que o moldou.
Rotas finas, recursos robustos. A maior rotatividade foi em src/features/inbox/, não em app/(app)/(tabs)/inbox.tsx. O onboarding melhorou quando novos engenheiros aprenderam o sistema de arquivos apenas para URLs.
Canais são ambientes, não engenheiros. Renomear jane-dev para preview eliminou publicações acidentais de OTA de produção.
staleTime do Query é um controle de produto. Inbox com 30s de stale, configurações com 5m - um staleTime global causou dreno de bateria desnecessário.
Reconstrua clientes de desenvolvimento após atualizações que afetam o nativo. Atualizações do Reanimated e expo-image do SDK 57 exigiram novos binários do perfil development; atualizações apenas do Metro mentiram sobre o comportamento nativo.
Documente o que o OTA não pode mudar. O marketing uma vez solicitou uma nova permissão de câmera via OTA - bloqueado até a compilação da loja; agora listado no checklist de lançamento Nível 1.