When a consumer clicks an arrow or drags the wheel, the SVG animations pause, the entire wrapper rotates and the newly seen part turns into interactive.
The part swap additionally triggers a route change. As a result of the hero carousel and the remainder of the web page (represented by the Outlet element) stay on a special stage throughout the web page’s format, the info on the web page can change whereas the carousel doesn’t re-render:
routes/applications/format.tsx
export default perform ProgramsLayout() {
return (
// Carousel logic, separated from the remainder of the web page and freed from re-renders when the info updates
// Remainder of the web page, re-rendering when this system route modifications
);
}
Every part of the carousel showcases a Lottie animation mixed with a most important consumer interplay:
The fourth program encompasses a solar setting on a peaceful sea, illuminated by a lighthouse within the background. Customers can work together with the water itself: each mouse motion triggers light ripples that unfold throughout the floor.
That is carried out utilizing a easy ripple simulation on an SVG form with a number of management factors:
That is the place AI got here in useful. Creating and distributing management factors throughout an SVG form will be troublesome and time-consuming. Claude Code helped with that, taking the unique form and producing the content material so GSAP may animate every management level following the ripple algorithm:
Authentic sea form:
// Claude-generated management level system mixed with GSAP:
perform animateWave(mouseX?: quantity) {
const startX = 277.223;
const endX = 2705.13;
const baseY = 703.836;
const numPoints = 50;
const amplitude = -(pointerSpeed.speedY) * 0.3;
const length = 3;
// Decide epicenter of ripple
const epicenterX = mouseX !== undefined ? Math.max(startX, Math.min(endX, mouseX)) : (startX + endX) / 2;
gsap.killTweensOf(rippleProgress.present);
rippleProgress.present.worth = 0;
gsap.to(rippleProgress.present, {
worth: 1,
length,
ease: 'power2.out',
onUpdate: () => {
if (!sea.present) return;
const progress = rippleProgress.present.worth;
const fadeOut = 1 - progress;
// Calculate ripple unfold distance from epicenter
const maxDistance = Math.max(epicenterX - startX, endX - epicenterX);
const rippleDistance = progress * maxDistance * 1.5;
// Generate factors alongside the curve
const factors: Array<{
x: quantity;
y: quantity
}> = [];
for (let i = 0; i <= numPoints; i++) {
const x = startX + (endX - startX) * (i / numPoints);
// Calculate distance from epicenter
const distanceFromEpicenter = Math.abs(x - epicenterX);
// Ripple impact: solely apply amplitude the place the ripple has reached
let ripple = 0;
if (distanceFromEpicenter <= rippleDistance) {
// Calculate how far into the ripple wave this level is
const ripplePhase = (rippleDistance - distanceFromEpicenter) / (maxDistance * 0.3);
ripple = Math.sin(ripplePhase * Math.PI) * amplitude * fadeOut;
}
const y = baseY + ripple;
factors.push({
x,
y
});
}
// Construct the trail with clean curves
let pathData = `M${startX} ${baseY}n`;
// Create clean curve by way of all factors
for (let i = 0; i < factors.size - 1; i++) {
const present = factors[i];
const subsequent = factors[i + 1];
const cpX = (present.x + subsequent.x) / 2;
pathData += `Q ${present.x} ${present.y} ${cpX} ${(present.y + subsequent.y) / 2}n`;
}
// Connect with final level and shut the trail
const lastPoint = factors[points.length - 1];
pathData += `L ${lastPoint.x} ${lastPoint.y}n`;
pathData += `L ${endX} ${baseY}n`;
pathData += `L ${endX} 1491.4n`;
pathData += `L ${startX} 1491.4n`;
pathData += `L ${startX} ${baseY} Z`;
sea.present.setAttribute('d', pathData);
},
onComplete: () => {
if (!sea.present) return;
// Reset to authentic path
sea.present.setAttribute('d', `
M277.223 703.836
C 1200 703.836 1800 703.836 2705.13 703.836
C 2705.13 703.836 2705.13 1491.4 2705.13 1491.4
C 2705.13 1491.4 277.223 1491.4 277.223 1491.4
C 277.223 1491.4 277.223 703.836 277.223 703.836 Z
`);
}
});
}
Scroll-based Interactive Backgrounds for Lottie Animations
One other enjoyable problem was to combine Lottie-based animations with a set sample background, that reacts to the scroll:
To realize the impact, we got here up with an strategy that mixes a number of canvas layers, blended collectively utilizing globalCompositeOperation:
Step1: draw the mounted sample as soon as in an offscreen canvas
Step2: set Lottie's render mode to canvas
Step3: seize the Lottie's canvas and use it as a masks
Step4: draw the masks and glued sample along with a globalCompositeOperation
Physics-based Interactive Block
The careers web page options an interactive ingredient the place the phrase “helps” hangs from two ropes, echoing the team-building message. To make it much more impactful, Louis got here up with the concept to let customers work together with it.
The pure answer was to include a physics engine for a practical and interesting expertise.
We used the Matter.js library, mapping the phrase’s dimensions to a rectangle physique. The ropes are a stack of composites, rendered in canvas. The phrase “helps” itself is an SVG, that then will get displaced with the outcomes from the physics simulation:
Morphing Shapes
A small interplay, that at the beginning seems easy however truly introduced some challenges is the morphing form of the square-to-circle CTA piece.
GSAP’s MorphSVG plugin makes this easy:
perform onEnter() {
gsap.to('.cta-rect', {
length: 0.9,
morphSVG: '.cta-circle-shape', ease: 'elastic.out(0.8, 0.8)'
});
}
perform onLeave() {
gsap.to('.cta-rect', {
length: 0.9,
morphSVG: '.cta-rec', ease: 'elastic.out(1.2, 1)'
});
}
Stickers Block
Including stickers to a number of the sections felt like a pure interplay, giving a playful dimension to the textual content.
Biking by way of an array of stickers on click on and displaying them with bouncy animations was made straightforward utilizing GSAP’s built-in elastic easing:
// Animate the size for the present sticker
if (stickerRefs.present[targetIndex]) {
gsap.fromTo(stickerRefs.present[targetIndex], {
scale: 0,
}, {
scale: 1,
ease: 'elastic.out(1.2, 0.8)',
length: 1,
});
}
Scroll-based Interactions
Lastly, the web site is filled with scroll-based interactions. From textual content exhibiting to photographs revealing and SVG animations taking part in, it’s essential to have the ability to handle every interactive ingredient’s state with ease.
ScrollTrigger is a perfect match for this. It helped us keep away from establishing Intersection Observers manually and integrates completely with the useGSAP hook:
// Instance of a scroll-based parallax animation created with ScrollTrigger and useGSAP. The tweens are mechanically killed and discarded as soon as the element unmounts
useGSAP(() => {
ScrollTrigger.create({
set off: root.present,
begin: 'high high',
finish: 'backside high',
scrub: true,
onUpdate: (self) => {
setDispY(20 * self.progress * weight);
}
});
}, []);
The Use of AI within the Venture
Whereas conventional coding methods had been nonetheless on the core of the challenge, AI supplied a really robust further pair of fingers for duties that will be in any other case tedious and time consuming.
It was excellent at optimizing SVGs when given clear steering (for instance, changing a masks to a clip-path for efficiency positive factors). With a transparent knowledge mannequin as a place to begin, it additionally helped create further comparable Sanity blocks and map the info fetching on the appliance’s facet.
We additionally discovered that a number of the extra superior inventive coding methods (just like the wave ripple impact) had been additionally surprisingly correct, and it made resolving TypeScript points and creating varieties a breeze.
It additionally got here with some caveats:
First, it sometimes produced inconsistent and inaccurate outcomes. It will generally alter sure knowledge fetching patterns unexpectedly, making the code messy and probably inflicting essential points if left unchecked.
Although good at optimizing and cleansing sure SVGs, it additionally hallucinated in some situations (even creating made-up shapes and including them to the code with out consideration).
All in all, we loved utilizing AI for smaller, tightly scoped duties slightly than larger ones. One level is also made about “AI fatigue”, the place letting an agent code most of a performance led to a sure feeling of not controlling the output anymore. Going again to generated code felt like doing further code evaluate, and have become tough when the options needed to be rewritten in some situations.
Closing Phrases
Crafting Maxima Remedy was an train in combining tech and creativity. Establishing a powerful framework with Sanity, React, and GSAP streamlined the design-to-code supply. With a powerful inventive imaginative and prescient, having the instruments prepared meant we had been in a position to say “sure” to the concepts as they got here alongside.
Utilizing a coding agent made iterating on ideas sooner and lowered a number of the most tedious duties to an afterthought, permitting us to deal with the true inventive intent.
It really was a enjoyable problem and we’re very grateful to have been trusted with serving to Maxima of their mission to ship further excellent care for individuals with neurodivergence.
Credit
Company: KOKI-KIKO
Technique & PO: Kim Levan
Artwork Course & Design: Louis Paquet
Branding & Illustrations: Anthony Morell
Tech & Growth: Nicolas Garnier







