- web/static/manifest.webmanifest: name/short_name/start_url=/dashboard/ display=standalone/theme_color/background_color + three icons (192, 512, 512-maskable with ~12% safe-zone padding) - web/static/sw.js: minimal SW — install caches /static/* shell assets, fetch is network-first with cache fallback on GETs only, skips /mcp/ and non-GETs entirely. CACHE_NAME versioned for clean activate-time prune. - cmd/icongen: stdlib-only generator that produces the three PNG icons from a stylised "p" monogram. Run once at brand-change, commit output. - web.init() registers .webmanifest → application/manifest+json with mime.AddExtensionType so Chrome accepts the manifest at all - layout.tmpl + login.tmpl: manifest link, apple-touch-icon, theme-color, apple-mobile-web-app-* metas, inline SW-register on load (silent on failure — older browsers still work) - design.md gets §"PWA install (Phase 3j)"; CLAUDE.md "Out of scope" drops the Phase-3j line and adds push/background-sync as the remaining Otto-PWA territory - 4 new tests cover manifest MIME, sw.js delivery, all 3 icons, layout meta tags
47 lines
1.8 KiB
Cheetah
47 lines
1.8 KiB
Cheetah
{{define "layout"}}<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
<meta name="theme-color" content="#1a1a1a">
|
|
<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="projax">
|
|
<title>{{.Title}} — projax</title>
|
|
<link rel="manifest" href="/static/manifest.webmanifest">
|
|
<link rel="apple-touch-icon" href="/static/icon-192.png">
|
|
<link rel="icon" type="image/png" sizes="192x192" href="/static/icon-192.png">
|
|
<link rel="icon" type="image/png" sizes="512x512" href="/static/icon-512.png">
|
|
<link rel="stylesheet" href="/static/style.css">
|
|
<script src="https://unpkg.com/htmx.org@1.9.12" integrity="sha384-ujb1lZYygJmzgSwoxRggbCHcjc0rB2XoQrxeTUQyRjrOnlCoYta87iKBWq3EsdM2" crossorigin="anonymous"></script>
|
|
<script>
|
|
// Phase 3j — register the service worker post-load so the install
|
|
// affordance fires and shell assets warm into cache. Failures are silent
|
|
// (older browsers, http context, etc.) — projax must work without SW.
|
|
if ('serviceWorker' in navigator) {
|
|
window.addEventListener('load', function() {
|
|
navigator.serviceWorker.register('/static/sw.js').catch(function(){});
|
|
});
|
|
}
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<nav>
|
|
<a href="/" class="brand">projax</a>
|
|
<a href="/dashboard">dashboard</a>
|
|
<a href="/graph">graph</a>
|
|
<a href="/admin/classify">classify orphans</a>
|
|
<a href="/admin/bulk">bulk edit</a>
|
|
<a href="/admin/caldav">caldav</a>
|
|
<form method="post" action="/logout" class="logout-form">
|
|
<button type="submit" class="logout-btn">sign out</button>
|
|
</form>
|
|
</nav>
|
|
</header>
|
|
<main>
|
|
{{template "content" .}}
|
|
</main>
|
|
</body>
|
|
</html>{{end}}
|