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.

JackOLantern maps each skill in your portfolio to a carved pumpkin SVG. The pumpkin’s face grows more expressive as proficiency increases: expert skills get a full flickering grin with multiple teeth, intermediate skills get a simpler two-triangle smile, and familiar skills get a flat-line mouth. Hovering any pumpkin triggers a playful wobble animation via Framer Motion.

Usage

JackOLantern receives a single skill object. The Skills page renders them in a responsive grid, each wrapped in a Framer Motion spring entrance:
import { JackOLantern } from '../components/JackOLantern';

<JackOLantern skill={skill} />
The full grid in assets/main.js applies staggered entrance animations:
// assets/main.js — Skills page
{skills.map((skill, index) => (
  <motion.div
    key={skill.name}
    initial={{ opacity: 0, scale: 0.5 }}
    animate={{ opacity: 1, scale: 1 }}
    transition={{ delay: index * 0.1, type: 'spring' }}
  >
    <JackOLantern skill={skill} />
  </motion.div>
))}
The delay prop on the skill object is used for the CSS animate-flicker face animation, not the entrance animation. The entrance stagger is controlled by the parent mapping index * 0.1.

Props

skill.name
string
required
The skill label displayed beneath the pumpkin in the Spooky font. Also shown in a smaller monospace uppercase label below it.
skill.level
"expert" | "intermediate" | "familiar"
required
Controls which carved face is rendered inside the pumpkin SVG:
  • "expert" — Three flicker triangles (two eyes + one nose), a full jagged grin with alternating teeth, and a glow bloom beneath the pumpkin.
  • "intermediate" — Two smaller triangle eyes and a smooth arc smile. Less dramatic glow.
  • "familiar" — Two minimal triangle eyes and a flat rectangular mouth. Subtle glow.
skill.delay
number
required
Delay in seconds applied to the animate-flicker CSS animation on the pumpkin face and the glow bloom beneath it. Staggers the flicker timing so pumpkins don’t all pulse in unison.

Face Expressions by Level

All three face variants use fill="#ffeb3b" (bright yellow) on a viewBox="0 0 100 110" SVG. The pumpkin body is layered from three concentric ellipses:
LayerFillRadius
Outer body#e65100rx=45, ry=40
Mid body#ef6c00rx=35, ry=40
Center highlight#ff7a1arx=20, ry=40
A small green stem sits above: M 45 20 Q 50 5 60 10 Q 55 15 55 20 Z with fill="#2e7d32".
// Three triangles + full jagged grin + large glow
<g className="animate-flicker" style={{ animationDelay: `${skill.delay}s` }}>
  <polygon points="35,45 45,60 25,60" fill="#ffeb3b" />  {/* left eye */}
  <polygon points="65,45 75,60 55,60" fill="#ffeb3b" />  {/* right eye */}
  <polygon points="50,65 55,75 45,75" fill="#ffeb3b" />  {/* nose */}
  <path
    d="M 20 80 Q 50 100 80 80 L 75 85 L 70 80 L 65 85 L 60 80 L 55 85
       L 50 80 L 45 85 L 40 80 L 35 85 L 30 80 L 25 85 Z"
    fill="#ffeb3b"
  />
</g>

Hover Animation

Each pumpkin is wrapped in a motion.div that responds to whileHover with a quick scale-up and a two-degree wobble sequence:
<motion.div
  className="relative w-32 h-32 cursor-pointer"
  whileHover={{ scale: 1.1, rotate: [-2, 2, -2, 0] }}
  transition={{ duration: 0.3 }}
>

Entrance Animation

The parent page wraps each JackOLantern in its own motion.div for a spring-based scale-in entrance:
initial={{ opacity: 0, scale: 0.5 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: index * 0.1, type: 'spring' }}
The entrance stagger delay is derived from the grid index (multiplied by 0.1), not from skill.delay. The skill.delay property is used exclusively for the CSS animate-flicker face animation.

Skills Data

Replace the skills array in assets/main.js to update your pumpkin patch:
// assets/main.js
const skills = [
  { name: 'React',          level: 'expert',       delay: 0.1 },
  { name: 'TypeScript',     level: 'expert',       delay: 0.5 },
  { name: 'Tailwind',       level: 'expert',       delay: 0.2 },
  { name: 'Next.js',        level: 'intermediate', delay: 0.8 },
  { name: 'Node.js',        level: 'intermediate', delay: 0.4 },
  { name: 'Framer Motion',  level: 'intermediate', delay: 0.7 },
  { name: 'GraphQL',        level: 'familiar',     delay: 0.3 },
  { name: 'Python',         level: 'familiar',     delay: 0.9 },
];

Customization

Add a new skill — Append an object to the skills array. Choose a delay value between 0 and 1 to spread the flicker animation out from the others:
{ name: 'Rust', level: 'familiar', delay: 0.6 },
Adjust stagger timing — Increase the flicker delay spread for a more dramatic cascade, or set all delays to 0 to make every pumpkin flicker in sync.
Keep delay values spaced at least 0.1s apart so the flicker animation on neighbouring pumpkins is visually distinct. Values above 1.0s cause a noticeable pause before the first flicker cycle begins.
Change pumpkin colors — Edit the three ellipse fills in JackOLantern.js to use a different color family, such as a ghostly white pumpkin:
<ellipse cx="50" cy="65" rx="45" ry="40" fill="#b0bec5" />  {/* outer */}
<ellipse cx="50" cy="65" rx="35" ry="40" fill="#cfd8dc" />  {/* mid */}
<ellipse cx="50" cy="65" rx="20" ry="40" fill="#eceff1" />  {/* center */}

Build docs developers (and LLMs) love