diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx
new file mode 100644
index 0000000..49bfe6d
--- /dev/null
+++ b/src/app/not-found.tsx
@@ -0,0 +1,10 @@
+import { PacmanLoader } from "react-spinners";
+
+export function NotFound() {
+ return (
+
+ );
+}
diff --git a/src/router.tsx b/src/router.tsx
index dbe489b..fcf97aa 100644
--- a/src/router.tsx
+++ b/src/router.tsx
@@ -1,5 +1,6 @@
import { Converter } from "./app/converter";
import { Home } from "./app/home";
+import { NotFound } from "./app/not-found";
import { Route, Routes } from "react-router";
export default function AppRouter() {
@@ -7,6 +8,9 @@ export default function AppRouter() {
} />
} />
+
+ {/* Fall back on app's 404 page. This is because of the SPA routing trick with 404.html used in GitHub Pages. */}
+ } />
);
}
diff --git a/vite.config.ts b/vite.config.ts
index 180abd0..27f5e72 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,8 @@
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react-swc";
+import fs from "fs";
import path from "path";
-import { defineConfig } from "vite";
+import { type Plugin, defineConfig } from "vite";
import sitemap from "vite-plugin-sitemap";
// https://vite.dev/config/
@@ -9,6 +10,7 @@ export default defineConfig({
plugins: [
react(),
tailwindcss(),
+ copyIndexTo404(),
sitemap({
hostname: "https://libresplit.org",
dynamicRoutes: ["/converter"],
@@ -25,3 +27,23 @@ export default defineConfig({
},
},
});
+
+// Home spun plugin for copying index.html to 404.html at build time.
+// This makes SPA routing work on GitHub pages.
+function copyIndexTo404(): Plugin {
+ return {
+ name: "copy-index-to-404",
+ closeBundle() {
+ const distDir = path.resolve(__dirname, "dist");
+ const indexPath = path.join(distDir, "index.html");
+ const notFoundPath = path.join(distDir, "404.html");
+
+ if (fs.existsSync(indexPath)) {
+ fs.copyFileSync(indexPath, notFoundPath);
+ console.log("Copied index.html → 404.html for SPA fallback");
+ } else {
+ console.warn("⚠️ index.html not found in dist directory");
+ }
+ },
+ };
+}