Quando SDKs Opcionais Agem como Infraestrutura Core

Uma falha comum de lançamento em apps mobile feitas com vibe coding é inicializar analytics, attribution ou crash reporting junto com serviços realmente críticos. Se um desses SDKs opcionais se comporta mal em um dispositivo específico ou sob uma condição de rede específica, o app inteiro pode morrer antes de a primeira tela aparecer.

Isso acontece porque código de setup gerado por IA tende a tratar toda dependência como se tivesse a mesma importância. Sem um sistema de tiers explícito, não existe distinção arquitetural entre infraestrutura obrigatória e observadores nice-to-have. Tudo vira obrigatório por acidente.

Três Tiers de Dependência

Toda dependência da sua app cai em um de três grupos. Desenhar essas linhas explicitamente é a diferença entre um app que sobrevive ao crescimento e um que morre em mil crashes de produção:

  • Hard dependencies: Se elas falham, sua app não consegue renderizar. Parsing de config. Criação de storage. Construção dos services centrais. Essa é a fundação.
  • Soft dependencies: Elas podem falhar com degradação elegante. Auth. Recursos dependentes de rede. Fluxos dependentes de permissão. O shell da app ainda renderiza; o usuário vê uma experiência degradada, não um crash.
  • Optional dependencies: Elas podem falhar em silêncio. Analytics. Crash reporting. Testes A/B. Nunca bloqueiam a app. São observadores, não participantes.

O erro que a maioria das apps feitas com vibe coding comete é tratar tudo como hard dependency. Todo SDK inicializa na partida. Toda falha vira crash de startup. Mas o seu SDK de analytics não merece o mesmo status da sua camada de storage.

A Fronteira das Hard Dependencies

A fronteira hard valida a config e constrói os services. Se ela falha, a app mostra uma tela de erro com botão de retry, não um vazio branco que os usuários vão punir com uma estrela na App Store.

// src/context/hard-dependency-boundary.tsx
// This is the gatekeeper. If it fails, nothing else renders.

import * as SplashScreen from 'expo-splash-screen'

void SplashScreen.preventAutoHideAsync()

export function HardDependencyBoundary({
  children,
}: {
  children: (services: Services) => ReactNode
}) {
  const { services, ready, error, retry } =
    useHardDependencies()

  useEffect(() => {
    if (ready || error) void SplashScreen.hideAsync()
  }, [ready, error])

  if (error) {
    return (
      <ErrorScreen
        title='Startup failed'
        message={error.message}
        onRetry={retry}
      />
    )
  }

  if (!ready || !services) return null

  return <>{children(services)}</>
}

Repare no padrão de render prop. A fronteira passa os services inicializados para os filhos. Os filhos não constroem services; eles os recebem. A construção acontece exatamente uma vez, e qualquer falha é capturada na fronteira, não vazada para um crash report em produção.

A Fronteira Opcional

Compare isso com dependências opcionais. Elas nunca deveriam derrubar sua app. Se o Mixpanel cair, sua app nem soluça:

// src/context/optional-dependency-boundary.tsx
// If analytics fails, we log a warning and keep going.

export function OptionalDependencyBoundary({
  children,
}: PropsWithChildren) {
  const { analytics, crashReporting } = useServices()

  useEffect(() => {
    try {
      analytics.track('app_started')
    } catch (error) {
      if (__DEV__) console.warn('Analytics failed:', error)
    }

    try {
      crashReporting.setContext('app', { started: true })
    } catch (error) {
      if (__DEV__) console.warn('Crash reporting failed:', error)
    }
  }, [analytics, crashReporting])

  return <>{children}</>
}

A diferença de postura é gritante. Fronteira hard: se falhar, mostre uma tela de erro. Fronteira opcional: se falhar, registre um warning e siga em frente. As duas são explícitas. Nenhuma finge ser a outra.

A maioria dos crashes em produção em apps feitos com vibe coding vem do mesmo erro: tratar dependências soft ou opcionais como se fossem hard. O Autotomy Expo Starter Pack traça essas linhas desde o primeiro dia para que você nunca aprenda essa lição às 2 da manhã.