dev-mode uses React Router’sDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/dev-mode/llms.txt
Use this file to discover all available pages before exploring further.
HashRouter to manage all client-side navigation. Every URL change is tracked in the hash fragment (#/about, #/projects, etc.) rather than the pathname, which means the browser never makes a round-trip to the server when the user moves between pages. A single AppShell layout component wraps all seven routes, providing the persistent bottom navigation bar and the ScanlineOverlay CRT effect across every view.
Why HashRouter?
Hash-based routing stores the active route after the# character in the URL. From the server’s perspective, every request is for the same file — the URL https://example.com/pages/About.html#/about resolves to About.html whether the user is on the home screen or has navigated to About. This makes dev-mode fully compatible with static file hosts (GitHub Pages, Netlify, S3, etc.) that cannot be configured with path rewrite rules.
The trade-off is that hash-based URLs are not as clean as history-mode URLs.
For a portfolio project hosted statically, this is the right default choice.
Route Table
The router defines seven routes, all nested under theAppShell layout component. The top-level Route renders AppShell, and each child Route renders the matching page component.
| Route | Component | Arcade Theme |
|---|---|---|
/#/ | Home | High-score leaderboard |
/#/about | About | Character select |
/#/projects | Projects | Cartridge wall |
/#/skills | Skills | Command list |
/#/writing | Writing | Manual rack |
/#/cases | CaseStudies | Boss battles |
/#/contact | Contact | Initials entry |
Page Transition Animations
Route changes are animated with Framer Motion’sAnimatePresence component, which is wrapped around the Routes tree with mode="wait". The wait mode ensures the exiting page fully completes its exit animation before the entering page begins mounting — preventing both views from being visible at the same time.
Each page is wrapped in a motion.div with the following transition definition:
0.98) while the exit scale ends slightly large (1.02), giving a punchy zoom-through sensation.
The window.__STATIC_PAGE_ROUTE__ Mechanism
Because the SPA is deployed as static HTML files, a user who navigates directly to pages/About.html or shares a link must still land on the correct React route. Each pages/*.html file sets a global variable before main.js loads:
Browser requests a page
The user navigates directly to
pages/About.html or refreshes the browser
while on the About route.Inline script runs
window.__STATIC_PAGE_ROUTE__ is set to "/about" and the redirect
function checks whether a hash is already present.Hash is set if missing
If there is no hash (e.g.
pages/About.html with no fragment), the script
replaces the URL with pages/About.html#/about before React mounts.AppShell Layout
Every route renders insideAppShell, which provides two persistent elements:
ScanlineOverlay— fixed atz-50, renders the CRT scanline and vignette over all page content.- Bottom navigation bar — fixed at the bottom of the viewport, containing seven
ArcadeButtonlinks to each route.
animate-flicker Tailwind utility (a subtle screen-flicker keyframe animation) and the selection color overrides selection:bg-arcade-magenta selection:text-arcade-white.