Skip to main content

Documentation Index

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

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

MoonPhaseNav is the beating heart of The Craft’s navigation system. Rather than conventional labels or numbered tabs, each portfolio section is mapped to a specific phase of the lunar cycle, rendered as a small SVG-style circle that fills, empties, and glows to reflect the moon’s shape. The result is a navigation bar that feels native to the grimoire aesthetic while remaining fully accessible and keyboard-friendly via React Router’s <NavLink>.

Route-to-Phase Mapping

Every route in the portfolio is assigned a moon phase. The navItems array in the source defines these mappings:
PathPage NameMoon Phase
/The Covernew
/aboutThe Practitionerwaxing-crescent
/projectsSpellworkfirst-quarter
/skillsArcane Artswaxing-gibbous
/workCoven Recordsfull
/case-studiesTome of Workingswaning-gibbous
/blogWhisperslast-quarter
/contactSummoningwaning-crescent
The sequence intentionally follows the real lunar calendar from new moon to waning crescent, so navigating through the portfolio mirrors the progression of a complete lunar cycle.

How Moon Phases Are Rendered

Each navigation item uses a MoonPhase sub-component that receives the phase string and an isActive boolean. Every moon is a w-6 h-6 rounded circle with a border border-spell/30 base. The interior of the circle is composed using overflow-hidden and absolutely positioned fill divs to simulate each lunar shape:

new

A plain bg-midnight-darker circle with no fill — representing the absence of light.

waxing-crescent

Dark background with a narrow w-1/3 right-side fill, shaped with border-radius: 100% 0 0 100% to form the crescent curve.

first-quarter

Dark background with a w-1/2 right-side fill, creating a precise half-lit circle.

waxing-gibbous

Mostly lit (bg-spell/40) with a narrow w-1/4 left-side dark cutout shaped with border-radius: 0 100% 100% 0.

full

A fully solid bg-spell/60 circle — the brightest and most prominent icon in the bar.

waning-gibbous

Mostly lit with a narrow w-1/4 right-side dark cutout, mirroring the waxing gibbous.

last-quarter

Dark background with a w-1/2 left-side fill — the mirror image of first quarter.

waning-crescent

Dark background with a narrow w-1/3 left-side fill, the mirror image of waxing crescent.
When isActive is true, fills switch from bg-spell/40 to bg-spell (full brightness) and the outer ring changes to border-spell with a shadow-[0_0_15px_rgba(45,212,191,0.8)] teal glow.

Active State & Framer Motion Indicator

React Router’s <NavLink> supplies the isActive boolean via its render prop API. When a route is active:
  • The MoonPhase circle switches to full-brightness fills and adds the border-spell ring glow.
  • A Framer Motion motion.div with layoutId="activeMoon" renders as an absolutely positioned overlay ring. Because layoutId is shared across all nav items, Framer Motion smoothly animates this indicator as it slides from one moon to the next during navigation — no jump cuts, only a fluid spring transition (stiffness: 300, damping: 30).

Tooltips

Each <NavLink> uses Tailwind’s group / group-hover pattern to reveal a floating tooltip. The tooltip is:
  • Absolutely positioned relative to the nav item.
  • Hidden by default via opacity-0.
  • Revealed on hover via group-hover:opacity-100 with a transition-opacity duration-300 fade.
  • On mobile, it appears above the icon (bottom-full mb-4) to stay within the viewport.
  • On desktop, it appears to the right of the icon (left-full ml-4) alongside the vertical bar.
The tooltip itself is a glass-panel card with font-cinzel tracking-wider text-spell styling to match the grimoire aesthetic. It has pointer-events-none so it never blocks mouse interaction.

Positioning

The nav bar adapts its orientation and position between mobile and desktop using responsive Tailwind classes:
BreakpointPositionOrientationClasses
Mobile (default)Horizontally centered, 1.5rem from the bottomRow (horizontal)fixed bottom-6 left-1/2 -translate-x-1/2 flex items-center gap-6
Desktop (md+)2rem from the left edge, vertically centeredColumn (vertical)md:bottom-auto md:top-1/2 md:-translate-y-1/2 md:left-8 md:translate-x-0 md:flex-col md:px-3 md:py-8
The nav container uses the .glass-panel utility class for the frosted glass background, with rounded-full on mobile for a pill shape and implicit rectangular rounding on desktop.

How to Customize

Adding a new portfolio section to the navigation requires only a single entry in the navItems array in MoonPhaseNav.js:
const navItems = [
  // ... existing items
  {
    path: '/grimoire',
    name: 'The Grimoire',
    phase: 'full', // must be one of the eight valid phase strings
  },
];
The phase value must be one of the eight valid strings: new, waxing-crescent, first-quarter, waxing-gibbous, full, waning-gibbous, last-quarter, or waning-crescent. Any other value will fall through to the default branch of the switch statement and render a plain unstyled circle.
To maintain the lunar-cycle metaphor, try to assign phases that reflect the narrative weight of each page. The full moon is the brightest and most visually dominant — in the default data it belongs to the Work page, the portfolio’s most important section.

Build docs developers (and LLMs) love