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 Work page maps a career journey onto a literal winding path. A faint dashed SVG bezier curve runs down the center of the page like a moonlit trail through a haunted forest. Work experience cards are planted alternately on the left and right of the path, connected to it by short horizontal glowing lines. As the visitor scrolls, each card materializes out of the dark with a Framer Motion whileInView animation. The visual metaphor reinforces the portfolio’s narrative: this is a path you walk, not a table you read.

Work Experiences

All three entries are defined in the EXPERIENCE constant array in assets/main.js:
const EXPERIENCE = [
  { company: 'SpookyCorp',      role: 'Senior Frontend Engineer', years: '2022 - Present', desc: 'Architected the new haunting dashboard.' },
  { company: 'Ghostly Startups', role: 'Full Stack Developer',    years: '2019 - 2022',    desc: 'Built the MVP that raised $5M in seed funding.' },
  { company: 'Web Witches',     role: 'Junior Dev',               years: '2017 - 2019',    desc: 'Maintained legacy PHP spells and incantations.' },
];
CompanyRoleYearsDescription
SpookyCorpSenior Frontend Engineer2022 – PresentArchitected the new haunting dashboard.
Ghostly StartupsFull Stack Developer2019 – 2022Built the MVP that raised $5M in seed funding.
Web WitchesJunior Dev2017 – 2019Maintained legacy PHP spells and incantations.

Alternating Left / Right Layout

Cards alternate sides based on their zero-based array index. Even-index entries (0, 2, 4 …) align to the left; odd-index entries (1, 3, 5 …) align to the right:
<motion.div
  className={`flex ${index % 2 === 0 ? 'justify-start' : 'justify-end'} w-full`}
  // …
>
The connector line flips position to match — it extends from the right edge of left-aligned cards and the left edge of right-aligned cards, pointing toward the central path:
<div className={`
  absolute top-1/2 -translate-y-1/2 w-16 h-px bg-haunt-moon/50
  ${index % 2 === 0 ? '-right-16' : '-left-16'}
`} />

The Winding SVG Path

The central dashed path is an SVG <path> element using a cubic bezier curve that oscillates between the left and right sides of the container:
<svg
  className="absolute top-0 left-1/2 -translate-x-1/2 w-full h-full z-0 opacity-20"
  preserveAspectRatio="none"
  viewBox="0 0 100 1000"
>
  <path
    d="M50,0 C80,200 20,400 50,600 C80,800 20,1000 50,1000"
    fill="none"
    stroke="#fef3c7"
    strokeWidth="2"
    strokeDasharray="10 10"
  />
</svg>
  • preserveAspectRatio="none" stretches the SVG to fill the container regardless of its actual aspect ratio.
  • opacity-20 keeps the path subtle — a ghost trail rather than a bold line.
  • strokeDasharray="10 10" creates evenly spaced dashes.
  • The bezier control points (C80,200 20,400 and C80,800 20,1000) make the path sway left then right.

Scroll-Triggered Entrance Animations

Each card uses Framer Motion’s whileInView prop for scroll-triggered entrance. Cards start below their final position and slide up as they enter the viewport:
initial:    { opacity: 0, y: 50 }
whileInView:{ opacity: 1, y:  0 }
viewport:   { once: true }
PropertyValueEffect
initial{opacity:0, y:50}Card starts transparent and 50 px below its final position
whileInView{opacity:1, y:0}Fades in and rises to rest when scrolled into view
viewport.oncetrueAnimation plays once and does not replay on scroll-up

Card Design

Each experience card is a bg-haunt-tombstoneDark rounded panel with a subtle border:
<div className="bg-haunt-tombstoneDark p-6 rounded-lg border border-haunt-tombstone
                w-[80%] md:w-[45%] relative shadow-2xl">

  {/* Connector line */}
  <div className={`absolute top-1/2 -translate-y-1/2 w-16 h-px bg-haunt-moon/50
                   ${index % 2 === 0 ? '-right-16' : '-left-16'}`} />

  <h3 className="text-2xl font-spooky text-haunt-pumpkin mb-1">{entry.company}</h3>
  <h4 className="text-lg text-haunt-moon font-bold mb-2">{entry.role}</h4>
  <div className="text-xs text-haunt-bone/50 mb-4">{entry.years}</div>
  <p  className="text-haunt-bone/80 text-sm">{entry.desc}</p>
</div>
  • Cards are w-[80%] on mobile and w-[45%] on md: and above so they don’t stretch across the full container — leaving room for the central path to remain visible.

Adding a Work Entry

1

Append to the EXPERIENCE array

Open assets/main.js, find the EXPERIENCE constant, and add a new object:
const EXPERIENCE = [
  // … existing entries …
  {
    company: 'Phantom Labs',
    role:    'Contract Engineer',
    years:   '2016 - 2017',
    desc:    'Delivered three client projects on time and under budget.',
  },
];
2

Check the side alignment

The new entry will appear at the bottom of the list. Its index determines which side it appears on. With four entries, index 3 is odd → it will align right. If you need it on the left, reorder the array or add a placeholder entry.
3

Extend the SVG path (optional)

If you add many entries, the SVG path may not reach the new cards. Extend the bezier by increasing the last y coordinate in the d attribute to match the new total height of the space-y-32 stack. Each entry adds roughly 128 px to the total height.
The SVG path uses preserveAspectRatio="none" and stretches to fill its parent container’s height. The parent is relative max-w-3xl mx-auto — its height is determined by the space-y-32 stack of cards. The path always spans the full height automatically, regardless of how many entries you add.

Build docs developers (and LLMs) love