commit 458cc49d19fdca325c0a623df43edfee1083f6e1 Author: posimai Date: Fri Apr 3 00:55:31 2026 +0900 init: posimai log — AI駆動開発の軌跡ビューワー diff --git a/index.html b/index.html new file mode 100644 index 0000000..ca3339c --- /dev/null +++ b/index.html @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + posimai log + + + + + + + + + + + + + + + + +
+
+
+ + posimai log +
+ +
+ +
+ + + + +
+
+ + select a log entry +
+ +
+
+
+ +
+ + + + + diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..13fcd40 --- /dev/null +++ b/manifest.json @@ -0,0 +1,17 @@ +{ + "id": "/posimai-log/", + "name": "posimai log", + "short_name": "log", + "description": "Architect without Code — AI駆動開発の軌跡", + "start_url": "/", + "display": "standalone", + "display_override": ["window-controls-overlay", "standalone"], + "background_color": "#0D0D0D", + "theme_color": "#0D0D0D", + "orientation": "portrait-primary", + "categories": ["productivity"], + "icons": [ + { "src": "/logo.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, + { "src": "/logo.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" } + ] +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8390dca --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "posimai-log", + "version": "1.0.0", + "description": "Architect without Code — AI駆動開発の軌跡", + "private": true, + "scripts": { + "deploy": "git push gitea main && git push github main" + } +} diff --git a/posts/index.json b/posts/index.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/posts/index.json @@ -0,0 +1 @@ +[] diff --git a/sw.js b/sw.js new file mode 100644 index 0000000..10aaf80 --- /dev/null +++ b/sw.js @@ -0,0 +1,44 @@ +// Posimai Log SW — stale-while-revalidate for static, network-first for posts +const CACHE = 'posimai-log-v1'; +const STATIC = ['/', '/index.html', '/manifest.json', '/logo.png']; + +self.addEventListener('install', e => { + e.waitUntil( + caches.open(CACHE).then(c => c.addAll(STATIC)) + ); +}); + +self.addEventListener('activate', e => { + e.waitUntil( + caches.keys().then(keys => + Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k))) + ).then(() => self.clients.claim()) + ); +}); + +self.addEventListener('fetch', e => { + if (e.request.method !== 'GET') return; + const url = e.request.url; + if (!url.startsWith(self.location.origin)) return; + + // posts/ → network-first (content changes on every deploy) + if (url.includes('/posts/')) { + e.respondWith( + fetch(e.request).catch(() => caches.match(e.request)) + ); + return; + } + + // static assets → stale-while-revalidate + e.respondWith( + caches.open(CACHE).then(cache => + cache.match(e.request).then(cached => { + const network = fetch(e.request).then(res => { + if (res.ok && res.type === 'basic') cache.put(e.request, res.clone()); + return res; + }).catch(() => cached); + return cached || network; + }) + ) + ); +});