# Progressive Web App (PWA) Guide (Português (Brasil)) 🌐 **Languages:** 🇺🇸 [English](../../../../guides/PWA_GUIDE.md) · 🇪🇹 [am](../../../am/docs/guides/PWA_GUIDE.md) · 🇸🇦 [ar](../../../ar/docs/guides/PWA_GUIDE.md) · 🇦🇿 [az](../../../az/docs/guides/PWA_GUIDE.md) · 🇧🇬 [bg](../../../bg/docs/guides/PWA_GUIDE.md) · 🇧🇩 [bn](../../../bn/docs/guides/PWA_GUIDE.md) · 🇧🇦 [bs](../../../bs/docs/guides/PWA_GUIDE.md) · 🇨🇿 [cs](../../../cs/docs/guides/PWA_GUIDE.md) · 🇩🇰 [da](../../../da/docs/guides/PWA_GUIDE.md) · 🇩🇪 [de](../../../de/docs/guides/PWA_GUIDE.md) · 🇬🇷 [el](../../../el/docs/guides/PWA_GUIDE.md) · 🇪🇸 [es](../../../es/docs/guides/PWA_GUIDE.md) · 🇪🇪 [et](../../../et/docs/guides/PWA_GUIDE.md) · 🇮🇷 [fa](../../../fa/docs/guides/PWA_GUIDE.md) · 🇫🇮 [fi](../../../fi/docs/guides/PWA_GUIDE.md) · 🇫🇷 [fr](../../../fr/docs/guides/PWA_GUIDE.md) · 🇮🇪 [ga](../../../ga/docs/guides/PWA_GUIDE.md) · 🇮🇳 [gu](../../../gu/docs/guides/PWA_GUIDE.md) · 🇳🇬 [ha](../../../ha/docs/guides/PWA_GUIDE.md) · 🇮🇱 [he](../../../he/docs/guides/PWA_GUIDE.md) · 🇮🇳 [hi](../../../hi/docs/guides/PWA_GUIDE.md) · 🇭🇷 [hr](../../../hr/docs/guides/PWA_GUIDE.md) · 🇭🇺 [hu](../../../hu/docs/guides/PWA_GUIDE.md) · 🇦🇲 [hy](../../../hy/docs/guides/PWA_GUIDE.md) · 🇮🇩 [id](../../../id/docs/guides/PWA_GUIDE.md) · 🇳🇬 [ig](../../../ig/docs/guides/PWA_GUIDE.md) · 🇮🇹 [it](../../../it/docs/guides/PWA_GUIDE.md) · 🇯🇵 [ja](../../../ja/docs/guides/PWA_GUIDE.md) · 🇬🇪 [ka](../../../ka/docs/guides/PWA_GUIDE.md) · 🇰🇭 [km](../../../km/docs/guides/PWA_GUIDE.md) · 🇮🇳 [kn](../../../kn/docs/guides/PWA_GUIDE.md) · 🇰🇷 [ko](../../../ko/docs/guides/PWA_GUIDE.md) · 🇱🇹 [lt](../../../lt/docs/guides/PWA_GUIDE.md) · 🇱🇻 [lv](../../../lv/docs/guides/PWA_GUIDE.md) · 🇮🇳 [ml](../../../ml/docs/guides/PWA_GUIDE.md) · 🇮🇳 [mr](../../../mr/docs/guides/PWA_GUIDE.md) · 🇲🇾 [ms](../../../ms/docs/guides/PWA_GUIDE.md) · 🇲🇹 [mt](../../../mt/docs/guides/PWA_GUIDE.md) · 🇲🇲 [my](../../../my/docs/guides/PWA_GUIDE.md) · 🇳🇵 [ne](../../../ne/docs/guides/PWA_GUIDE.md) · 🇳🇱 [nl](../../../nl/docs/guides/PWA_GUIDE.md) · 🇳🇴 [no](../../../no/docs/guides/PWA_GUIDE.md) · 🇮🇳 [or](../../../or/docs/guides/PWA_GUIDE.md) · 🇮🇳 [pa](../../../pa/docs/guides/PWA_GUIDE.md) · 🇵🇭 [phi](../../../phi/docs/guides/PWA_GUIDE.md) · 🇵🇱 [pl](../../../pl/docs/guides/PWA_GUIDE.md) · 🇵🇹 [pt](../../../pt/docs/guides/PWA_GUIDE.md) · 🇷🇴 [ro](../../../ro/docs/guides/PWA_GUIDE.md) · 🇷🇺 [ru](../../../ru/docs/guides/PWA_GUIDE.md) · 🇱🇰 [si](../../../si/docs/guides/PWA_GUIDE.md) · 🇸🇰 [sk](../../../sk/docs/guides/PWA_GUIDE.md) · 🇸🇮 [sl](../../../sl/docs/guides/PWA_GUIDE.md) · 🇷🇸 [sr](../../../sr/docs/guides/PWA_GUIDE.md) · 🇸🇪 [sv](../../../sv/docs/guides/PWA_GUIDE.md) · 🇰🇪 [sw](../../../sw/docs/guides/PWA_GUIDE.md) · 🇮🇳 [ta](../../../ta/docs/guides/PWA_GUIDE.md) · 🇮🇳 [te](../../../te/docs/guides/PWA_GUIDE.md) · 🇹🇭 [th](../../../th/docs/guides/PWA_GUIDE.md) · 🇹🇷 [tr](../../../tr/docs/guides/PWA_GUIDE.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/guides/PWA_GUIDE.md) · 🇵🇰 [ur](../../../ur/docs/guides/PWA_GUIDE.md) · 🇺🇿 [uz](../../../uz/docs/guides/PWA_GUIDE.md) · 🇻🇳 [vi](../../../vi/docs/guides/PWA_GUIDE.md) · 🇳🇬 [yo](../../../yo/docs/guides/PWA_GUIDE.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/guides/PWA_GUIDE.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/guides/PWA_GUIDE.md) --- O OmniRoute é fornecido como um Progressive Web App totalmente instalável. Ao acessar o dashboard por qualquer navegador móvel — Android (Chrome) ou iOS (Safari) — você pode usar a opção "Adicionar à tela inicial" e obter uma experiência semelhante à de um aplicativo nativo, sem precisar de uma loja de aplicativos. ## O que é um PWA? Um Progressive Web App transforma o dashboard web do OmniRoute em algo com a aparência e a experiência de um aplicativo móvel nativo. Depois de instalado, ele: - É iniciado pela tela inicial com seu próprio ícone - É aberto em tela cheia — sem barra de endereços ou interface de abas do navegador - Funciona offline com uma página dedicada de conectividade - Armazena recursos estáticos em cache para um carregamento mais rápido - Oferece suporte às orientações retrato e paisagem ## Instalação ### Android (Chrome) 1. Abra o dashboard do OmniRoute no Chrome: `http://YOUR_IP:20128` 2. O Chrome exibirá automaticamente um banner **"Adicionar o OmniRoute à tela inicial"** ou: - Toque no menu **⋮** (três pontos) → **"Adicionar à tela inicial"** ou **"Instalar aplicativo"** 3. Confirme a solicitação 4. O OmniRoute aparecerá na tela inicial como um aplicativo independente ### iOS (Safari) 1. Abra o dashboard do OmniRoute no Safari: `http://YOUR_IP:20128` 2. Toque no botão **Compartilhar** (caixa com uma seta) 3. Role para baixo e toque em **"Adicionar à Tela de Início"** 4. Dê um nome a ele (o padrão é "OmniRoute") e toque em **Adicionar** 5. O OmniRoute aparecerá na tela inicial com o ícone do aplicativo ### Desktop (Chrome / Edge) 1. Abra o dashboard do OmniRoute 2. Clique no **ícone de instalação** na barra de endereços (ou ⋮ → "Instalar OmniRoute...") 3. Confirme a solicitação 4. O OmniRoute será aberto em uma janela independente — sem abas e sem barra de endereços ## Recursos ### Experiência em tela cheia O manifesto está configurado com `display: "fullscreen"`, o que significa que o aplicativo instalado usa a tela inteira — sem interface do navegador e sem sobreposição da barra de status. Isso faz com que o dashboard realmente pareça nativo. ### Suporte offline O OmniRoute inclui um service worker (`sw.js`) que fornece armazenamento inteligente em cache: | Tipo de recurso | Estratégia | Comportamento | | ------------------------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------- | | **Shell do aplicativo** | Cache primeiro | `/`, `/offline`, o manifesto e os ícones são pré-armazenados em cache durante a instalação | | **Recursos estáticos** (CSS, JS, imagens, fontes) | Rede primeiro, com fallback para o cache | Busca a versão mais recente na rede; usa o cache como fallback se estiver offline | | **Bundles do Next.js** (`/_next/`) | Rede primeiro, com atualização do cache | Busca na rede e atualiza o cache; fornece a versão em cache se estiver offline | | **Solicitações de navegação** | Ignorar (nunca interceptadas) | O navegador gerencia o fallback de HTTP/3→HTTP/2; um socket QUIC inativo não deve se tornar `Response.error()` | | **Rotas da API/do dashboard** (`/api/`, `/a2a`, `/dashboard`) | Ignorar (nunca armazenadas em cache) | Sempre vão diretamente para o servidor — nunca são interceptadas pelo service worker | ### Página offline Quando a rede está indisponível e um usuário navega para uma nova página, o service worker fornece uma página dedicada em `/offline` que: - Exibe uma mensagem clara de **"Problema de conectividade"** - Mostra um **indicador de status online/offline em tempo real** que é atualizado instantaneamente - Fornece um botão **"Tentar conexão novamente"** para recarregar quando a conectividade retornar - Inclui um link para a **Página de status** para diagnóstico ### Ícones do aplicativo O OmniRoute fornece ícones otimizados para cada plataforma: | Arquivo | Tamanho | Usado por | | ---------------------- | --------------- | ------------------------------------------------------ | | `icon-512.png` | 512×512 | Solicitação de instalação do Android, tela de abertura | | `apple-touch-icon.png` | 180×180 | Ícone da tela inicial do iOS | | `icon-192.svg` | 192×192 (vetor) | Ícone adaptável do Android | | `apple-touch-icon.svg` | 180×180 (vetor) | Fallback da Apple | | `favicon.svg` | Vetor | Abas do navegador | | `favicon.ico` | Vários tamanhos | Navegadores antigos | ### Registro automático O service worker é registrado automaticamente por meio do componente `` no layout raiz. Nenhuma ação do usuário é necessária — o aplicativo se torna instalável assim que o navegador detecta o manifesto e o service worker válidos. ## Arquitetura técnica ### Manifesto do aplicativo Web (`manifest.webmanifest`) Gerado pelo Next.js por meio de `src/app/manifest.ts`: ```json { "name": "OmniRoute", "short_name": "OmniRoute", "description": "OmniRoute is an AI gateway for multi-provider LLMs. One endpoint for all your AI providers.", "start_url": "/", "scope": "/", "display": "fullscreen", "orientation": "any", "background_color": "#0b0f1a", "theme_color": "#0b0f1a", "icons": [ { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }, { "src": "/apple-touch-icon.png", "sizes": "180x180", "type": "image/png" } ] } ``` ### Service Worker (`public/sw.js`) Um service worker básico (sem dependências de frameworks) com: - **Fase de instalação**: Armazena previamente em cache o shell do aplicativo (raiz, página offline, manifesto e ícones) - **Fase de ativação**: Remove versões antigas do cache e assume o controle de todos os clientes - **Fase de busca**: Roteamento inteligente com base no tipo de requisição (navegação, recurso estático ou API) - **Versionamento do cache**: `omniroute-pwa-v3` — incremente esse valor para forçar um novo cache após uma atualização ### Metadados do layout (`src/app/layout.tsx`) O layout raiz fornece todas as metatags necessárias para a conformidade com PWA: - Link `manifest` para `/manifest.webmanifest` - `apple-web-app-capable: true` para o modo independente no iOS - `apple-web-app-status-bar-style: black-translucent` - `mobile-web-app-capable: yes` para o Chrome no Android - `theme-color: #0b0f1a` - `viewport-fit: cover` para renderização de ponta a ponta ### Componente: `PwaRegister` Localizado em `src/shared/components/PwaRegister.tsx`, este componente cliente: 1. É executado durante a montagem (somente no lado do cliente) 2. Verifica se o navegador oferece suporte a `serviceWorker` 3. Registra `/sw.js` silenciosamente (os erros são ignorados para evitar o bloqueio do aplicativo) 4. Não renderiza nada (`return null`) — é um componente usado apenas para efeitos colaterais ## Uso com o Termux (Android) Ao executar o OmniRoute no Android por meio do Termux, o PWA funciona perfeitamente: 1. Inicie o OmniRoute no Termux: `npx omniroute` 2. Abra o Chrome no mesmo celular: `http://localhost:20128` 3. Instale o PWA por meio da opção "Adicionar à tela inicial" 4. O PWA se conecta ao servidor local do Termux — tudo é executado no dispositivo Essa combinação significa que seu celular Android é tanto o **servidor** (Termux) quanto o **cliente** (PWA) — um gateway de IA completo e autossuficiente. ## Uso em outros dispositivos Instale o PWA em qualquer dispositivo cujo navegador tenha acesso ao seu servidor OmniRoute: - **Outro celular/tablet**: Acesse `http://PHONE_IP:20128` e instale o PWA - **Notebook**: Abra o Chrome/Edge e instale-o como um PWA para desktop - **Smart TV com navegador**: Acesse o painel em tela cheia ## Personalização ### Nome da instância O título do PWA respeita a configuração de **Nome da instância** em `Painel → Configurações`. Se você renomear sua instância para "Meu gateway de IA", o PWA instalado exibirá esse nome. ### Favicon personalizado Se você enviar um favicon personalizado por meio de `Painel → Configurações`, o ícone do PWA no desktop refletirá o ícone personalizado. Os ícones da tela inicial em dispositivos móveis usam os arquivos predefinidos `icon-512.png` e `apple-touch-icon.png`. ## Limitações - **Sem notificações push** — O service worker não implementa a Push API. Em vez disso, as notificações são gerenciadas pelo aplicativo Electron. - **Sem sincronização em segundo plano** — As ações offline não são enfileiradas para serem repetidas. O PWA serve principalmente para visualização do dashboard. - **Restrições do iOS** — O Safari no iOS não oferece suporte a todos os recursos de PWA (por exemplo, os prompts de instalação são manuais e os service workers em segundo plano são limitados). - **Tamanho do cache** — O service worker armazena em cache apenas recursos estáticos. Payloads de resposta grandes provenientes de rotas `/api/` nunca são armazenados em cache. - **Ícones personalizados em dispositivos móveis** — Alterar o favicon nas configurações não atualiza o ícone da tela inicial em dispositivos móveis (isso exige gerar novamente os ícones do PWA). ## Referência de arquivos | Arquivo | Finalidade | | --------------------------------------- | ------------------------------------------------------------------ | | `src/app/manifest.ts` | Rota de manifesto do Next.js (gera `manifest.webmanifest`) | | `public/sw.js` | Service worker com lógica de cache | | `src/shared/components/PwaRegister.tsx` | Componente cliente que registra o service worker | | `src/app/offline/page.tsx` | Página alternativa offline com indicador de status em tempo real | | `src/app/layout.tsx` | Layout raiz com metadados de PWA (apple-web-app, theme-color etc.) | | `public/icon-512.png` | Ícone PNG de 512×512 (Android, tela de inicialização) | | `public/apple-touch-icon.png` | Ícone PNG de 180×180 (tela inicial do iOS) | | `public/icon-192.svg` | Ícone SVG de 192×192 (ícone adaptativo do Android) | | `public/apple-touch-icon.svg` | Ícone SVG de 180×180 (alternativa para dispositivos Apple) |