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.

The Witch page lives at route /about and is rendered by the AboutPage component (minified export Oe). It presents the developer’s professional backstory as a three-chapter gothic narrative, animating each chapter into view as the user scrolls. The page uses no third-party layout components — all structure comes from Framer Motion, Tailwind utility classes, and a CSS pseudo-element for the central timeline spine. The header block animates in on mount using initial={{ opacity: 0, y: 20 }} transitioning to animate={{ opacity: 1, y: 0 }}. It contains:
  • Title"The Witch" in Cormorant Unicase (font-heading text-5xl)
  • Subtitle"A serious non-serious person." in JetBrains Mono (font-code text-sm)
  • Years of Practice card — an inline parchment card (.parchment-bg + border-witch-plum/30) displaying the moon phase indicator and the caption "From novice scripter to master architect."

Moon Phase Indicator

The MoonPhaseIndicator sub-component (He) renders five moon-phase emoji in a horizontal row. The first four are dimmed (text-witch-moonlight/60) and the fifth — the full moon — is highlighted (text-witch-moonlight text-glow-teal), visually marking “mastery” as the current phase:
// MoonPhaseIndicator component
const MoonPhaseIndicator = () => (
  <div className="flex gap-2 text-witch-moonlight/60 text-xl my-4 justify-center">
    <span>🌑</span>
    <span>🌒</span>
    <span>🌓</span>
    <span>🌔</span>
    <span className="text-witch-moonlight text-glow-teal">🌕</span>
  </div>
);

Timeline Structure

The timeline is a single div with space-y-24 (96px vertical gaps between chapters) and a CSS pseudo-element that draws the central spine:
/* Equivalent Tailwind utilities on the wrapper div */
before:absolute before:inset-0
before:ml-[50%] before:-translate-x-1/2
before:w-px
before:bg-gradient-to-b
before:from-witch-amber/0 before:via-witch-amber/20 before:to-witch-amber/0
The result is a 1px vertical line centered in the container, fading from transparent at both ends to a soft amber glow at mid-scroll. It is a pure CSS ::before pseudo-element — there is no SVG or JavaScript involved.

Chapter Layout

Each chapter alternates between left-aligned and right-aligned text using flex-row (even indices) and flex-row-reverse (odd indices). The three-column flex structure per chapter is:
  1. Text column (w-1/2) — chapter title and narrative paragraph.
  2. Center marker (w-16) — a small dark circle (border-witch-amber/50) with a tiny <Candle> component layered above it (z-20).
  3. Spacer column (w-1/2) — empty, provides visual balance on the opposing side.
The text alignment also flips: even chapters are text-right, odd chapters are text-left. This creates the classic alternating-sides timeline appearance common in editorial layouts.

The Three Chapters

The chapter data is defined as a plain array inside AboutPage:
const chapters = [
  {
    title: "The Calling",
    content: "It began not with a wand, but with a terminal. The black screen, a void waiting to be filled with logic and syntax. I discovered that words, when arranged perfectly, could command machines to do my bidding. They called it 'programming'. I knew it was an incantation.",
    delay: 0.2,
  },
  {
    title: "The Apprenticeship",
    content: "Years spent in the dim light of monitors, deciphering ancient documentation and wrestling with legacy curses. I learned the delicate art of state management—keeping the chaotic energies of the frontend contained within predictable vessels.",
    delay: 0.4,
  },
  {
    title: "The First Hex Banished",
    content: "A memory leak that had plagued the production servers for a fortnight. It required a deep dive into the astral plane of the heap snapshot. With a single, precise line of cleanup code, the hex was broken. The servers breathed easy once more.",
    delay: 0.6,
  },
];
The Calling — The origin story. The developer discovers programming through a terminal and frames writing code as casting incantations. Establishes the witch-as-programmer metaphor that carries through the whole portfolio.The Apprenticeship — The learning years. Wrestling with documentation, legacy codebases, and the discipline of state management. The “chaotic energies of the frontend” is a reference to the difficulty of predictable client-side state before modern tools.The First Hex Banished — The first real victory: diagnosing and fixing a production memory leak using heap snapshots. The “single, precise line of cleanup code” is a nod to a forgotten removeEventListener or subscription teardown.

Scroll Animation

Each chapter motion.div uses Framer Motion’s whileInView prop to trigger the animation only when the chapter enters the viewport:
<motion.div
  initial={{ opacity: 0, y: 50 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true, margin: "-100px" }}
  transition={{ duration: 0.8, delay: chapter.delay }}
>
Key points:
  • viewport.once: true — the animation fires once and does not reset when scrolling back up.
  • viewport.margin: "-100px" — the trigger fires 100px before the element’s top edge enters the viewport, giving a slight early start.
  • delay — staggered at 0.2s, 0.4s, 0.6s so rapid scrolling still reveals chapters in sequence.
If you set once: false, chapters will re-animate every time the user scrolls past them. This can feel jarring on the timeline. The default once: true is intentional.

Customization

1

Add a new timeline chapter

Append a new object to the chapters array inside AboutPage. Provide a unique title, narrative content, and a delay value slightly larger than the last chapter’s delay:
{
  title: "The Grand Summoning",
  content: "The day everything clicked. Complex systems became simple, patterns emerged from chaos, and the code wrote itself. Almost.",
  delay: 0.8,
},
The alternating layout is driven by the array index (n % 2 === 0), so a fourth chapter will automatically appear on the left side.
2

Adjust animation timing

Change duration in the transition object to slow down or speed up the fade-in. Change each chapter’s delay to control stagger spacing. Setting all delays to 0 causes all three chapters to animate simultaneously as soon as any enters the viewport.
3

Update the moon phase indicator

The MoonPhaseIndicator component is a standalone functional component defined just above AboutPage. To change which moon is highlighted, move the text-witch-moonlight text-glow-teal class to a different <span>. To add a caption beneath it, edit the <p> tag reading "From novice scripter to master architect." inside the parchment card.

Build docs developers (and LLMs) love