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
- Connected
- EduVisa Services Website
The brief
system cutWhy 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
- 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
- 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
- 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
- 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.lazyandSuspensesplit code by section so the initial bundle stays smaller
- 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