# Web (TeaVM/WebGL) e suas limitações reais

> O app compilado para JS via TeaVM rodando em canvas WebGL2 — e o que NÃO funciona.

Source: https://crossfly.dev/pt/docs/platforms/web-teavm — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Web (TeaVM/WebGL) 🌐

**A página mais honesta da seção.** O alvo web (módulo `web`, `WebLauncher`) compila o app para
**JavaScript via TeaVM** e o roda num `<canvas>` **WebGL2** (backend `gdx-teavm`). **Não é GWT** e
**não** é um webview embutido: é o **próprio app** rodando no navegador.

## Build e servir
```bash
gradlew :web:webBundle       # (alias: dist)
```
Gera `web/build/webapp/` com `index.html`, `web.js`, `scripts/howler.js`, `gdx.wasm.js`, e
`assets/` + `assets.txt`. Sirva localmente:
```bash
cd web/build/webapp && python -m http.server 8080
# abra http://127.0.0.1:8080/index.html
```
O `WebLauncher` faz `new TeaApplication(new Main(true, cmdline), config)`.

## ⚠️ O que NÃO funciona (é *stub*)
No web, `PlatformUtilsWeb` implementa a maioria dos recursos como *stub* — a chamada existe mas **não
faz nada útil**:
| Recurso | Comportamento no web |
|---|---|
| `WebContainer` | `createWebView()` retorna **`null`** |
| GPS / localização | *stub* (sem fix) |
| Bluetooth / rádios | *stub* (`WirelessState.UNSUPPORTED`) |
| Biometria | `AuthResult.ERROR` "Not supported" |
| Voz (TTS/STT) | `voiceToText` → `onError` |
| Mapas nativos | não suportado |
| Vibração / bateria | *stub* |
| **Persistência de arquivos** | `Device.homeFolder = null` |

> Como `crossfly-lib` (JNI) **não é carregada no WebGL** (`Main.create()` pula o `SharedLibraryLoader`
> no alvo WebGL), tudo que depende de nativo cai para os *stubs* acima.

## O que FUNCIONA
- **Renderizar a UI** completa (é o app real no canvas WebGL2).
- **Abrir URL externa / discar**: `PlatformUtils.instance.view(url)` / `dial(numero)` (via
  `Gdx.net.openURI`).
- HTTP com **restrições** (CORS; `Utils.getRemoteFile` retorna `null` em falha).

## Padrão obrigatório: detecte e caia para o fallback
```java
if (PlatformUtils.instance.createWebView() != null) {
   // Android/iOS/Desktop: webview embutido
} else {
   PlatformUtils.instance.view(url);   // Web: abre em nova aba
}
```
E cheque `Device.homeFolder == null` antes de tentar persistir arquivo no web.

## Boas práticas
- **Desabilite/adapte** recursos de dispositivo no web (não deixe botões que não fazem nada).
- Persistência no web: use o que estiver disponível no seu build (não conte com `homeFolder`).
- Teste servindo o bundle estático localmente antes de hospedar.

## Erros comuns
- Assumir `WebContainer`/GPS/biometria no web (são *stub*).
- Tentar `Device.homeFolder + "arquivo"` no web (`homeFolder` é `null` → NPE).

## Veja também
- [Integração nativa](/docs/platforms/native-integration) · [Matriz de plataformas](/docs/platforms/overview)
