Skip to main content

Documentation Index

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

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

The Skills page reimagines a standard tech-stack list as a bowl of Halloween candy. Every skill is a candy-shaped pill with two side nubs — a classic wrapped-sweet silhouette — color-coded by category. Hovering a candy makes it float dramatically out of the bowl with a Framer Motion spring animation, and a tooltip above it unwraps to show the skill name. The visual metaphor extends all the way to the bowl label: “Take One”, rendered in a large faded spooky font.

Skill Categories

Three categories are defined in the SKILLS constant array in assets/main.js. Each category has a Tailwind background-color class and a list of four skill names.
const SKILLS = [
  { name: 'Languages',  color: 'bg-purple-500',     skills: ['JavaScript', 'TypeScript', 'Python', 'HTML/CSS'] },
  { name: 'Frameworks', color: 'bg-haunt-pumpkin',  skills: ['React', 'Next.js', 'Node.js', 'Tailwind'] },
  { name: 'Tools',      color: 'bg-haunt-moon',     skills: ['Git', 'Docker', 'AWS', 'Figma'] },
];
CategoryTailwind ColorSkills
Languagesbg-purple-500JavaScript, TypeScript, Python, HTML/CSS
Frameworksbg-haunt-pumpkinReact, Next.js, Node.js, Tailwind
Toolsbg-haunt-moonGit, Docker, AWS, Figma
A color-coded legend appears below the bowl, mapping each dot to its category name.

Candy Shape

Each skill is rendered as a <div> with a main pill body and two absolute-positioned side nubs that mimic the twisted ends of a wrapped candy:
<div className={`w-16 h-10 ${category.color} rounded-full
                 flex items-center justify-center shadow-lg relative`}>

  {/* Left nub */}
  <div className={`absolute -left-3 w-4 h-6 ${category.color} rounded-l-full opacity-80`}
       style={{ clipPath: 'polygon(100% 0, 0 20%, 0 80%, 100% 100%)' }} />

  {/* Right nub */}
  <div className={`absolute -right-3 w-4 h-6 ${category.color} rounded-r-full opacity-80`}
       style={{ clipPath: 'polygon(0 0, 100% 20%, 100% 80%, 0 100%)' }} />
</div>
  • w-16 h-10 rounded-full — the main wrapped body.
  • The clipPath polygons angle the nubs inward so they taper like twisted wrapper ends.
  • The color class from the parent category object is applied to both the body and the nubs, keeping them consistent.

Hover Float Animation

Each candy is wrapped in a Framer Motion <motion.div> with whileHover configured to shoot the candy upward:
initial:    { y: 0 }
whileHover: { y: -50, scale: 1.2, zIndex: 50 }
onHoverStart and onHoverEnd update a shared hoveredSkill state string, which drives the tooltip’s Framer Motion animate prop:
<motion.div
  className="relative cursor-pointer group"
  initial={{ y: 0 }}
  whileHover={{ y: -50, scale: 1.2, zIndex: 50 }}
  onHoverStart={() => setHoveredSkill(skillName)}
  onHoverEnd={()  => setHoveredSkill(null)}
>
  {/* Tooltip */}
  <motion.div
    className="absolute -top-12 bg-haunt-bg border border-haunt-moon
               text-haunt-moon px-3 py-1 rounded text-sm font-bold
               whitespace-nowrap pointer-events-none"
    initial={{ opacity: 0, y: 10 }}
    animate={{
      opacity: hoveredSkill === skillName ? 1 : 0,
      y:       hoveredSkill === skillName ? 0 : 10,
    }}
  >
    {skillName}
  </motion.div>

  <CandyShape color={category.color} />
</motion.div>
The tooltip is positioned with absolute -top-12 so it appears above the candy as it floats up.

The Bowl Graphic

The bowl is built from three layered <div> elements inside a relative container:
{/* Shadow/depth layer behind the bowl */}
<div className="absolute bottom-0 left-1/2 -translate-x-1/2
                w-3/4 h-48 bg-haunt-dark rounded-b-full border-b-8
                border-haunt-tombstoneDark opacity-50" />

{/* Candy layout area */}
<div className="absolute bottom-10 left-1/2 -translate-x-1/2
                w-2/3 h-48 flex flex-wrap justify-center
                content-end gap-2 p-4 z-10">
  {/* All candy elements rendered here */}
</div>

{/* Foreground bowl rim (frosted glass) */}
<div className="absolute bottom-0 left-1/2 -translate-x-1/2
                w-3/4 h-48 bg-haunt-tombstone/30 backdrop-blur-md
                rounded-b-full border-b-8 border-x-4
                border-haunt-tombstoneDark z-20
                flex items-end justify-center pb-8">
  <span className="font-spooky text-3xl text-haunt-moon opacity-50">Take One</span>
</div>
The foreground bowl layer uses z-20 so it visually contains the candies, which sit on z-10. The backdrop-blur-md gives the bowl a frosted-glass look.

Adding Skills

1

Add a skill to an existing category

Find the matching object in the SKILLS array and append the new skill name to its skills array:
{ name: 'Languages', color: 'bg-purple-500', skills: ['JavaScript', 'TypeScript', 'Python', 'HTML/CSS', 'Rust'] },
The new candy will appear in the bowl automatically with the category’s color.
2

Add a new category

Append a new object to the SKILLS array:
const SKILLS = [
  // … existing categories …
  {
    name:   'Databases',
    color:  'bg-emerald-500',
    skills: ['PostgreSQL', 'MongoDB', 'Redis', 'SQLite'],
  },
];
Then add a matching entry to the legend section at the bottom of the component so visitors know what the new color represents.
When choosing a color for a new category, pick any Tailwind background class (bg-sky-400, bg-rose-500, bg-emerald-600, etc.). The same class string is applied to the candy body, both nubs, and the legend dot, so a single well-chosen color keeps the whole candy visually cohesive.

Build docs developers (and LLMs) love