feat(#34): PWA instalável com cache do shell para Android

- vite-plugin-pwa com Workbox (generateSW, autoUpdate)
- manifest.webmanifest: standalone, theme #0a0418, ícones 192/512
- Service worker pré-cacheia 29 entradas (shell completo offline)
- Google Fonts cacheadas via CacheFirst (1 ano)
- Ícone pixel art Arcade Neon (SVG + PNGs gerados)
- Meta tags PWA e apple-touch-icon no index.html

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
2026-05-27 11:57:56 -03:00
co-authored by Claude Sonnet 4.6
parent a8a4a76dd5
commit d20892977d
8 changed files with 4875 additions and 3 deletions
+7 -2
View File
@@ -2,8 +2,13 @@
<html lang="pt-BR"> <html lang="pt-BR">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/pwa-icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="#0a0418" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Financeiro" />
<title>Financeiro Carvalho</title> <title>Financeiro Carvalho</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 />
+4766
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -17,6 +17,7 @@
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^5.2.1",
"typescript": "^5.7.2", "typescript": "^5.7.2",
"vite": "^6.3.5", "vite": "^6.3.5",
"vite-plugin-pwa": "^1.3.0",
"vue-tsc": "^2.2.8" "vue-tsc": "^2.2.8"
} }
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

+41
View File
@@ -0,0 +1,41 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512">
<!-- Background: Arcade Neon dark purple -->
<rect width="512" height="512" rx="96" fill="#0a0418"/>
<!-- Coin glow (cyan outer ring) -->
<circle cx="256" cy="256" r="196" fill="none" stroke="#00f0ff" stroke-width="4" opacity="0.5"/>
<circle cx="256" cy="256" r="192" fill="none" stroke="#00f0ff" stroke-width="2" opacity="0.3"/>
<!-- Coin fill (gold) -->
<circle cx="256" cy="256" r="188" fill="#ffd84d"/>
<!-- Coin inner shadow ring -->
<circle cx="256" cy="256" r="188" fill="none" stroke="#a16207" stroke-width="8" opacity="0.4"/>
<!-- Pixel art "F" (dark on gold) — 32px pixel grid, 5×7, centered -->
<!-- Row 0: cols 04 (full top bar) -->
<rect x="176" y="144" width="32" height="32" fill="#150827"/>
<rect x="208" y="144" width="32" height="32" fill="#150827"/>
<rect x="240" y="144" width="32" height="32" fill="#150827"/>
<rect x="272" y="144" width="32" height="32" fill="#150827"/>
<rect x="304" y="144" width="32" height="32" fill="#150827"/>
<!-- Row 1: col 0 (left bar) -->
<rect x="176" y="176" width="32" height="32" fill="#150827"/>
<!-- Row 2: cols 03 (middle bar) -->
<rect x="176" y="208" width="32" height="32" fill="#150827"/>
<rect x="208" y="208" width="32" height="32" fill="#150827"/>
<rect x="240" y="208" width="32" height="32" fill="#150827"/>
<rect x="272" y="208" width="32" height="32" fill="#150827"/>
<!-- Row 36: col 0 (left bar continues) -->
<rect x="176" y="240" width="32" height="32" fill="#150827"/>
<rect x="176" y="272" width="32" height="32" fill="#150827"/>
<rect x="176" y="304" width="32" height="32" fill="#150827"/>
<rect x="176" y="336" width="32" height="32" fill="#150827"/>
<!-- Subtle cyan pixel accent dot (top-right of coin) -->
<rect x="374" y="116" width="8" height="8" fill="#00f0ff" opacity="0.8"/>
<rect x="382" y="108" width="8" height="8" fill="#00f0ff" opacity="0.5"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+60 -1
View File
@@ -1,9 +1,68 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'node:url' import { fileURLToPath, URL } from 'node:url'
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [
vue(),
VitePWA({
registerType: 'autoUpdate',
includeAssets: ['pwa-icon.svg', 'apple-touch-icon.png'],
manifest: {
name: 'Financeiro Carvalho',
short_name: 'Financeiro',
description: 'Controle financeiro pessoal — Arcade Neon',
theme_color: '#0a0418',
background_color: '#0a0418',
display: 'standalone',
orientation: 'portrait',
scope: '/',
start_url: '/',
icons: [
{
src: 'pwa-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
},
{
src: 'pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable',
},
],
},
workbox: {
globPatterns: ['**/*.{js,css,html,svg,png,woff2}'],
runtimeCaching: [
{
urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts-cache',
expiration: { maxEntries: 10, maxAgeSeconds: 60 * 60 * 24 * 365 },
cacheableResponse: { statuses: [0, 200] },
},
},
{
urlPattern: /^https:\/\/fonts\.gstatic\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'gstatic-fonts-cache',
expiration: { maxEntries: 10, maxAgeSeconds: 60 * 60 * 24 * 365 },
cacheableResponse: { statuses: [0, 200] },
},
},
],
},
}),
],
resolve: { resolve: {
alias: { alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)),