Skip to main content

Documentation 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.

Nightshade is a single-page React application built with Vite. All React components, page definitions, and routing logic compile into a single assets/main.js bundle. Understanding how the app bootstraps, how components nest, and how static per-page HTML files work together is essential context before diving into the routing or component docs.

App Bootstrap

The application is mounted in assets/main.js with a single ReactDOM.render call:
assets/main.js
ReactDOM.render(<App />, document.getElementById("root"));
The root <App> component (named et in the compiled output) renders a <HashRouter> from React Router v6, which wraps the entire application. Inside the router, the <Layout> component acts as the persistent app shell, and within it an <AnimatePresence> block keyed by location.pathname drives page-transition animations around the <Routes> tree.

Component Hierarchy

The full component tree, from router root to individual route leaves, looks like this:
<HashRouter>
  └── <Layout>
        ├── <FamiliarCursor />      # Custom witch cursor
        ├── <SmokeLayer />          # Ambient background
        ├── <Navigation />          # Fixed top nav bar
        └── <motion.main>           # Animated page wrapper
              └── <AnimatePresence>
                    └── <Routes>
                          ├── /                  → SanctumPage
                          ├── /about             → AboutPage
                          ├── /projects          → ProjectsPage
                          ├── /skills            → SkillsPage
                          ├── /work              → WorkPage
                          ├── /case-studies      → CaseStudiesPage
                          ├── /case-studies/:slug → CaseStudyDetailPage
                          ├── /blog              → BlogPage
                          ├── /blog/:slug        → BlogPostPage
                          ├── /testimonials      → TestimonialsPage
                          └── /contact           → ContactPage
<Layout> provides the full-screen dark background (min-h-screen bg-witch-dark), renders the ambient <FamiliarCursor> and <SmokeLayer> layers, mounts the <Navigation> bar, and then wraps all page content in a motion.main element that fades and adjusts brightness on each route change. A final sibling div (fixed inset-0 pointer-events-none z-40) applies a vignette over the entire viewport using an inset box-shadow (shadow-[inset_0_0_150px_rgba(0,0,0,0.9)]), darkening the edges without interfering with pointer events.

Why HashRouter

Nightshade is deployed as a static site on GitHub Pages. GitHub Pages serves pre-built files directly from the repository root and has no server-side routing logic. Any request for a path like /about would return a 404, because no about/index.html exists at that path. HashRouter sidesteps this problem entirely by encoding the route in the URL fragment (/#/about). The browser never sends the fragment to the server, so every navigation request hits index.html, and React Router handles the rest client-side.

Static Per-Page HTML Files

Each route in the app has a corresponding HTML file in the pages/ directory (for example, pages/About.html). These files serve as direct-link entry points. When a visitor opens a bookmarked URL like https://example.github.io/pages/About.html, the page sets the correct hash before React mounts:
pages/About.html
<script>
  window.__STATIC_PAGE_ROUTE__ = "/about";
  if (!window.location.hash || window.location.hash === "#/" || window.location.hash === "#") {
    window.location.hash = "/about";
  }
</script>
This redirect runs synchronously before assets/main.js initialises, so React Router always reads the correct hash on first render. The result: deep links work on a host with no server-side rewrites.
All component and page code lives in assets/main.js — this is the single compiled bundle Vite produces. The files under components/ (such as Layout.js, Navigation.js, and Candle.js) are the pre-compiled ES module sources listed as <link rel="modulepreload"> in index.html. The browser fetches them in parallel during cold-start to reduce latency, but the runtime logic all executes from within the main bundle.

Build docs developers (and LLMs) love