Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/dev-haunt/llms.txt

Use this file to discover all available pages before exploring further.

Navigation is DevHaunt’s persistent top bar. It lives at the very top of every page thanks to its fixed positioning and z-50 stacking order. On large screens it shows a centered pill of themed route links with a frosted-glass background. On smaller screens the links collapse behind a hamburger button that animates a dropdown menu in and out with Framer Motion. The brand mark in the top-left corner combines a Lucide Ghost icon with the site name, and the whole nav uses pointer-events: none on its outer wrapper so transparent gaps don’t accidentally swallow mouse events — only the interactive elements re-enable pointer events individually. The full list of routes and their Halloween-flavoured labels is defined in a static array inside the component:
const navLinks = [
  { path: '/',             label: 'The Porch' },
  { path: '/about',        label: 'Trick or Treat' },
  { path: '/projects',     label: 'Graveyard' },
  { path: '/skills',       label: 'Pumpkin Patch' },
  { path: '/work',         label: 'Hall of Doors' },
  { path: '/case-studies', label: 'Evidence' },
  { path: '/blog',         label: 'Tales' },
  { path: '/testimonials', label: 'Spirits Speak' },
  { path: '/contact',      label: 'Ring Doorbell' },
];
useLocation() from React Router provides the current pathname. Each link compares its path against location.pathname at render time:
  • Active routetext-pumpkin (orange #ff7a1a)
  • Inactive routestext-ghost (cream #f4f1ea)
A hover:text-pumpkin class provides the hover state on inactive links so the colour feedback is instant and consistent with the active state.

Desktop navigation

The desktop strip is visible only at lg breakpoints and above (hidden lg:flex). It uses a pill-shaped container styled with bg-night/80 backdrop-blur-sm for a frosted-glass effect and a border border-tombstone/30 outline that subtly separates it from the background without being distracting.
<div className="hidden lg:flex gap-6 pointer-events-auto bg-night/80 backdrop-blur-sm px-6 py-3 rounded-full border border-tombstone/30">
  {navLinks.map(link => (
    <Link
      to={link.path}
      key={link.path}
      className={`font-spooky text-lg transition-colors hover:text-pumpkin ${
        location.pathname === link.path ? 'text-pumpkin' : 'text-ghost'
      }`}
    >
      {link.label}
    </Link>
  ))}
</div>

Mobile menu

On viewports narrower than lg, the desktop strip is hidden and a circular hamburger button appears in the top-right corner. The button toggles a boolean state value (isOpen) managed by useState.
  • Closed — shows the Lucide Menu icon (three horizontal lines)
  • Open — shows the Lucide X icon (close)
The dropdown menu is conditionally rendered inside AnimatePresence so Framer Motion can play the exit animation before the element unmounts:
<AnimatePresence>
  {isOpen && (
    <motion.div
      initial={{ opacity: 0, y: -20 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -20 }}
      className="absolute top-20 right-4 bg-night/95 border border-tombstone/50 rounded-xl p-4 flex flex-col gap-4 pointer-events-auto shadow-2xl shadow-black/50 lg:hidden"
    >
      {navLinks.map(link => (
        <Link
          to={link.path}
          key={link.path}
          onClick={() => setIsOpen(false)}
          className={`font-spooky text-xl text-right transition-colors hover:text-pumpkin ${
            location.pathname === link.path ? 'text-pumpkin' : 'text-ghost'
          }`}
        >
          {link.label}
        </Link>
      ))}
    </motion.div>
  )}
</AnimatePresence>
The y: -20 → 0 motion combined with opacity: 0 → 1 gives the dropdown a quick fall-in feel when opening, and the reverse plays on dismiss. The top-left brand mark is always visible. It is a React Router <Link to="/"> containing:
  1. A Lucide Ghost icon (w-8 h-8) that plays a floating animation on hover
  2. The text “DevHaunt” in the font-spooky typeface — hidden on mobile (hidden sm:block) to keep the bar uncluttered on small screens
<Link to="/" className="pointer-events-auto flex items-center gap-2 text-ghost hover:text-pumpkin transition-colors group">
  <Ghost className="w-8 h-8 group-hover:animate-float" />
  <span className="font-spooky text-2xl tracking-wider hidden sm:block">DevHaunt</span>
</Link>

Adding a new route

DevHaunt ships as a pre-built static dist. The components/Navigation.js file is a compiled/minified ES module — editing it directly will break the bundle. New nav links must be added in the original source code and the project rebuilt before the change takes effect.
1

Add an entry to the navLinks array in source

In the original (pre-build) source for Navigation, append your new route to the navLinks array following the { path, label } shape, then rebuild the project.
{ path: '/haunted-archive', label: 'The Archive' },
2

Add a matching Route in the router

In your app’s router setup (typically main.jsx or App.jsx), add a <Route> that maps the new path to its page component.
<Route path="/haunted-archive" element={<HauntedArchive />} />
The desktop nav and mobile dropdown both derive their links from the same navLinks array, so a single addition to that array updates both menus automatically.

Build docs developers (and LLMs) love