# CONTRIBUTING — Guia para devs ## Setup inicial ### Requisitos - Node.js 20+ - npm - (Opcional) Docker para teste do build de produção ### Rodando o backend localmente ```bash cd server cp .env.example .env # Edite .env com seus valores (BOAT_TOKEN obrigatório) npm install npm start ``` Acesse `http://localhost:3000` Modo dev com auto-reload: ```bash npm run dev ``` ### Rodando o frontend localmente O HTML é standalone — pode abrir direto no navegador (`file:///...`), mas algumas APIs do navegador (Geolocation, Wake Lock, MediaRecorder) **só funcionam em HTTPS ou localhost**. Recomendado: deixar o backend servindo o frontend: ```bash cd server npm start # Acesse http://localhost:3000 — o backend serve public/index.html ``` Para iterar em mudanças do frontend: - Edite `app/diario-bordo.html` - Copie para `server/public/index.html` - Recarregue o navegador (sem necessidade de rebuild) Script de copy útil (para macOS/Linux): ```bash cp app/diario-bordo.html server/public/index.html ``` ### Testando com Docker ```bash cd server docker compose up --build ``` Para testar o pipeline completo de produção (igual Coolify faria). --- ## Estrutura do código ### `app/diario-bordo.html` Único arquivo HTML. Para navegar pelo código, use search: | Comentário | Função | |------------|--------| | `============ STORAGE ============` | Persistência local | | `============ GPS Math ============` | Haversine, conversões | | `============ GPS Tracking ============` | Rastreio de viagem | | `============ ANCHOR WATCH ============` | Vigia de fundeio | | `============ ALARM ============` | Sistema de alarme | | `============ CONTACTS ============` | Cadastro de contatos | | `============ CLOUD SYNC ============` | Integração com servidor | | `============ WEBHOOKS ============` | Telegram/Discord direto | | `============ GEOFENCING / ZONES ============` | Zonas de proibição/atenção | | `============ CHECKLISTS ============` | Listas de verificação | | `============ GPX EXPORT ============` | Export GPX | | `============ BATTERY SAVER ============` | Modo economia | | `============ WEATHER ============` | Windy + Open-Meteo | ### `server/src/` - `index.js` — entry point Express, todos os routes - `db.js` — wrapper SQLite com queries prepared - `notifications.js` — fan-out para todos os canais --- ## Convenções ### Estilo de código - **Sem build step no frontend** — escrevemos JS direto que roda no navegador. Cuidado com features muito recentes (target ≥ Chrome 100, Safari 16). - **Zero dependências runtime no frontend** exceto Leaflet e Google Fonts. - Variáveis curtas em código compacto (ex: `r` para response, `c` para content). Trade-off de legibilidade x tamanho do arquivo. ### CSS - Sistema de design baseado em variáveis CSS no `:root` - Tipografia: 3 famílias (Fraunces, Manrope, JetBrains Mono) - Paleta marítima editorial (ver ARCHITECTURE.md) - Mobile-first, com `@media (min-width:560px)` para desktop ### Backend - ESM modules (`"type": "module"`) - `async/await` em vez de promises encadeadas - Erros logados com `console.warn` ou `console.error` - Status HTTP semânticos: 200 ok, 400 bad input, 401 unauth, 404 not found, 500 server ### Commits e branches - `main` — sempre deployável - Features em branches `feat/...`, fixes em `fix/...` - PRs com descrição clara do que muda e por quê --- ## Como adicionar uma nova funcionalidade ### Exemplo: novo canal de notificação (Slack) 1. **Backend** — em `server/src/notifications.js`: ```js async function sendSlack(text) { const url = process.env.SLACK_WEBHOOK_URL; if (!url) return null; try { const r = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text }) }); return { ok: r.ok }; } catch (e) { return { ok: false, error: e.message }; } } ``` 2. Adicionar ao `dispatchAlarm()`: ```js const tasks = [ // ...existentes ['slack', sendSlack(text)] ]; ``` 3. Adicionar a `listConfiguredChannels()`: ```js if (env.SLACK_WEBHOOK_URL) channels.push('slack'); ``` 4. **Documentar** — adicionar `SLACK_WEBHOOK_URL=` no `.env.example` 5. **Testar** localmente: ```bash curl -X POST -H "Authorization: Bearer $TOKEN" \ http://localhost:3000/api/test ``` ### Exemplo: novo campo na viagem 1. **Frontend** — adicionar no modal de viagem (HTML) 2. Adicionar no `saveTrip()` — incluir no objeto data 3. Adicionar na renderização (`renderTrips`) 4. **Backup compatibility**: viagens antigas não terão o campo, lembre de tratar `undefined` graciosamente Não precisa mudar o backend — a API guarda JSON arbitrário em `state.data`. --- ## Debugging ### Frontend Abrir DevTools no Chrome (F12 ou ⌥⌘I). Console mostra: - `[zone]` ao entrar/sair de zona - `[deadman]` no servidor (acessível via `docker logs`) - Erros de fetch sem CORS são típicos quando se acessa `file://` em vez de `http://localhost` Application tab: - `Local Storage` — ver todo o estado - `IndexedDB > diario_bordo_db > media` — ver mídias ### Backend ```bash # Logs em produção docker logs # Em dev, vê no terminal direto # Testar endpoint manualmente curl -H "Authorization: Bearer abc..." http://localhost:3000/api/info ``` SQLite — abrir o `.db` direto: ```bash sqlite3 server/data/shivao.db > .tables > SELECT * FROM alarm_log ORDER BY ts DESC LIMIT 10; ``` --- ## Releases Atualmente não há versionamento formal. Sugestão para o time: 1. Adicionar `version` em `package.json` 2. Tags Git para releases (`v1.0.0`) 3. Changelog (`CHANGELOG.md`) com mudanças por versão 4. Coolify: configurar para deploy automático apenas em tags (não em todo push) --- ## Boas práticas para o app de barco Coisas a manter em mente ao desenvolver: 1. **Conectividade incerta**: o app é usado em alto-mar. Falhas de rede são normais. Tudo deve degradar graciosamente. 2. **Bateria é crítica**: cada feature que ativa GPS/CPU contínuo precisa ser justificada. Sempre considerar o impacto em bateria. 3. **Tela ao sol**: contraste alto, fontes grandes. A paleta atual já é bem legível ao sol. 4. **Mãos molhadas**: tap targets grandes (mínimo 44x44 px). 5. **Sob estresse**: alarmes, MOB, etc. devem ter UX MUITO simples — botões óbvios, pouco texto, ações irreversíveis sempre com confirmação. 6. **Dados são preciosos**: nunca apagar sem dupla confirmação. Backup é fácil (aba Arquivo). 7. **Single-handed sailing**: capitão pode estar sozinho no leme. Operação com uma mão deve ser viável onde possível.