export function parseOrgIdFromCookie(cookieHeader: string | null): number | null { if (!cookieHeader) return null; const match = cookieHeader.match(/(?:^|;\s*)x-org-id=(\d+)/); if (!match) return null; const id = Number.parseInt(match[1], 10); return Number.isNaN(id) ? null : id; } interface ManifestIcon { src: string; sizes: string; type: string; purpose?: string; } interface WebAppManifest { name: string; short_name: string; description: string; start_url: string; display: string; orientation: string; theme_color: string; background_color: string; icons: ManifestIcon[]; } const ASSETS_BASE_URL = "https://assets.xtablo.com"; export function buildManifest(orgId: number | null): WebAppManifest { const base = { name: "XTablo", short_name: "XTablo", description: "Collaborative project management for construction teams", start_url: "/", display: "standalone", orientation: "any", theme_color: "#1e1b2e", background_color: "#1e1b2e", }; if (orgId !== null) { return { ...base, icons: [ { src: `${ASSETS_BASE_URL}/org-icons/${orgId}/icon-192.png`, sizes: "192x192", type: "image/png" }, { src: `${ASSETS_BASE_URL}/org-icons/${orgId}/icon-512.png`, sizes: "512x512", type: "image/png" }, { src: `${ASSETS_BASE_URL}/org-icons/${orgId}/icon-512-maskable.png`, sizes: "512x512", type: "image/png", purpose: "maskable" }, ], }; } return { ...base, icons: [ { src: "/pwa-icons/pwa-192x192.png", sizes: "192x192", type: "image/png" }, { src: "/pwa-icons/pwa-512x512.png", sizes: "512x512", type: "image/png" }, { src: "/pwa-icons/pwa-512x512-maskable.png", sizes: "512x512", type: "image/png", purpose: "maskable" }, ], }; } export default { fetch(request: Request) { const url = new URL(request.url); // Serve org-specific or default PWA icons // Static files are renamed to default-* so the worker handles all requests for these paths const iconMap: Record = { "/pwa-icons/apple-touch-icon-180x180.png": { orgFile: "icon-180.png", defaultFile: "/pwa-icons/default-apple-touch-icon-180x180.png" }, "/pwa-icons/favicon-32x32.png": { orgFile: "icon-32.png", defaultFile: "/pwa-icons/default-favicon-32x32.png" }, "/pwa-icons/favicon-16x16.png": { orgFile: "icon-16.png", defaultFile: "/pwa-icons/default-favicon-16x16.png" }, }; if (iconMap[url.pathname]) { const cookieHeader = request.headers.get("cookie"); const orgId = parseOrgIdFromCookie(cookieHeader); const entry = iconMap[url.pathname]; if (orgId !== null) { return Response.redirect(`${ASSETS_BASE_URL}/org-icons/${orgId}/${entry.orgFile}`, 302); } // No cookie — serve default icon return Response.redirect(`${url.origin}${entry.defaultFile}`, 302); } if (url.pathname === "/manifest.webmanifest") { const cookieHeader = request.headers.get("cookie"); const orgId = parseOrgIdFromCookie(cookieHeader); const manifest = buildManifest(orgId); return new Response(JSON.stringify(manifest), { headers: { "Content-Type": "application/manifest+json", "Cache-Control": "no-cache", }, }); } if (url.pathname.startsWith("/api/")) { return Response.json({ name: "Cloudflare" }); } return new Response(null, { status: 404 }); }, };