Skip to content

Commit 9f07ea0

Browse files
committed
Add SPA routing support for GitHub Pages - handle refresh on client-side routes
1 parent c58d545 commit 9f07ea0

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

.github/workflows/deploy-books.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ jobs:
6161
# Copy demo build to docs/book/demo for serving
6262
mkdir -p docs/book/demo
6363
cp -r demo/build/* docs/book/demo/
64+
# Copy 404.html for SPA routing support
65+
cp demo/public/404.html docs/book/demo/404.html
6466
# Verify the structure
6567
echo "Documentation files:"
6668
ls -la docs/book/

demo/public/404.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="./favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta name="description" content="Needle Demo - Image Search System" />
9+
<title>Needle Demo</title>
10+
<script>
11+
// GitHub Pages SPA redirect
12+
// Redirect to the main demo page and let React Router handle the routing
13+
var segmentCount = 1; // Number of path segments to keep (/demo/)
14+
var l = window.location;
15+
l.replace(
16+
l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
17+
l.pathname.split('/').slice(0, 1 + segmentCount).join('/') + '/?p=' +
18+
encodeURIComponent(l.pathname.slice(1).split('/').slice(segmentCount).join('/')) +
19+
(l.search ? '&' + l.search.slice(1) : '') +
20+
l.hash
21+
);
22+
</script>
23+
</head>
24+
<body>
25+
<noscript>You need to enable JavaScript to run this app.</noscript>
26+
<div id="root"></div>
27+
</body>
28+
</html>

demo/src/App.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,43 @@
1-
import React from 'react';
2-
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
1+
import React, { useEffect } from 'react';
2+
import { BrowserRouter as Router, Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-dom';
33
import Layout from './components/Layout';
44
import SearchPage from './pages/SearchPage';
55
import DirectoryPage from './pages/DirectoryPage';
66
import GeneratorPage from './pages/GeneratorPage';
77
import StatusPage from './pages/StatusPage';
88
import './styles/index.css';
99

10+
// Component to handle GitHub Pages SPA redirect
11+
function RedirectHandler() {
12+
const navigate = useNavigate();
13+
const location = useLocation();
14+
15+
useEffect(() => {
16+
// Check for redirect parameter from 404.html
17+
const urlParams = new URLSearchParams(location.search);
18+
const redirectPath = urlParams.get('p');
19+
20+
if (redirectPath) {
21+
// Clean up the URL by removing the redirect parameter
22+
const newUrl = new URL(window.location);
23+
newUrl.searchParams.delete('p');
24+
window.history.replaceState({}, '', newUrl.pathname + newUrl.search + newUrl.hash);
25+
26+
// Navigate to the intended path
27+
navigate(redirectPath, { replace: true });
28+
}
29+
}, [navigate, location.search]);
30+
31+
return null;
32+
}
33+
1034
function App() {
1135
console.log('Needle Demo App loading...');
1236

1337
return (
1438
<Router>
1539
<div className="App">
40+
<RedirectHandler />
1641
<Layout>
1742
<Routes>
1843
<Route path="/" element={<Navigate to="/search" replace />} />

0 commit comments

Comments
 (0)