feat: add GitHub Actions CI and support hosting under a subpath
Mirrors the GitLab pipeline — typecheck, tests, feed sanity — and adds a Pages deploy. Pages serves from /<repo>/, and the app used absolute asset paths, so that job would have shipped a site that 404s on everything. Assets now resolve against a <base href> the build substitutes, the feed URL resolves against document.baseURI so deep links work too, and the service worker derives its paths from its own registration scope. Root-hosted builds are unchanged. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
517066dc65
commit
b86794a62d
+4
-1
@@ -13,7 +13,10 @@ export type FeedState =
|
||||
* worse than one that asks you to reload.
|
||||
*/
|
||||
export async function fetchFeed(signal?: AbortSignal): Promise<EventFeed> {
|
||||
const res = await fetch("/data/events.v1.json", { signal: signal ?? null });
|
||||
// Resolved against <base>, so this is correct at a domain root, under a
|
||||
// GitHub Pages subpath, and on a deep link alike.
|
||||
const feedUrl = new URL("data/events.v1.json", document.baseURI);
|
||||
const res = await fetch(feedUrl, { signal: signal ?? null });
|
||||
if (!res.ok) {
|
||||
throw new Error(`Feed request failed (${res.status}).`);
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,7 +15,8 @@ createRoot(root).render(
|
||||
// guarded because file:// and older browsers have no service worker at all.
|
||||
if ("serviceWorker" in navigator && location.protocol.startsWith("http")) {
|
||||
window.addEventListener("load", () => {
|
||||
void navigator.serviceWorker.register("/sw.js").catch(() => {
|
||||
const swUrl = new URL("sw.js", document.baseURI);
|
||||
void navigator.serviceWorker.register(swUrl).catch(() => {
|
||||
// An unavailable worker costs offline support, nothing else. The app
|
||||
// works exactly as before.
|
||||
});
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
"name": "Event Clock",
|
||||
"short_name": "Event Clock",
|
||||
"description": "Live and upcoming gacha events, sorted by what expires next.",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"start_url": "./",
|
||||
"scope": "./",
|
||||
"display": "standalone",
|
||||
"background_color": "#12141c",
|
||||
"theme_color": "#12141c",
|
||||
"orientation": "portrait-primary",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icon.svg",
|
||||
"src": "icon.svg",
|
||||
"sizes": "any",
|
||||
"type": "image/svg+xml",
|
||||
"purpose": "any maskable"
|
||||
|
||||
+6
-2
@@ -15,8 +15,12 @@
|
||||
*/
|
||||
|
||||
const CACHE_VERSION = "event-clock-v1";
|
||||
const SHELL = ["/", "/index.html", "/styles.css", "/main.js"];
|
||||
const FEED = "/data/events.v1.json";
|
||||
// Paths are derived from the registration scope, so the same worker is
|
||||
// correct at a domain root and under a subpath (GitHub Pages) alike.
|
||||
const BASE = new URL("./", self.registration.scope);
|
||||
const at = (path) => new URL(path, BASE).toString();
|
||||
const SHELL = ["", "index.html", "styles.css", "main.js"].map(at);
|
||||
const FEED = new URL("data/events.v1.json", BASE).pathname;
|
||||
const FONT_HOSTS = new Set(["fonts.googleapis.com", "fonts.gstatic.com"]);
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
|
||||
Reference in New Issue
Block a user