5.7 C
New York
Monday, April 6, 2026

Constructing the Maxima Remedy Web site: React, GSAP, and Dabbling with AI



The Venture

Maxima Remedy is a company devoted to supporting neurodivergent people all through their lives. They imagine in kindness, creativity and a heat and empowering setting. With this mindset, our mission was to ship a extremely illustrated, interactive and playful web site for the California-based firm.

Past the inventive facets, we needed to push the boundaries of what a “tech business pleasant” stack might supply. And with the rise of coding brokers, we checked out how utilizing AI might probably assist us within the course of.

The Stack

For the muse, we selected Sanity as our CMS, React Router for the frontend with static era, and Cloudflare Pages for internet hosting. In comparison with Subsequent.js, React Router provided a neater configuration to get issues began. Information is fetched from Sanity on the root degree and handed right down to particular person contexts, which lets us share it throughout completely different elements of the positioning with out being constrained by page-level scope limitations.

The positioning’s scrolling is smoothed with Lenis, whereas GSAP powers the entire interactive parts, particularly the scroll-based animations pushed by ScrollTrigger. Each are synchronized utilizing GSAP’s inner ticker and Lenis’s onScroll occasion. Most of the SVG animations are dealt with with Lottie, alongside some customized canvas implementations for patterns and Matter.js for the physics-based results. Utilizing GSAP with React additionally provides us entry to the useGSAP hook, which ensures computerized cleanup whereas mimicking React’s personal useEffect.

On the styling aspect, we used Tailwind CSS, with the occasional CSS module the place wanted, and we additionally introduced in TypeScript for sort checking, even when that self-discipline was generally loosely enforced. Altogether, the stack gave us a stable basis and sufficient flexibility to realize the ultimate end result. Claude Code additionally got here in very helpful for dashing up and automating duties that may in any other case have been tedious, which I’ll get into extra beneath.

The Options

House Carousel

The primary gate to the expertise is the interactive residence hero carousel.

Customers can seize and launch the wheel to navigate by means of the primary packages Maxima gives, and every part of the wheel comprises a set of SVG animations taking part in with Lottie in addition to a customized interactive ingredient.

The primary problem right here was to render and animate fairly a considerable amount of large SVG parts whereas protecting the web page interactive. It’s carried out by splitting the 4 completely different sections into 4 separated, rotated <div> parts inside a essential wrapper. Every part is unresponsive till it turns into seen.

When a person 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 part) stay on a unique degree throughout the web page’s structure, the info on the web page can change whereas the carousel doesn’t re-render:

routes/packages/structure.tsx

export default perform ProgramsLayout() {
  return (
    <ProgramHoverProvider>
      // Carousel logic, separated from the remainder of the web page and freed from re-renders when the info updates
      <ProgramHeroCarousel />
      <ProgramHeroCards />

      // Remainder of the web page, re-rendering when this system route adjustments
      <Outlet />
    </ProgramHoverProvider>
  );
}

Every part of the carousel showcases a Lottie animation mixed with a essential person interplay:

The fourth program incorporates a solar setting on a relaxed sea, illuminated by a lighthouse within the background. Customers can work together with the water itself: each mouse motion triggers mild 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 helpful. 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 might animate every management level following the ripple algorithm:

Unique sea form:

<path ref={sea} className="sea2" 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" 
  fill="#56D3D2" 
/>

// 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 period = 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,
      period,
      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 means 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 hard and fast sample background, that reacts to the scroll:

To attain 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 thought to let customers work together with it.

The pure resolution was to include a physics engine for a sensible 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 initially appears to be like easy however really offered some challenges is the morphing form of the square-to-circle CTA piece.

GSAP’s MorphSVG plugin makes this easy:

<svg
  width="140"
  peak="140"
  viewBox="0 0 140 140"
  fill="none"
  xmlns="http://www.w3.org/2000/svg"
  ref={svg}
>
  <path d={circleShapePath} className="cta-circle-shape opacity-0" />
  <path d={rectPath} className="cta-rect"/>
</svg>


perform onEnter() {
  gsap.to('.cta-rect', {
    period: 0.9,
    morphSVG: '.cta-circle-shape', ease: 'elastic.out(0.8, 0.8)'
  });
}

perform onLeave() {
  gsap.to('.cta-rect', {
    period: 0.9,
    morphSVG: '.cta-rec', ease: 'elastic.out(1.2, 1)'
  });
}

Stickers Block

Including stickers to a few of the sections felt like a pure interplay, giving a playful dimension to the textual content.

Biking by means 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 dimensions for the present sticker
if (stickerRefs.present[targetIndex]) {
  gsap.fromTo(stickerRefs.present[targetIndex], {
    scale: 0,
  }, {
    scale: 1,
    ease: 'elastic.out(1.2, 0.8)',
    period: 1,
  });
}

Scroll-based Interactions

Lastly, the web site is filled with scroll-based interactions. From textual content displaying to pictures 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 organising 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 routinely killed and discarded as soon as the part unmounts

useGSAP(() => {
    ScrollTrigger.create({
      set off: root.present,
      begin: 'prime prime',
      finish: 'backside prime',
      scrub: true,
      onUpdate: (self) => {
        setDispY(20 * self.progress * weight);
      }
    });
  }, []);

The Use of AI within the Venture

Whereas conventional coding methods have been nonetheless on the core of the undertaking, AI provided a really sturdy further pair of arms for duties that may be in any other case tedious and time consuming.

It was excellent at optimizing SVGs when given clear steerage (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 aspect.

We additionally discovered that a few of the extra superior inventive coding methods (just like the wave ripple impact) have been additionally surprisingly correct, and it made resolving TypeScript points and creating varieties a breeze.

It additionally got here with some caveats:

First, it often produced inconsistent and inaccurate outcomes. It might generally alter sure knowledge fetching patterns unexpectedly, making the code messy and doubtlessly inflicting vital 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 quite 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.

Ultimate 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 have 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 decreased a few 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 Path & Design: Louis Paquet
Branding & Illustrations: Anthony Morell
Tech & Growth: Nicolas Garnier



Supply hyperlink

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles