Fluid background animation on mouse move

Does anyone know any tutorial for re-creating this background effect from this website: https://chriskalafatis.com/

As we move the mouse cursor, there is a fluid trail that follows.

import React, { Component, createRef } from 'react';
import * as THREE from 'three'; 

class BackgroundComponent extends Component {
  constructor(props) {
    super(props);
    this.containerRef = createRef()
    this.state ={
        time: 0
    }
  }

  componentDidMount() {
    this.container = this.containerRef.current;
    this.width = this.container.offsetWidth;
    this.height = this.container.offsetHeight;

    this.renderer = new THREE.WebGLRenderer({
      alpha: true,
      antialias: true,
    });

    this.dispScene = new THREE.Scene();
    this.scene = new THREE.Scene();
    this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    this.renderer.setSize(this.width, this.height);
    this.container.appendChild(this.renderer.domElement);
    this.camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 100, 2000);
    this.camera.position.set(0, 0, 600);
    this.manager = new THREE.LoadingManager();
    this.loader = new THREE.Curve(this.manager);
    this.time = 0;
    this.mouse = new THREE.Vector2();
    this.prevMouse = new THREE.Vector2();
    this.total = 100;
    this.currentSmoke = 0;
    this.s = 0;
    this.renderTex = new THREE.RenderTarget(this.width, this.height, {
      minFilter: THREE.LinearFilter,
      magFilter: THREE.LinearFilter,
      format: THREE.RGBAFormat,
    });

