From 1bee838c8d7f39a8f882b54e9d758f4ac108e117 Mon Sep 17 00:00:00 2001 From: "Claude (Chronicler #83 - The Compiler)" Date: Tue, 14 Apr 2026 11:32:35 -0500 Subject: [PATCH] PWA Phase 1: manifest, service worker, icons, and static serving Adds manifest.json, sw.js (static-only caching, never admin routes), placeholder cyan T icons (192 + 512), express.static middleware, and PWA meta tags + service worker registration in layout.ejs. Co-Authored-By: Claude Opus 4.6 (1M context) --- services/arbiter-3.0/src/index.js | 4 +++ .../src/public/images/trinity-icon-192.png | Bin 0 -> 739 bytes .../src/public/images/trinity-icon-512.png | Bin 0 -> 3662 bytes services/arbiter-3.0/src/public/manifest.json | 24 ++++++++++++++++++ services/arbiter-3.0/src/public/sw.js | 21 +++++++++++++++ services/arbiter-3.0/src/views/layout.ejs | 15 +++++++++++ 6 files changed, 64 insertions(+) create mode 100644 services/arbiter-3.0/src/public/images/trinity-icon-192.png create mode 100644 services/arbiter-3.0/src/public/images/trinity-icon-512.png create mode 100644 services/arbiter-3.0/src/public/manifest.json create mode 100644 services/arbiter-3.0/src/public/sw.js diff --git a/services/arbiter-3.0/src/index.js b/services/arbiter-3.0/src/index.js index 5ccb2ca..65c17c2 100644 --- a/services/arbiter-3.0/src/index.js +++ b/services/arbiter-3.0/src/index.js @@ -8,6 +8,7 @@ const DiscordStrategy = require('passport-discord').Strategy; const { Client, GatewayIntentBits, REST, Routes } = require('discord.js'); const csrf = require('csurf'); const cors = require('cors'); +const path = require('path'); const { Pool } = require('pg'); const authRoutes = require('./routes/auth'); @@ -74,6 +75,9 @@ app.use((req, res, next) => { // Mounted at /webhooks/stripe to avoid conflict with /stripe checkout mount app.use('/webhooks/stripe', stripeRoutes); +// Static files (PWA manifest, icons, service worker) +app.use(express.static(path.join(__dirname, 'public'))); + // Body parsing middleware (comes AFTER webhook route) app.use(express.json()); app.use(express.urlencoded({ extended: true })); diff --git a/services/arbiter-3.0/src/public/images/trinity-icon-192.png b/services/arbiter-3.0/src/public/images/trinity-icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..326865ae7da822c4bc15988cea931e425e572e70 GIT binary patch literal 739 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE2}s`E_d9@rfoYYei(^Q|oVT|fbD13kSRD8B zDE%>H>11Se$$nB1yOy=!(v|OW_CYT`zGHu}nb||LVG0vfh*`{4|MuOH&flx=aGc)6 z`|x_5KT{_DD`sGv!o;ya#DQTc1Cs`;fP-cOgBK%90GC2T(5Mt;q48=p<4X1kK@6I# b)FSE~neA7xg-mz=OuP)9u6{1-oD!M literal 0 HcmV?d00001 diff --git a/services/arbiter-3.0/src/public/images/trinity-icon-512.png b/services/arbiter-3.0/src/public/images/trinity-icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d1166a39015c9cb58e58ba13177777b7bc4d1ec6 GIT binary patch literal 3662 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&t&wwUqN(1_nM+PZ!6KiaBquI_9z%2(TQi zW_9_IY@xy^B4Ha9p2_$l(YL;ivEtJ5I-nVh3>8xt7;L;4801tL82W`68r(S<4lHJ2 zco4|M@Ihl#nozKOtzxL#SATA2`uey9GZ?K8k3kV)H^

xI#}aUk0Vqx}-<^vC|szahLWNcP5jU_X(;)78&qol`;+0B!c*5C8xG literal 0 HcmV?d00001 diff --git a/services/arbiter-3.0/src/public/manifest.json b/services/arbiter-3.0/src/public/manifest.json new file mode 100644 index 0000000..55cea15 --- /dev/null +++ b/services/arbiter-3.0/src/public/manifest.json @@ -0,0 +1,24 @@ +{ + "name": "Trinity Console", + "short_name": "Trinity", + "description": "Firefrost Gaming Operations Console", + "start_url": "/admin", + "display": "standalone", + "background_color": "#1a1a1a", + "theme_color": "#06b6d4", + "orientation": "portrait-primary", + "icons": [ + { + "src": "/images/trinity-icon-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/images/trinity-icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ] +} diff --git a/services/arbiter-3.0/src/public/sw.js b/services/arbiter-3.0/src/public/sw.js new file mode 100644 index 0000000..52cb260 --- /dev/null +++ b/services/arbiter-3.0/src/public/sw.js @@ -0,0 +1,21 @@ +const CACHE_NAME = 'trinity-console-v1'; +const STATIC_ASSETS = [ + '/css/app.css', + '/manifest.json' +]; + +self.addEventListener('install', event => { + event.waitUntil( + caches.open(CACHE_NAME).then(cache => cache.addAll(STATIC_ASSETS)) + ); +}); + +self.addEventListener('fetch', event => { + // Only cache GET requests for static assets + if (event.request.method !== 'GET') return; + if (event.request.url.includes('/admin/')) return; // Never cache admin routes + + event.respondWith( + caches.match(event.request).then(cached => cached || fetch(event.request)) + ); +}); diff --git a/services/arbiter-3.0/src/views/layout.ejs b/services/arbiter-3.0/src/views/layout.ejs index 289e2fe..7901486 100644 --- a/services/arbiter-3.0/src/views/layout.ejs +++ b/services/arbiter-3.0/src/views/layout.ejs @@ -4,6 +4,21 @@ <%= title %> | Trinity Console + + + + + + + + +