Mystery Haunting uses React Router v6 (Documentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/mystery-haunting/llms.txt
Use this file to discover all available pages before exploring further.
react-router-dom@6) with a BrowserRouter to manage client-side navigation across nine portfolio pages. The BrowserRouter uses the browser’s History API so that every route maps to a clean pathname (e.g., /about) rather than a hash fragment. To support static hosting on GitHub Pages — where there is no server capable of rewriting arbitrary paths to index.html — each route also has a corresponding file in pages/ that seeds window.location.hash before the app boots (see Static Page Exports and Deep Linking below). The router is initialized inside the root App component, which wraps a Routes tree containing one Route per portfolio section.
Route Reference
| Path | Component | Spooky Label | Description |
|---|---|---|---|
/ | Landing | The Foyer | Animated welcome page with a spooky haunted house silhouette, floating ghost icons, and a “ENTER IF YOU DARE” CTA button |
/about | About | The Attic | Monster dossier page with an interactive card that flips open on click to reveal subject details |
/projects | Projects | The Graveyard | Project showcase rendered as tombstone cards with hover pop-up ghost cards |
/skills | Skills | The Lab | Animated potion bottle skill bars that fill with colored liquid on scroll into view |
/work | Work | Previous Hauntings | Career timeline with alternating entries and animated house icons that light up on hover |
/case-studies | CaseStudies | Autopsy Reports | Post-mortem bug reports styled as aged paper case files with a “RESOLVED” stamp |
/blog | Blog | Forbidden Library | Interactive bookshelf with hoverable book spines that tilt and glow on hover |
/testimonials | Testimonials | Eye-Witnesses | Mouse-tracking SVG eye widgets that follow cursor movement; click to reveal testimonial quotes |
/contact | Contact | Séance Circle | Ouija board contact form with a planchette that animates to each typed letter’s position on the board |
Page Transition Animation
Every route change triggers a 3D book-flip transition powered by Framer Motion’sAnimatePresence and motion.div. The Layout component wraps page content in an AnimatePresence mode="wait" block so the outgoing page fully completes its exit animation before the incoming page begins its entrance.
The transition is driven by a shared variants object:
initial— the incoming page starts rotated 90° away from the viewer (like a closed book page), invisible, with a 1200 px perspective applied.in— the page rotates to face the viewer (rotateY: 0), fading in over 0.8 s with an ease-out curve.out— the departing page rotates 90° in the opposite direction and fades out over 0.8 s with an ease-in curve, simulating a page being turned away.
motion.div is keyed by location.pathname, so React treats each route as a distinct element and triggers the full enter/exit lifecycle on every navigation:
The
perspective-[1200px] utility is applied to the <main> container in Layout to establish the 3D rendering context required for the rotateY transforms to appear correctly in the browser.Route Definitions
All nine routes are declared inside a single<Routes> block in the root component. Each route maps a URL path to its corresponding page component:
<Routes> and <Route> components are imported from react-router-dom and compiled into the assets/main.js bundle (aliased as S and d respectively in the minified output).
Static Page Exports and Deep Linking
BecauseBrowserRouter relies on the server to serve index.html for every path, direct access to a route URL on static GitHub Pages hosting would normally return a 404. To work around this, each pages/ HTML file sets window.__STATIC_PAGE_ROUTE__ and seeds window.location.hash before the app boots, giving the React app a hint about which route to render:
window.location.hash changes the URL in the browser (e.g., to pages/About.html#/about) before the React bundle executes. The BrowserRouter then reads window.location and can use the seeded hash value to navigate to the correct route on first render, so the right page component is displayed without a redirect or flash of the landing page.