    this.addBg();
    this.addSmoke();
    this.animate();
  }

  addSmoke() {
    this.smoke = true;
    // const t = this.data.data.media;
    // const e = window.TEXTURES[t][0];
    const i = new THREE.Vector2(55, 57); // Create a Vector2 with appropriate dimensions

    this.dispM = [];
    for (let t = 0; t < this.total; t++) {
      let smokeParticle = new THREE.Mesh(
        new THREE.BufferGeometry(i.x, i.y), // Use PlaneBufferGeometry
        new THREE.MeshBasicMaterial({
        //   map: e,
          transparent: true,
          blending: THREE.NormalBlending, // Use appropriate blending mode
          depthTest: false,
          depthWrite: false,
        })
      );

      smokeParticle.visible = false;
      this.dispM.push(smokeParticle);
      this.dispScene.add(smokeParticle);
    }
  }

  addBg() {
     // Create a shader material for the background
     this.material = new THREE.ShaderMaterial({
        extensions: {
          derivatives: "#extension GL_OES_standard_derivatives : enable",
        },
        uniforms: {
          time: {
            value: 0,
          },
          tex: {
            value: null,
          },
          t: {
            value: 0,
          },
          t2: {
            value: 0,
          },
          pt: {
            value: 0,
          },
          st: {
            value: 0,
          },
          ps: {
            value: new THREE.Vector2(window.innerWidth, window.innerHeight),
          },
          r: {
            value: 0,
          },
          fc: {
            value: 0,
          },
          vc1: {
            value: new THREE.Vector2(0.5, 0.5),
          },
          vc2: {
            value: new THREE.Vector2(0, 1),
          },
          vc3: {
            value: new THREE.Vector2(1, 0),
          },
          c1: {
            value: new THREE.Vector4(0, 0, 0, 1),
          },
          c2: {
            value: new THREE.Vector4(0.3, 0.3, 0.3, 0.95),
          },
        },
        transparent: true,
        vertexShader: `
          #define GLSLIFY 1
          uniform float t;
          uniform float t2;
          uniform float time;
          uniform float pt;
          varying vec2 vUv;
          
          float ea1(float x) {
            return x < 0.5 ? 16. * x * x * x * x * x : 1. - pow(-2. * x + 2., 5.) / 2.;
          }
          
          float ea2(float x) {
            return x < 0.5 ? 8. * x * x * x * x : 1. - pow(-2. * x + 2., 4.) / 2.;
          }
          
          float pi = 3.14159265359;
          
          void main() {
            vUv = uv;
            vec3 pos = position;
            pos.z -= 85.;
            vec2 ct = vec2(0.5);
            float p = ea1(t);
            float p2 = ea2(t2);
            float np = min(2. * p2, 2. * (1. - p2));
            pos.y -= .15 * sin(uv.x * pi + 0.25) * np;
            pos.y += 1. * (1. - p);
            float nPt = min(2. * pt, 2. * (1. - pt));
            // pos.x *= 1. -(0.05 * (pt));
            float dist = distance(vUv, ct);
            float md = length(ct);
            float nd = dist / md;
            float b = nd * 150.;
            float c = -nd * 150.;
            float fm = mix(c, b, pt);
            // pos.z -= fm * nPt;
            float dt = distance(vec2(uv), vec2(0.5)) * 1.25;
            pos.z -= dt * 85. * pt;
            pos.y *= 1. + (0.11 * pt);
            gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 );
          }
        `,
        fragmentShader: `
          #define GLSLIFY 1
          #define PI 3.14159265359
          #define PI2 6.28318530718
          uniform float time;
          uniform float pt;
          uniform float st;
          uniform sampler2D tex;
          uniform vec2 ps;
          uniform float r;
          uniform float fc;
          uniform vec2 vc1;
          uniform vec2 vc2;
          uniform vec2 vc3;
          uniform vec4 c1;
          uniform vec4 c2;
          varying vec2 vUv;
          
          float rand(vec2 st){
            return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
          }
          
          float ns(vec2 p){
            vec2 ip = floor(p);
            vec2 u = fract(p);
            u = u*u*(3.0-2.0*u);
            
            float res = mix(
              mix(rand(ip),rand(ip+vec2(1.0,0.0)),u.x),
              mix(rand(ip+vec2(0.0,1.0)),rand(ip+vec2(1.0,1.0)),u.x),
              u.y
            );
            return res*res;
          }
          
          float ub( vec2 p, vec2 b, float r ){
            return length(max(abs(p)-b+r,0.0))-r;
          }
          
          vec4 la(vec4 frg, vec4 bc) {
            return frg * frg.a + bc * (1.0 - frg.a);
          }
          
          float aastep(float threshold, float value) {
            float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
            return smoothstep(threshold-afwidth, threshold+afwidth, value);
          }
          
          float sw(vec2 pt, vec2 center, float radius, float line_width, float edge_thickness, float side){
            vec2 d = pt - center;
            float theta = time * .25 * side;
            vec2 p = vec2(cos(theta), -sin(theta))*radius;
            float h = clamp( dot(d,p)/dot(p,p), 0.0, 1.0 );
            //float h = dot(d,p)/dot(p,p);
            float l = length(d - p*h);
          
            float gradient = 0.0;
            const float gradient_angle = PI * .25;
          
            if (length(d)<radius){
              float angle = mod(theta + atan(d.y, d.x), PI2);
              gradient = clamp(gradient_angle - angle, 0.0, gradient_angle)/gradient_angle * 0.5;
            }
          
            return gradient + 1.0 - smoothstep(line_width, line_width+edge_thickness, l);
          }
          
          void main(){
            vec2 m = vUv;
            vec2 m2 = vUv;
          
            vec4 n = texture2D(tex, vUv);
            float z = n.r * 2. * PI;
            vec2 dr = vec2(sin(z));
            vec2 uv = vUv + dr * n.r * 0.1;
            float d1 = distance(uv, vc1);
            float d2 = distance(uv, vc2);
            float d3 = distance(uv, vc3);
            float gr = mix(-0.2, 0.2, rand(uv + sin(time)));
            vec2 mv = vec2(time *0.05, time * -0.05);
            float f = ns((uv * d1 * 2.) + mv);
            f += ns((uv * d2 * 2.5) + vec2(time * -0.075, time * 0.05));
            f += gr;
            f = smoothstep(0., 2., f);
            // f = fract(f);
            float mx = smoothstep(0., 0.1, f) - smoothstep(0.5, 1., f);
            vec4 color = mix(c1, c2, f);
            float nPt = min(2. * pt, 2. * (1. - pt));
            float u = .3 * sin(m.x * PI + 0.25) * nPt;
            float d = -.3 * sin(m.x * PI + 0.25) * nPt;
            m.y -= mix(u, d, st);
            float ft = step(m.y, pt);
            vec2 rs = ps * (0.5 - vec2(fc * 0.35, fc));
            vec2 rs2 = ps * (0.5 - vec2(fc * 0.35, fc));
            float ra = r;
            vec2 yl = vUv;
            yl.y += 0.002;
            yl.x += 0.00125;
            float cr = ub(((vUv - vec2(fc * 0.35, fc * 0.75)) * ps) - rs, rs, ra);
            float cr2 = ub(((yl - vec2(fc * 0.35, fc * 0.75)) * vec2(ps.x * 0.99725, ps.y * 0.995)) - rs2, rs2, ra);
            cr = clamp(cr, 0.0, 1.);
            cr2 = clamp(cr2, 0.0, 1.);
            vec4 br = vec4(0.,0.,0.,0.);
            vec4 s1 =  mix(color, vec4(0.,0.,0., 1.), ft);
            vec3 brcl = vec3(77. / 255.);
            brcl += sw(yl, vec2(0.5), 1.5, 0.00003,0.00001, 1.) * vec3(85./255.);
            vec4 final = mix(s1, la(mix(vec4(brcl,1.), vec4(0.), cr2),vec4(0.,0.,0.,1.)), cr);
          
            float alpha = 1.;
            float cut = 0.001;
            alpha *= aastep(cut, m2.x);
            alpha *= 1. - aastep(1. - cut, m2.x);
            alpha *= aastep(cut, m2.y);
            alpha *= 1. - aastep(1. - cut, m2.y);
          
            gl_FragColor =  vec4(final.rgb, alpha);
          }
        `,
      });
  
      // Create a geometry for the background
      this.geometry = new THREE.PlaneGeometry(this.width, this.height, 30, 30);
  
    // Create a mesh using the geometry and material
    this.mesh = new THREE.Mesh(this.geometry, this.material);

    // Scale the mesh to match the window size
    this.mesh.scale.set(window.innerWidth, window.innerHeight, 1);

    // Add the mesh to the scene
    this.scene = new THREE.Scene();
    this.scene.add(this.mesh);
  }

  animate = () => {
    requestAnimationFrame(this.animate);
    // Update your animation here
    // this.material.uniforms.time.value += 0.01; // Example animation
    this.renderer.render(this.scene, this.camera);
  };

  componentWillUnmount() {
    cancelAnimationFrame(this.animate)
  }

  
  render() {
    return (
      <div ref={this.containerRef}>
   
      </div>
    );
  }
}

export default BackgroundComponent;

This is what I have come up with but I am not anywhere near to what I am trying to achieve.