Skip to main content

Documentation Index

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

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

The Home page (/) is the entry point — the Portal — of Magical Portfolio. It renders a full-viewport hero section that introduces Elara Nightshade through a stroke-drawn SVG text animation, then presents six navigation menu cards as the primary wayfinding UI for the entire site.

Visual & UX Overview

Animated SVG Hero

The name “Elara Nightshade” is drawn onto the screen using a strokeDasharray animation that sweeps from "0 1000" to "1000 0", followed by a fill fade from transparent to #e2e8f0. The subtitle “Software Alchemist & Digital Weaver” appears beneath in font-mono styled in mystic-teal/80.

3D Tilt Navigation Cards

Six navigation menu cards sit in a flex-wrap row. Each card is w-48 h-72 (192 × 288 px) and responds to mouse movement with a live 3D tilt effect powered by Framer Motion’s useMotionValue and useTransform hooks (rotateX / rotateY derived from cursor position, ranging ±15°).

Background Alchemy Sigil

A large alchemy <Sigil> component is rendered at 10% opacity centered behind all content, providing ambient mystical atmosphere without distracting from foreground elements.

Staggered Card Entrance

Cards animate in from opacity: 0, y: 50 to opacity: 1, y: 0. Each card’s animation is delayed by 2 + (index × 0.1) seconds, creating a cascading reveal after the hero text finishes drawing.

Tagline

The hero section includes a sardonic one-liner displayed beneath the subtitle:
“No actual spells, just suspiciously organized files and a concerning amount of coffee.”
Each card is driven by a static data array. The six entries are:
IDTitleSubtitlePathRoman NumeralColor Gradient
aboutThe ChronicleOrigins & Lore/aboutIfrom-mystic-800 to-mystic-950
projectsThe GrimoireSummoned Works/projectsIIfrom-mystic-900 to-mystic-800
skillsAffinitiesArcane Competencies/skillsIIIfrom-mystic-800 to-mystic-900
writingThe TomesInscribed Thoughts/writingIVfrom-mystic-950 to-mystic-800
case-studiesRitualsDeep Magic/case-studiesVfrom-mystic-800 to-mystic-950
contactThe SummoningSend a Raven/contactVIfrom-mystic-900 to-mystic-800
The Sigil type cycles through ["star", "moon", "alchemy", "eye"] by index position (i.e., sigils[index % 4]). Card 0 (about) gets star, card 1 (projects) gets moon, card 2 (skills) gets alchemy, card 3 (writing) gets eye, card 4 (case-studies) gets star, and card 5 (contact) gets moon.
The card data structure in source looks like:
const cards = [
  { id: "about",         title: "The Chronicle",  subtitle: "Origins & Lore",          path: "/about",        roman: "I",   color: "from-mystic-800 to-mystic-950" },
  { id: "projects",     title: "The Grimoire",   subtitle: "Summoned Works",           path: "/projects",     roman: "II",  color: "from-mystic-900 to-mystic-800" },
  { id: "skills",       title: "Affinities",     subtitle: "Arcane Competencies",      path: "/skills",       roman: "III", color: "from-mystic-800 to-mystic-900" },
  { id: "writing",      title: "The Tomes",      subtitle: "Inscribed Thoughts",       path: "/writing",      roman: "IV",  color: "from-mystic-950 to-mystic-800" },
  { id: "case-studies", title: "Rituals",        subtitle: "Deep Magic",               path: "/case-studies", roman: "V",   color: "from-mystic-800 to-mystic-950" },
  { id: "contact",      title: "The Summoning",  subtitle: "Send a Raven",             path: "/contact",      roman: "VI",  color: "from-mystic-900 to-mystic-800" },
];

3D Tilt Interaction

Each card tracks mouse position relative to its own bounding box and feeds those values into Framer Motion motion values:
const mouseX = useMotionValue(0);
const mouseY = useMotionValue(0);

const rotateX = useTransform(mouseY, [-0.5, 0.5], ["15deg", "-15deg"]);
const rotateY = useTransform(mouseX, [-0.5, 0.5], ["-15deg", "15deg"]);

const handleMouseMove = (e) => {
  const rect = e.currentTarget.getBoundingClientRect();
  const x = (e.clientX - rect.left) / rect.width - 0.5;
  const y = (e.clientY - rect.top) / rect.height - 0.5;
  mouseX.set(x);
  mouseY.set(y);
};
perspective is set on the card’s wrapper so the rotateX/rotateY values produce a genuine 3D tilt effect. On mouseLeave, both motion values are reset to 0.

Customization

The SVG text element renders the literal string "Elara Nightshade". To change it, update the <text> element’s content inside the hero section and adjust the strokeDasharray end value if the new name is significantly longer or shorter (longer names need a higher max value than 1000).The subtitle "Software Alchemist & Digital Weaver" and tagline are plain string literals inside the component — find and replace them directly.
Edit the cards array. Each object must have: id, title, subtitle, path, roman, and color. The Sigil type is assigned by index % 4 against the array ["star", "moon", "alchemy", "eye"], so adding a seventh card will cycle back to star.Update docs.json navigation entries to match any new routes added here.
The stagger delay formula is delay: 2 + index * 0.1. To make cards appear sooner, reduce the base 2 seconds. To tighten or loosen the cascade spread, adjust the 0.1 multiplier.

Component Dependencies

ComponentSourceRole
Sigilcomponents/Sigil.jsDraws animated SVG sigil icons inside each card and as the background watermark
BackgroundEffectscomponents/BackgroundEffects.jsRenders floating particle orbs and the deep purple/teal ambient blurs
Navigationcomponents/Navigation.jsFixed top navigation bar (rendered globally, visible here)
motion (Framer Motion)assets/proxy.jsPowers strokeDasharray hero animation, card tilt, and stagger entrance
useMotionValue / useTransformFramer MotionDerives rotateX/rotateY from live mouse coordinates for the tilt effect
The CustomCursor component (components/CustomCursor.js) is also active on this page — it replaces the native cursor with a glowing custom pointer. It is rendered at the app shell level and is visible across all pages.

Build docs developers (and LLMs) love