Skip to main content

Documentation Index

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

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

The Navigation component renders a persistent fixed bar across the top of every page. It displays the V. DOOM logo on the left and the six main route links on the right, using React Router’s <NavLink> for active-state detection. A Framer Motion shared-layout animation slides an amber dot beneath whichever link is currently active, and a mix-blend-difference blend mode ensures the nav text remains legible over any background color the particle canvas happens to produce. The navigation is driven by a static navLinks array. Each entry maps a route path to its occult-flavored display label:
const navLinks = [
  { path: '/',           label: 'The Circle'   },
  { path: '/about',      label: 'Practitioner' },
  { path: '/projects',   label: 'Spells Cast'  },
  { path: '/skills',     label: 'Cauldron'     },
  { path: '/experience', label: 'Pacts'        },
  { path: '/contact',    label: 'Summoning'    }
];
Each entry is rendered as a React Router <NavLink>. Both className and children accept render callbacks that receive the isActive flag. The className callback applies font and color classes; the children callback renders the label text and conditionally mounts the active indicator:
<NavLink
  to={link.path}
  className={({ isActive }) =>
    `relative font-sans text-sm uppercase tracking-widest transition-colors duration-300 ${
      isActive ? 'text-amber' : 'text-bone/70 hover:text-bone'
    }`
  }
>
  {({ isActive }) => (
    <>
      {link.label}
      {isActive && (
        <motion.div
          layoutId="nav-indicator"
          className="absolute -bottom-2 left-1/2 w-1 h-1 bg-amber rounded-full -translate-x-1/2"
          style={{ boxShadow: '0 0 8px 2px rgba(245, 178, 91, 0.6)' }}
        />
      )}
    </>
  )}
</NavLink>

Active Indicator

When a link is active, a small amber dot appears beneath it. This dot is a Framer Motion element that uses a shared layout animation — identified by layoutId="nav-indicator" — to smoothly slide from one link to the next whenever the active route changes. Because all instances share the same layoutId, Framer Motion treats them as a single element that physically moves across the DOM rather than fading one out and another in. The result is a dot that appears to glide between nav items as you navigate the site. A boxShadow glow (0 0 8px 2px rgba(245, 178, 91, 0.6)) is applied via style to give the dot a soft amber radiance.
The layout animation is automatic — no additional configuration is required. Framer Motion infers the start and end positions from the DOM positions of the layoutId elements.

mix-blend-difference

The nav bar container applies mix-blend-difference to its CSS mix-blend-mode property:
<nav className="fixed top-0 left-0 right-0 z-50 p-6 flex justify-between items-center mix-blend-difference">
mix-blend-difference subtracts the background pixel color from the foreground pixel color. In practice this means:
  • Over a dark background the nav text appears light
  • Over a light background the nav text appears dark
  • The effect is continuous — as the animated particle background shifts, the nav text contrast adjusts in real time with zero JavaScript
This eliminates the need for a semi-transparent backdrop or a separate scroll-aware color toggle while keeping the navigation readable across every particle-canvas state.
mix-blend-difference operates on the composited pixel values, so it only takes effect when the nav element overlaps the layers below it. If you add an opaque full-width header background, the blend mode will have no visible effect against that background.

Mobile Behavior

The route link list is hidden on viewports narrower than the md breakpoint (768 px) using Tailwind’s responsive prefix:
<ul className="hidden md:flex space-x-8">
  {/* navLinks rendered here */}
</ul>
There is no hamburger menu in the default implementation — the links simply collapse. The V. DOOM logo link to '/' remains visible at all screen sizes. To add a mobile menu, replace the hidden <ul> with a controlled drawer or sheet component:
// Example — replace the hidden ul with a toggle + drawer pattern
const [open, setOpen] = useState(false);

// In JSX:
<button className="md:hidden" onClick={() => setOpen(o => !o)}>

</button>

{open && (
  <div className="absolute top-full left-0 w-full bg-midnight/95 flex flex-col gap-4 p-6 md:hidden">
    {navLinks.map(link => (
      <NavLink key={link.path} to={link.path} onClick={() => setOpen(false)}>
        {link.label}
      </NavLink>
    ))}
  </div>
)}

Customizing Labels

The display labels in navLinks are entirely independent of the route paths — renaming them has no routing side effects. Open components/Navigation.js and edit the label values directly:
// Before
{ path: '/projects', label: 'Spells Cast' }

// After — rename without touching the route definition
{ path: '/projects', label: 'Grimoire' }
To add a new route to the navigation, add a { path, label } entry to the navLinks array and register a matching <Route> in your React Router configuration. The nav will render the new link automatically — the active indicator and blend-mode effect apply to all entries without extra configuration.

Build docs developers (and LLMs) love