A realidade PWA-first em 2026: instalabilidade, Safari no iOS, funcionamento offline e a questão das lojas para o Math Challenge
Resumo executivo
PWA-first é viável em 2026, com fronteiras técnicas que é preciso desenhar, não ignorar. No Chrome/Edge a instalação é automática via manifest + heurística de compromisso, sem exigir service worker registado como critério formal [7]. No iOS Safari continua a ser manual (“Partilhar → Adicionar ao ecrã inicial”, sem beforeinstallprompt) [1]; a partir do iOS 16.4 isto habilita Web Push e Badging API, mas apenas se a aplicação estiver instalada com display: standalone/fullscreen [1][2]. O episódio da DMA da UE (2024) foi real — a Apple anunciou degradar as aplicações de início a marcadores simples na UE e reverteu antes do iOS 17.4 após pressão pública; hoje a funcionalidade completa persiste na UE [6]. O armazenamento melhorou: iOS 17/macOS 14 dão às aplicações instaladas ~60 % do disco, e ficam exentas da purga de 7 dias que se aplica ao armazenamento criado por script sem interação [4][5]. Background Sync e Periodic Background Sync não existem no Safari nem no Firefox (apenas Chromium), e Periodic Sync exige aplicação instalada mais “engagement score” positivo, sem garantia de frequência [15][16] — isto obriga a um mecanismo próprio de sincronização ao reabrir a aplicação como linha de base universal. Para lojas: PWABuilder/Bubblewrap cobre Android via Trusted Web Activity [8][9], mas iOS exige Capacitor com capacidades nativas reais para superar a guia 4,2 da Apple contra “recortes web” [12]. Se o produto se direciona a crianças, Kids Category (Apple) e Families (Google Play) aplicam independentemente da arquitetura [13][14].
Este documento foi traduzido do original em inglês por Claude (Anthropic) e verificado automaticamente contra a fonte: cada número, URL, marcador de citação e marca [unverified] corresponde ao original. A prosa em si ainda não foi revista por um editor humano nativo.
Estado de verificação
Este documento não traz qualquer marca [unverified]. Cada afirmação está ligada a uma fonte numerada abaixo.
[unverified] significa que a afirmação está na investigação mas não foi confirmada contra uma fonte primária na sessão que a produziu. É publicada em vez de removida, porque um corpus que esconde as suas lacunas não é verificável.
Como esta investigação foi produzida
Os 47 documentos foram produzidos a 2026-07-31 por agentes independentes, cada um com instrução de não inventar citações e de marcar como [unverified] o que não pudesse confirmar contra uma fonte primária. A quota de pesquisa na web da sessão esgotou-se a meio e os agentes seguintes trabalharam por descarregamento directo de fontes primárias. Vários sítios (ftc.gov, ico.org.uk) bloqueiam o descarregamento automatizado, e por isso certas afirmações jurídicas estão marcadas de propósito.
Isto é investigação, não aconselhamento jurídico, médico ou financeiro. Nada aqui reivindica um resultado de aprendizagem do Math Challenge; esse estudo ainda não existe.
Capability matrix
| Funcionalidade | iOS Safari (instalada) | Chrome Android | Chrome/Edge de secretária | Safari de secretária | Conclusão |
|---|---|---|---|---|---|
| Install prompt | Apenas manual, sem beforeinstallprompt [1] | Automático, UI mais rica (descrição + capturas de ecrã) [1][7] | Ícone na omnibox, beforeinstallprompt [1][7] | Manual “Adicionar ao Dock” (Safari 17+), respeita shortcuts/categories [1] | É necessária UI personalizada de incentivo à instalação apenas para iOS |
| Web Push | 16,4+, instalação necessária, acionado por gesto, infra APNs, não requer conta de desenvolvedor [2] | Suporte total, sem barreira de instalação | Suporte total | Suporte total (Safari 16+) | O push não pode ser o único canal pré‑instalação no iOS |
| Badging API | Suportado para aplicações instaladas desde 16,4 [2] | Suportado | Suportado | Não verificado nesta passagem | Apenas sinal secundário de retenção |
| Background Sync | Não suportado (todas as versões do Safari) [21] | Suportado desde Chrome 49 [21] | Suportado (Chromium) [21] | Não suportado | Melhoria apenas em Chromium, nunca principal |
| Periodic Background Sync | Não suportado | Suportado; requer instalação + pontuação de envolvimento positiva, frequência não garantida [16] | Mesmas restrições | Não suportado | Apenas atualização de melhor esforço |
| Storage quota | ~60 % do disco após instalação (iOS17+); ~1 GiB legado pré-iOS17 [4] | ~60 % do disco [4] | ~60 % (Chromium); Firefox 10 %/50 % [4] | Mesmo que o navegador após instalação [4] | Suficiente para conjuntos de problemas + progresso |
| 7-day eviction | Aplica‑se ao armazenamento de script sem interação; aplicações instaladas isentas [4][5] | N/A | N/A | N/A | Instalar elimina o maior risco de perda de dados no iOS |
| OPFS | Base amplamente disponível desde março de 2023, incluindo Safari [17] | Suportado | Suportado | Suportado | Opção segura de BD local multiplataforma |
shortcuts/categories | macOS Safari 17.4+; iOS não verificado nesta passagem | Suportado (pressão longa) [general knowledge, not re‑verified] | Suportado | Suportado (17,4+) | Extra de baixo custo, verificar no dispositivo |
| Store wrapping | Capacitor (shell nativo) [11] | PWABuilder/Bubblewrap → TWA → Play [8][9] | PWABuilder → MS Store [10] | N/A | Duas ferramentas diferentes, não uma só |
Constatações
1. Installability and manifest fields. Critérios publicados pelo Chrome: HTTPS; manifesto com short_name/name, icons (192 px + 512 px), start_url, display em {fullscreen, standalone, minimal-ui, window-controls‑overlay}; prefer_related_applications ausente/falso; não estar já instalado; heurística de envolvimento (um toque mais ≥30 s na página) antes de o beforeinstallprompt ser disparado [7]. Notavelmente, um service worker registado não é um critério listado nesta orientação atual — uma mudança em relação a uma regra Chrome mais restrita anterior, que vale a pena reconfirmar através de uma auditoria “installable” ao vivo do Lighthouse antes do lançamento [7]. description/screenshots desbloqueiam a UI de instalação Android mais rica do Chrome [7]. shortcuts/categories são suportados no macOS Safari 17.4+ [WebKit 17,4 notes].
2. iOS Safari install reality. Nenhum prompt programático: a instalação é exclusivamente Partilhar → “Add to Home Screen” [1]. Desde o iOS 16.4 este caminho também está disponível a partir do Chrome/Edge/Firefox no iOS, todos obrigados a correr sobre o WebKit, pelo que a mecânica e as capacidades resultantes são idênticas independentemente de qual ícone de navegador a tenha iniciado [1]. O Math Challenge necessita de um tutorial explícito, ilustrado por capturas de ecrã, “como instalar” no iOS — isto controla push, badging e a isenção da evicção de 7 dias [1][2].
3. Web Push and Badging on iOS. Lançado no iOS/iPadOS 16.4 (fev 2023): requer instalação na Tela de Início com display: standalone/fullscreen; a permissão tem de seguir um gesto direto (por exemplo, um botão “Subscribe”); funciona sobre a infraestrutura própria da Apple (APNs) mantendo conformidade com a especificação; não necessita de adesão ao Apple Developer Program para enviar [2]. A Badging API foi lançada ao mesmo tempo para aplicações instaladas [2]. Nenhuma das duas funciona numa aba ou marcador normal — a instalação é uma barreira funcional rígida, não uma preferência.
4. Storage and the 7‑day eviction rule. Desde o macOS 14/iOS 17, as aplicações instaladas na Tela de Início obtêm o mesmo teto de disco de ~60 % que o navegador (contra ~15 % para WebViews incorporados, e uma quota legada pré‑iOS‑17 de ~1 GiB) [4]. O ITP elimina proactivamente o armazenamento gravável por script (IndexedDB, Cache API, Web Storage) após 7 dias sem interação, e exime as aplicações instaladas [4]. Uma nova recolha direta do blog da WebKit nesta sessão revelou apenas a variante de cookie de 2019 do limite de 7 dias (ITP 2,1) [5]; a versão mais ampla que afeta todo o armazenamento de script está corroborada aqui via MDN como fonte secundária, não re‑confirmada independentemente contra o post original da WebKit nesta passagem — sinalizada como lacuna de precisão, embora a isenção para instalações esteja declarada claramente [4]. Para utilizadores iOS não‑instalados, o progresso local não sincronizado corre risco de eliminação dentro de uma semana de inatividade.
5. The 2024 EU DMA episode. Antes do prazo do DMA, a beta do iOS 17.4 da Apple (fev 2024) degradou as aplicações web na Tela de Início a simples marcadores apenas na UE, alegando a carga de suportar motores não‑WebKit sob o DMA. A reação pública e de desenvolvedores (PCMag, iDownloadBlog, Mashable relataram a reversão) levou a Apple a restaurar a funcionalidade completa antes do lançamento geral de 1 de março 2024: “all Home Screen web apps will still be powered by WebKit, regardless of whether the web app is added using Safari or not” [6]. A reversão mantém‑se válida nesta passagem, baseada em imprensa de 2024 em vez de uma declaração Apple de 2026 — vale a pena uma verificação pontual antes do lançamento, dado o ritmo rápido desta mudança.
6. Android/Chrome: TWA, badging, shortcuts. O Chrome Android usa beforeinstallprompt mais UI de instalação mais rica [7]. Os mecanismos de geração do WebAPK não puderam ser re‑confirmados contra um documento Chrome ao vivo nesta sessão (ambos os URLs provavelmente devolvem 404) — tratados como contexto de fundo, não como afirmação re‑verificada. Confirmado diretamente: Trusted Web Activity requer Chrome 72+, Digital Asset Links para verificar a relação de confiança, e recorre a uma barra de ferramentas Custom Tab caso contrário [8].
7. Desktop install. Chrome/Edge: instalação completa baseada em manifesto via omnibox [7]. Safari macOS (17+): “Add to Dock” no menu Ficheiro, sem manifesto necessário mas respeita shortcuts/categories [WebKit 17,4 notes]. Firefox: sem instalação baseada em manifesto [1].
8. Offline strategy. Estratégias padrão: cache‑first, network‑first, stale‑while‑revalidate, network‑only, cache‑only — “the optimal caching strategy is dependent on the particular web app and how it is used” [18]. O Workbox pré‑cacheia uma lista de ativos definida no momento da instalação; o exemplo funcional da MDN mostra cache‑first com fallback de rede e uma página final offline [18][19]. Para uma aplicação de aprendizagem: pré‑cachear a shell da aplicação + página de fallback offline; cache‑first para conteúdo estático versionado (fontes, ícones, conjuntos de problemas agrupados); stale‑while‑revalidate/network‑first para tabelas de classificação, rachas, dados de sessão [18][19].
9. Syncing offline attempts, anti-cheat, leaderboards. Background Sync dispara uma única nova tentativa assim que a conectividade regressa, mas sob limites rígidos — ~30 s de timeout inativo, 30 s de limite de execução JS de sync, teto de 5 minutos para waitUntil(), após o qual o worker é terminado e reinicia na tentativa seguinte [19]. É apenas Chromium (não suportado em nenhuma versão do Safari) [21], e Periodic Background Sync requer ainda instalação mais uma pontuação de envolvimento positiva com frequência não garantida [16] — nenhum existe no iOS. O único mecanismo universalmente fiável é um flush acionado em primeiro‑plano: enfileirar tentativas em IndexedDB, descarregar em visibilitychange/focus/resume, com Background Sync sobreposto apenas como acelerador Android de melhor‑esforço. A MDN não prescreve resolução de conflitos além dos primitivos de retry/timeout [19] — o que se segue é o raciocínio de design próprio do Math Challenge, não uma afirmação fonte: nunca confiar num score calculado no cliente quando offline; sincronizar o registo bruto da resposta/tempo e fazer o servidor recomputar a correção e a elegibilidade para a tabela de classificação, eliminando o vetor óbvio de trapaça offline.
10. Local storage options. IndexedDB/Cache API partilham o pool de quota da §4. OPFS está disponível como Baseline amplamente desde março 2023 em navegadores evergreen, incluindo Safari, oferece acesso síncrono a nível de byte em Web Workers (útil para um banco de problemas empacotado ao estilo SQLite), partilha a mesma quota e limpa com o armazenamento do site [17]. localStorage/sessionStorage permanecem limitados a cerca de 5 MiB e são síncronos — apenas bandeiras pequenas, não dados da aplicação [4].
11. Performance budget on low‑end Android. RAIL: responder a input dentro de 100 ms (~50 ms de orçamento após trabalho ocioso), renderizar frames dentro de 10 ms (de um orçamento de 16 ms), fazer trabalho ocioso em blocos ≤50 ms, alcançar interatividade dentro de 5 s num dispositivo de gama média sobre 3G lento (referência: Moto G4, 400 ms RTT/400 kbps), carregamentos subsequentes abaixo de 2 s [20]. Isto delimita diretamente a carga útil de pré‑cache e o tamanho inicial do bundle.
12. Store wrapping and guideline 4.2. PWABuilder é “powered by Bubblewrap and uses the same underlying core” [9]; Bubblewrap (GoogleChromeLabs CLI) gera um projeto Android baseado em TWA para a Play Store [9]; PWABuilder pode também direcionar a Microsoft Store [10]. iOS necessita do Capacitor — um shell nativo real (Swift) com acesso genuíno a APIs nativas, não um WebView simples [11]. A diretriz 4.2 da Apple exige que as aplicações vão “beyond a repackaged website”, e a 4.2.2 proíbe explicitamente aplicações que sejam principalmente “web clippings, content aggregators, or a collection of links” [12]. A 4.2.6 impede templates de fábricas de apps a menos que submetidos diretamente pelo fornecedor de conteúdo — o que favorece o Math Challenge como proprietário de primeira mão [12]. Cumprir a 4,2 significa entregar capacidade nativa real dentro do shell (push nativo, partilha nativa, dados offline‑first), não apenas apontar um WebView para um URL.
13. Kids Category / Families — architecture‑independent. A Kids Category da Apple (diretrizes 1,3, 5.1.4) requer uma faixa etária, proíbe o envio de PII/informação do dispositivo a terceiros sem consentimento parental, exige anúncios revistos por humanos e adequados à idade se exibidos, requer portões parentais antes de ligações externas/IAP/prompt da loja, e Ask to Buy [13]. O Google Play Families requer igualmente conteúdo adequado à idade, proíbe apps apenas WebView que direcionem tráfego externo, restringe anúncios a SDKs Families Self‑Certified, proíbe anúncios baseados em interesses e a recolha de AAID/ localização precisa para apps só para crianças, e exige UX de segurança para funcionalidades sociais [14]. Nenhuma das políticas cria uma exceção para apps híbridos/PWA‑wrapped — ambas regulam comportamento e práticas de dados, não a pilha tecnológica [13][14].
Implicações de design
- Baseline do manifesto:
name,short_name,icons(192px + 512px + variante mascarável),start_url,display: "standalone",theme_color,background_color,description,screenshots— os dois últimos desbloqueiam a UI de instalação Android mais avançada do Chrome sem custo [7]. - Não dependa de
beforeinstallpromptem várias plataformas. Crie um percurso personalizado, guiado por capturas de ecrã, “Adicionar à Tela Inicial” para iOS como integração obrigatória — controla push, badging e a isenção de expulsão de 7 dias lá [1][2][4]. - Distribua um service worker independentemente da alteração do critério do Chrome. Pré‑cache do app shell + página de fallback offline; estratégia cache‑first para ativos estáticos versionados; stale‑while‑revalidate/network‑first para dados de leaderboard/sessão [7][18][19].
- Projete push para o limite inferior do iOS, não para o teto do Android. O push só funciona após a instalação com
display: standalone/fullscreen; coloque o pedido de permissão por detrás de uma mensagem de valor explícita e de um gesto deliberado [2]. - Considere “não instalado” como um estado distinto e de menor confiança no iOS. O progresso local não instalado corre risco de expulsão após 7 dias; trate as gravações desse grupo como efémeras e incentive ativamente a instalação em vez de acumular dados silenciosamente que podem desaparecer [4].
- A fila offline tem de ser acionada em primeiro‑plano em todo o lado. Enfileire tentativas no IndexedDB com uma chave de idempotência do cliente + timestamp do dispositivo; descarregue na ocorrência de
visibilitychange/focus/resume em todas as plataformas; aplique Background Sync apenas no Android como acelerador de boa‑fé, nunca como caminho dependente [15][16][19]. - Anti‑trapaça via recomputação no servidor. Nunca confie num pontuação calculada pelo cliente a partir de uma fila offline. Sincronize o registo bruto de respostas/eventos de temporização; o servidor recomputa a correção e a pontuação da leaderboard a partir desse registo — fechando o vetor de falsificação offline (raciocínio próprio do Math Challenge, não referenciado).
- Consistência da leaderboard: uma tentativa concluída offline é enviada como “pendente” até à revalidação no servidor, usando a chave de idempotência do ponto #6 para eliminar submissões duplicadas de ligações instáveis.
- Armazenamento de dados local: IndexedDB para dados estruturados (progresso, fila, conteúdo em cache), não
localStorage/sessionStorage(sincronização, capacidade ~5 MiB); considere OPFS apenas se for necessária uma BD incorporada mais pesada (por exemplo, banco de problemas wa-sqlite), pois está disponível como Baseline em grande parte dos navegadores, incluindo Safari [4][17]. - Orçamento de desempenho: interatividade dentro de 5 s num dispositivo Android de gama média em 3G lento, menos de 2 s em carregamentos repetidos, trabalho de animação dentro de um orçamento de 10 ms/quadro — limita tanto o tamanho do pacote como a carga do pré‑cache [20].
- Badging apenas como sinal secundário (“N desafios pendentes”), nunca como canal de notificação essencial, uma vez que o suporte do Safari de desktop não foi independentemente re‑verificado nesta passagem [2].
- Empacotamento para lojas é uma fase posterior, opcional, com duas ferramentas diferentes. Android: PWABuilder/Bubblewrap → TWA → Play Store com Digital Asset Links [8][9]. iOS: Capacitor com capacidades nativas reais (push nativo, partilha nativa, dados offline‑first) especificamente para cumprir a diretriz 4.2/4.2.2 — um WebView simples não passará a revisão [11][12].
- Projete para a Categoria Infantil/Famílias agora se essa posição for considerada: nenhum SDK de análise ou publicidade de terceiros a enviar dados pessoais de crianças sem consentimento, apenas redes de anúncios certificadas como seguras para crianças se houver anúncios, um portão parental antes de ligações externas/IAP/prompt da loja, e uma decisão explícita de faixa etária — nada disso é evitado ao permanecer PWA‑first [13][14].
- Re‑verifique o estado da DMA e a afirmação do critério do service‑worker próximo ao lançamento. Ambos são detalhes de política/implementação que já foram alterados (DMA revertida dentro de um mês em 2024; o Chrome eliminou a verificação anteriormente exigida do service worker) — uma auditoria Lighthouse pré‑lançamento e uma verificação dos termos atuais da UE da Apple são um seguro barato [6][7].
Questões abertas para o proprietário do projeto
- Para utilizadores de iOS que nunca instalam, é aceitável uma experiência local efémera (expulsão após 7 dias), ou o progresso guardado/leaderboards devem ser bloqueados rigidamente atrás da instalação?
- As tentativas sincronizadas offline devem ficar totalmente ocultas da leaderboard até à revalidação no servidor, ou mostrar uma pontuação provisória de “verificação pendente”?
- É realmente planeada uma posição na Categoria Infantil (Apple) / Families (Google Play), ou o público é mais amplo “estudantes + pais” — isto altera materialmente a lista curta de fornecedores de analytics/publicidade?
- Considerando a realidade de duas ferramentas diferentes para empacotamento (TWA para Android vs. Capacitor para iOS), a presença nas lojas é um item de roadmap a curto prazo que vale a pena arquitetar agora, ou deve ser totalmente adiada?
- A equipa deve reservar orçamento para uma passagem de verificação no dispositivo (iPhone real + Android de gama baixa) para confirmar os itens marcados como não verificados aqui — badging no Safari de desktop,
shortcuts/categoriesno iOS, estado atual da DMA/UE — antes de se comprometer com estas implicações?
Fontes
- MDN, "Making PWAs installable"
- WebKit Blog, "Web Push for Web Apps on iOS and iPadOS"
- Math Challenge internal research, topic 19 (habit loops/push) — docs/research/2026-07-31-mc-19-habit-loops-push-notifications.md
- MDN, "Storage quotas and eviction criteria"
- WebKit Blog, "Intelligent Tracking Prevention 2.1"
- Press coverage of Apple's March 2024 EU DMA reversal (PCMag, iDownloadBlog, Mashable), dated ~2024-03-01, retrieved via search snippet 2026-07-31 — not independently re-confirmed against a live Apple statement
- web.dev, "Installability criteria"
- Chrome Developers, "Trusted Web Activity"
- GitHub, GoogleChromeLabs/bubblewrap
- PWABuilder
- Capacitor documentation
- Apple, "App Store Review Guidelines" §4.2
- Apple Developer, "Kids Category"
- Google Play, Families policy requirements
- Caniuse, "Background Sync"
- Chrome Developers, "Periodic Background Sync"
- MDN, "Origin Private File System"
- web.dev, PWA course, "Workbox" chapter
- MDN, "Offline and background operation"
- web.dev, "The RAIL performance model"
- MDN, "Badging API" cross-checked against caniuse Background Sync table
Perguntas que este documento deixa em aberto
Ficam sem resposta de propósito. São listadas, não resolvidas — transformá-las numa FAQ exigiria inventar respostas que o documento não tem.
- For iOS users who never install, is an ephemeral (7-day-eviction) local experience acceptable, or should saved progress/leaderboards hard-gate behind installation?
- Should offline-synced attempts hide from the leaderboard entirely until server revalidation, or show a provisional "pending verification" score?
- Is a Kids Category (Apple) / Families (Google Play) positioning actually planned, or is the audience "students + parents" broadly — this changes the analytics/ads vendor shortlist materially?
- Given the two-different-tools reality for store wrapping (TWA for Android vs. Capacitor for iOS), is store presence a near-term roadmap item worth architecting for now, or fully deferred?
- Should the team budget an on-device verification pass (real iPhone + low-end Android) to confirm the items flagged unverified here — desktop Safari badging, iOS shortcuts/categories, current DMA/EU status — before committing to these implications?
Um de 51 documentos de investigação, 168 346 palavras no total, contadas na compilação a partir dos próprios ficheiros. Ler este documento no repositório