Systems

supporting system

EduVisa Services Website

Pixel-Perfect Animated SPA - 70+ Components, 30+ Keyframes, 8 Breakpoints, Zero Backend

EduVisa is a client-side React site for an overseas education consultancy. I recreated a dense, animation-heavy Figma file one detail at a time, including overlapping SVG morphs, 190px blur shadows, and mouse-reactive backgrounds. It runs without a backend and was delivered during a two-month freelance engagement.

scale
Eight responsive breakpoints cover phones through 5xl displays at 3840px. More than 70 custom UI components support over 30 CSS and JavaScript animation sequences on modern devices.
latency
Vercel serves the static site through its CDN. React.lazy and Suspense split components so the initial load does not carry every page at once.
reliability
There is no application server or database to maintain. Text and media come from static data files, while Zustand retains SEO metadata between navigations.
automation
The Vite build pipeline compresses MozJPEG and PNG assets before deployment. EmailJS handles form submissions without a custom backend.
EduVisa - Home page with mouse-reactive backgroundfirst proof
The home page, including its mouse-reactive background.
Context

Problem had shape before code did.

The site uses spring-based backgrounds, animated SVG paths, scroll reveals, and ripple cards to make a consultancy site feel more alive. Contact forms go through EmailJS. Content and media are held in static data files, so there is no database or CMS behind it.

  • Recreated an animation-heavy Figma design in a client-side React application without a backend.
  • Built a layered animation system with more than 30 custom CSS keyframes and Framer Motion for physics-based and scroll-driven interactions.
  • Created a responsive layout that supports eight breakpoints up to 3840px, or 5xl.
  • Kept page data in TypeScript files so the application can run as a static site without a CMS or database.
Backend
None. It is a client-side React SPA built with Vite.
Animation
Three layers: CSS keyframes for ambient motion, Framer Motion for interaction, and Embla for carousels.
Responsive
Eight breakpoints through 3840px, with custom components for each section.
Content
Stored in TypeScript files. There is no CMS or database, so a typo fix is a code change.
Build
Vite, MozJPEG and PNG optimisation, plus React.lazy and Suspense for component splitting.
SEO
A Zustand metadata cache and header middleware handle meta tags without a custom backend.
Forms
EmailJS handles contact submissions without a custom backend.
Timeline
Delivered within a tight two-month freelance window
Build

Structure had to survive job.

  • Every route, including course and blog slugs, is handled in the client-side SPA.
  • A Zustand store keeps SEO metadata available while visitors move between pages, avoiding repeat work during navigation.
  • Text and media live in static data folders, keeping visual components separate from the content they render.
  • A routing fallback reads slug patterns such as study-in-* and *-coaching to choose the right page template.
The client wanted a close Figma recreation for an education consultancy, but the brief did not call for a backend. Standard UI libraries could not reproduce the overlapping SVG morphs, 190px blur shadows, or mouse-reactive backgrounds. I used custom components for each section, three complementary animation layers, and a Zustand metadata cache for SEO. In this project, the visual rules in CSS are a core part of the architecture.
Working stack

React / TypeScript / Vite / Tailwind CSS v4 / shadcn/ui / Zustand / Framer Motion / EmailJS / Vercel

Evidence

Browser becomes part of argument.

Evidence viewerKeyboard arrows change proof

01 / 12The about page.

Decisions

Small cuts make system trustworthy.

  • I wrote more than 640 lines of custom CSS utilities and keyframes for the floating, waving, and slow-moving gradient motion, without relying on JavaScript for those ambient loops.
  • The mouse-reactive background uses Framer Motion values and springs so it settles naturally after the pointer moves.
  • A Vite image-optimization step compresses MozJPEG and PNG assets before they are shipped.
  • Ripple cards are limited to hover-capable devices because their touch behavior was inconsistent on mobile.
  • For SEO in a client-only React app, metadata is cached in Zustand and header middleware provides the appropriate meta tags.
Pressure

What resisted, broke, stayed expensive.

Constraints in motion

  • Off-the-shelf UI libraries could not reproduce the overlapping SVG morphs, 190px blur radii, or mouse-reactive backgrounds in the Figma file.
  • Each of the eight responsive breakpoints needed custom consideration across the site sections.
  • Framer Motion and more than 70 components added to the JavaScript bundle, so React.lazy and Suspense split the first load into smaller chunks.
  • A client-only React app has limits around server-rendered SEO metadata.
  • Ripple cards behaved inconsistently on touch screens.

Failure modes

  • Ripple cards did not behave consistently on mobile touch screens, so they were restricted with hover-only media queries.
  • Without a backend, SEO metadata needed extra handling. Zustand caching and header middleware supply the appropriate tags.

Trade

  • Text and image references live in local TypeScript files. Fixing a typo means making a code change, but the project does not need a CMS or database.
  • Framer Motion and more than 70 custom components add to the JavaScript bundle. React.lazy and Suspense keep the first load smaller by splitting the application.
Result

What held. What carries forward.

metric

A faithful Figma build with SVG morphs and 190px blur shadows

Each section has its own custom component. The build includes more than 640 lines of CSS keyframes and mouse-reactive backgrounds driven by Framer Motion values and springs.

architecture

Layered animation with CSS keyframes and Framer Motion

Ambient loops use CSS keyframes, scroll and pointer interactions use Framer Motion, and sliding content uses Embla carousels.

architecture

A static SPA with no custom backend

Content lives in TypeScript files and the site deploys with Vite and Vercel. React.lazy and Suspense split components, with no database, CMS, or custom server.

metric

Eight breakpoints through 3840px

The responsive system uses custom section components from mobile sizes through 5xl ultrawide layouts.

If rebuilt

  • Move to Next.js with ISR where server-rendered SEO would help.
  • Consolidate repeated keyframes into shared animation tokens.
  • Explore react-three-fiber for interactive hero elements.
  • Optimise SVG paths during the build with SVGO.
結論

The Figma file needed custom keyframes, SVG work, and layout calculations that a generic component library could not provide. Over time, the components and animation rules became the site's design system.

Make it hold together

Complex frontend system need steady hand?

Architecture, interface, production constraints. Together.