Nightshade handles all navigation client-side using React Router v6. Because the app is deployed as a static site on GitHub Pages, it usesDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/nightshade/llms.txt
Use this file to discover all available pages before exploring further.
HashRouter rather than BrowserRouter. Every URL encodes the current route in the hash fragment — for example /#/about — so the browser never sends route paths to the server and the single index.html entry point always loads correctly.
Router Type
HashRouter is imported from react-router-dom and wraps the entire application. All internal URLs follow the pattern /#<path>, keeping routing fully decoupled from the static file server.
Route Table
The following routes are defined in theRoutes block inside assets/main.js. Each path maps to a dedicated page component:
| Path | Component | Description |
|---|---|---|
/ | SanctumPage | Hero home page with candle selection |
/about | AboutPage | Narrative timeline about the developer |
/projects | ProjectsPage | Orbital project showcase |
/skills | SkillsPage | Hexagonal skills wheel |
/work | WorkPage | Work history as parchment scrolls |
/case-studies | CaseStudiesPage | List of major case studies |
/case-studies/:slug | CaseStudyDetailPage | Individual case study detail |
/blog | BlogPage | Blog post listing |
/blog/:slug | BlogPostPage | Blog post reader |
/testimonials | TestimonialsPage | Client testimonials |
/contact | ContactPage | Contact form |
Programmatic Navigation
Several page components navigate programmatically rather than using<Link>. The useNavigate() hook is used in back buttons and in the candle-selection UI on the home page:
Dynamic Route Parameters
The:slug segment appears in two routes. Both CaseStudyDetailPage and BlogPostPage extract it with useParams():
Page Transitions
<AnimatePresence mode="wait"> wraps the entire <Routes> block and is keyed by location.pathname (obtained from useLocation()). This ensures React unmounts the outgoing page component and plays its exit animation fully before mounting the incoming page:
motion.div or motion.main with initial, animate, and exit props, so every route change produces a coordinated fade/brightness transition driven by Framer Motion.
Per-Page HTML Hash-Redirect Pattern
Each route has a corresponding file in thepages/ directory. These static HTML files allow direct linking to specific pages on GitHub Pages. On load, a synchronous inline script checks the current hash and redirects if needed:
pages/About.html
assets/main.js initialises. By the time React Router reads window.location.hash, it already contains the correct route, so the app renders the right page immediately without a redirect flicker.