Field Notes

Figma to Code

Pixel-Perfect Figma Replication - When Design Systems ARE the Architecture

EduVisa called for a one-to-one recreation of a complex Figma file, including overlapping SVG morphs, 190px blur shadows, mouse-reactive backgrounds, and eight breakpoints up to 3,840px. With no backend, the project needed a custom component and design-token system rather than an off-the-shelf library.

Topic
Figma to Code
Year
Read
6 min

The brief

EduVisa - Home page with mouse-reactive backgroundsystem cut
The home page, including its mouse-reactive background.
Proof from EduVisa Services WebsiteOpen system

Why standard libraries failed

  • shadcn/ui, Radix, and Material do not provide overlapping SVG morph animations
  • Tailwind utilities alone cannot describe a specific SVG path morphing into another path as the page scrolls
  • The 190px blur shadows required an explicit filter: blur(190px) value rather than a stock token
  • The mouse-reactive backgrounds use a mousemove, motionValue, spring, and transform pipeline

The architecture that emerged

  1. Design token extraction before component work:
  • Moved every Figma colour, gradient, spacing value, radius, and shadow into CSS custom properties
  • The system includes more than 60 colour tokens, 25 gradient tokens, and variables for spacing, radius, and shadow
  • A design update usually means changing one CSS variable instead of hunting through 50 files
  1. Three layers of animation:
  • CSS keyframes handle the ambient loops, including floating, waving, and gradient drift, across more than 640 lines of @keyframes
  • Framer Motion handles scroll and interaction work, including reveals, springy hover recovery, and layout animation
  • Embla Carousel handles sliding content such as testimonials, course cards, and blog posts
  • The layers stay separate so an ambient CSS loop does not fight Framer Motion, and Embla does not manage keyframes
  1. A responsive system built per section:
  • Eight breakpoints cover mobile, tablet, laptop, desktop, xl, 2xl, 3xl, and 5xl at 3,840px
  • There is no one-size-fits-all responsive grid. Hero, About, Courses, Destinations, Blog, and Contact each have their own component and breakpoint logic.
  • The layout maths lives with the component rather than in generic utility classes, which keeps the extreme sizes predictable
  1. A static SPA with no backend:
  • Vite, React, and TypeScript, deployed through the Vercel CDN
  • Content lives in TypeScript data files. A copy change needs a code push, but there is no database or CMS to maintain.
  • SEO uses a Zustand meta cache and header middleware, without a metadata server
  • Forms use EmailJS in the client, with no backend
  • Vite plugins run MozJPEG and PNG compression during the build
  • React.lazy and Suspense split code by section so the initial bundle stays smaller
  1. A guard for touch devices:
  • Complex ripple-card interactions behaved inconsistently on mobile
  • @media (hover: hover) and (pointer: fine) disables those interactions on touch-only devices

The lesson

Continue conversation

Frontend problem worth thinking through?

Bring the context, including the hard parts. I am happy to talk them through.