feat(pwa): manifest.json + ícone SVG marítimo pra instalar como app

- Endpoint Express /manifest.json com name/short_name/icons/theme
- /icon.svg vetorial (veleiro estilizado em paleta marítima)
- Links manifest + apple-touch-icon nos 2 HTMLs (app/ e server/public/)

Habilita:
- Android Chrome: 'Add to Home Screen' com ícone bonito
- iOS Safari: ícone na tela inicial
- PWABuilder: pode gerar APK Android sideload-ready

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
PontualTech / Karlão 2026-04-27 14:35:01 -03:00
parent 78c6de538a
commit 36ea8f006b
4 changed files with 36 additions and 0 deletions

View file

@ -8,6 +8,9 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="Diário de Bordo"> <meta name="apple-mobile-web-app-title" content="Diário de Bordo">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="manifest" href="/manifest.json">
<link rel="icon" type="image/svg+xml" href="/icon.svg">
<link rel="apple-touch-icon" href="/icon.svg">
<title>Diário de Bordo</title> <title>Diário de Bordo</title>
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

10
server/public/icon.svg Normal file
View file

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<rect width="512" height="512" rx="96" fill="#0e2a3d"/>
<g transform="translate(256 256)">
<path d="M -160 80 L 160 80 L 130 130 L -130 130 Z" fill="#a07832"/>
<path d="M 0 -180 L 0 70" stroke="#a07832" stroke-width="6" stroke-linecap="round"/>
<path d="M 0 -160 L 110 60 L 0 60 Z" fill="#efe5cd"/>
<path d="M 0 -160 L -90 50 L 0 50 Z" fill="#efe5cd" opacity="0.85"/>
</g>
<text x="256" y="450" font-family="Georgia, serif" font-style="italic" font-size="56" fill="#c89f54" text-anchor="middle">Shivao</text>
</svg>

After

Width:  |  Height:  |  Size: 603 B

View file

@ -8,6 +8,9 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="Diário de Bordo"> <meta name="apple-mobile-web-app-title" content="Diário de Bordo">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="manifest" href="/manifest.json">
<link rel="icon" type="image/svg+xml" href="/icon.svg">
<link rel="apple-touch-icon" href="/icon.svg">
<title>Diário de Bordo</title> <title>Diário de Bordo</title>
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

View file

@ -55,6 +55,26 @@ function requireAuth(req, res, next) {
// ==== Public endpoints ==== // ==== Public endpoints ====
app.get('/api/health', (req, res) => res.json({ ok: true, ts: Date.now() })); app.get('/api/health', (req, res) => res.json({ ok: true, ts: Date.now() }));
// PWA manifest (necessário pra "Add to Home Screen" + APK via PWABuilder)
app.get('/manifest.json', (req, res) => {
res.json({
name: 'Shivao · Diário de Bordo',
short_name: 'Shivao',
description: 'Diário de bordo do veleiro Shivao — viagens, manutenções, GPS, fundeio com alarme remoto',
start_url: '/',
display: 'standalone',
orientation: 'any',
background_color: '#0e2a3d',
theme_color: '#0e2a3d',
lang: 'pt-BR',
icons: [
{ src: '/icon.svg', sizes: 'any', type: 'image/svg+xml', purpose: 'any' },
{ src: '/icon.svg', sizes: 'any', type: 'image/svg+xml', purpose: 'maskable' }
],
categories: ['navigation', 'travel', 'productivity']
});
});
// ==== Static frontend ==== // ==== Static frontend ====
const publicDir = path.join(__dirname, '..', 'public'); const publicDir = path.join(__dirname, '..', 'public');
app.use(express.static(publicDir)); app.use(express.static(publicDir));