guoqqqi commented on a change in pull request #617:
URL: https://github.com/apache/apisix-website/pull/617#discussion_r716216294



##########
File path: website/src/pages/sections/architecture.jsx
##########
@@ -0,0 +1,88 @@
+import React, { useEffect } from "react";
+import HLDesign from "../../assets/images/infographs/Architecture.svg";
+import "../../css/customTheme.css";
+import gsap from "gsap";
+import Pattern from "../../assets/images/PatternGrouped.svg";
+
+function Architecture(props) {
+
+    const screenWidth = props.screenWidth;
+
+    useEffect(() => {
+        let strokePaths = []
+        for (let i=1; i<28; i++) {
+            strokePaths.push(".PatternGrouped_svg__p"+i);
+        } 
+
+        let tlStroke = gsap.timeline({
+            paused: true,
+            defaults: {
+                ease: "power2.inOut",
+                yoyo: true,
+                repeat: -1,
+            },
+        });
+
+        tlStroke.fromTo(strokePaths, {
+            strokeDashoffset: 10000
+        }, {
+            strokeDashoffset: 0,
+            duration: 5,
+            stagger: 0.3,
+            ease: "power2.inOut",
+            stroke: "red",
+        });
+
+        let observer = new IntersectionObserver(onIntersection, {
+            root: null,
+            threshold: 0.4,
+        })
+          
+        function onIntersection(entries, opts){
+            entries.forEach(entry =>  {
+                if (entry.isIntersecting) {
+                    tlStroke.paused(false);
+                } else {
+                    tlStroke.paused(true);
+                }
+            }
+          );
+        }
+          
+        observer.observe( document.querySelector('.arch'));
+        
+        return () => {
+            tlStroke.pause(0).kill(true);
+            observer.disconnect();
+        }
+    }, []);
+
+    return (
+        <>
+            <div className="arch">
+                <div style={{position: "absolute", display: "flex", 
justifyContent: "center", alignItems: "center", height: "120vh"}}>
+                    <Pattern style={{width: "100%", strokeWidth: "3", zIndex: 
"-10", opacity: "0.25", strokeDasharray: "10000"}}/>
+                </div>
+                <div>
+                    <h3 className="arch-head">Building for large-scale, high 
value systems</h3>
+                </div>
+                <div className="arch-subtitle">
+                    <p>Apache APISIX lets you build Cloud-Native Microservices 
API gateways, delivering the ultimate performance, security, open source and 
scalable platform for all your APIs and microservices.</p> 
+                </div>
+                <div className="arch-card" style={{position: "relative"}}>
+                    <div className="hldesign">
+                        <HLDesign className="hldesign-graphic"/>
+                    </div>
+                    <div className="arch-card-caption">
+                        <p style={{width: screenWidth >=768 ? "50%" : 
"90%"}}>Apache APISIX is based on Nginx and etcd. Compared with traditional API 
gateways, APISIX has dynamic routing and hot-loading plugins</p>
+                    </div>
+                    <div className="arch-card-border">
+

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/comparison.jsx
##########
@@ -0,0 +1,80 @@
+import React from "react";
+import Cross from "../../assets/icons/cross.svg";
+import Tick from "../../assets/icons/tick.svg";
+import "../../css/customTheme.css";
+
+function Comparison() {
+
+    return (
+        <>
+            <div className="compare">
+                <div>
+                    <h3 className="compare-head">Among the best, and always 
improving</h3>
+                </div>
+                <div className="compare-subtitle">
+                    <p>Apache APISIX is opensource and ever evolving. Here’s a 
general comparison of APISIX with other options in this API Gateway 
ecosystem.</p> 
+                </div>
+                <div>
+

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/features.jsx
##########
@@ -0,0 +1,221 @@
+import React, { useState, useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import "../../css/customTheme.css";
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import Dashboard from "../../assets/images/apisix-dashboard.png";
+import Snippet from "../../assets/images/code-sample.png";
+import Plugin from "../../assets/images/pluginised.png";
+import ArrowAnim from "./components/arrowAnim";
+
+function Features() {
+    const dashboardDiv = useRef(null);
+    const userfDiv = useRef(null);
+    const pluginDiv = useRef(null);
+    const triggerDiv = useRef(null);
+    const triggerDivCol = useRef(null);
+    const pinDiv = useRef(null);
+    const img1 = useRef(null);
+    const img1col = useRef(null);
+    const img2 = useRef(null);
+    const img2col = useRef(null);
+    const img3 = useRef(null);
+    const img3col = useRef(null);
+    const featPin = useRef(null);
+
+    gsap.registerPlugin(ScrollTrigger);
+
+    const [screenWidth, setScreenWidth] = useState(typeof window !== 
'undefined' && window.innerWidth);
+    const [screenHeight, setScreenHeight] = useState(typeof window !== 
'undefined' && window.innerWidth);
+
+    useEffect(()=>{
+        setScreenHeight(window.innerHeight);
+        setScreenWidth(window.innerWidth);
+        window.addEventListener('resize', resizeEvent, false);
+
+        function resizeEvent(event) {
+            setScreenHeight(window.innerHeight);
+            setScreenWidth(window.innerWidth);
+        }
+
+        return () => {
+            window.removeEventListener('resize', resizeEvent);
+        }
+    }, [])
+
+    useEffect(() => {
+        const value = window.innerHeight*2;
+        
+        let tl;
+        let observers = [];
+
+        if(window.innerWidth > 1100) {
+            tl = gsap.timeline({
+                defaults: {
+                    ease: "linear" 
+                },
+                scrollTrigger: {
+                    id: "feat",
+                    trigger: triggerDiv.current,
+                    start: "top top",
+                    pin: pinDiv.current,
+                    scrub: 1.5,
+                    end: value+"px"
+                }
+            });
+    
+            tl.to(img1.current,{
+                opacity: 0,
+            })
+            .to(img2.current,{
+                opacity: 1,
+            })
+            .to(img2.current,{
+                opacity: 0,
+            })
+            .to(img3.current,{
+                opacity: 1, 
+            });
+        } else {
+            // Mobile
+              
+            const elems = [img1col.current, img2col.current, img3col.current]
+            for (let i=1; i<4; i++) {
+                observers.push(new IntersectionObserver((entries, opts)=>{
+                    entries.forEach(entry =>  {
+                        if (entry.isIntersecting) {
+                            observers[i-1].disconnect();
+                            gsap.fromTo(elems[i-1],{
+                                opacity: 0,
+                                y: 90,
+                            }, {
+                                opacity: 1,
+                                y: 0,
+                                duration: 0.5,
+                                ease: "power3.out",
+                                yoyo: true,
+                                yoyoEase: "power3.inOut",
+                            });
+                        }
+                    }
+                  );
+                }, {
+                    root: null,
+                    threshold: .2
+                }));
+            }
+
+            observers.forEach((it, index)=>{
+                it.observe(elems[index]);
+            });
+        }
+
+        return ()=>{
+            ScrollTrigger.getAll().forEach(t => t.kill());
+            if(window.innerWidth > 1100) {
+                tl.pause(0).kill(true);
+            }
+        }
+    }, []);
+
+    return (
+        <>
+            <div ref={featPin} className="feat-top" style={{padding: "50px 
0"}}>
+                <h3 className="feat-head-desc">Why APISIX ?</h3>
+                <h1 className="feat-head add-left-margin">Reduce time fighting 
bugs, focus on designing world-class systems</h1>
+                <p className="feat-desc add-left-margin">
+                Apache APISIX is the first Open source API gateway, with a 
built-in low-code Dashboard offering a powerful and flexible interface for 
developers to use 
+                </p>
+            </div>
+
+            <div className="feat-container-d" ref={triggerDiv}>
+                        {/* Desktop */}
+                <div className="left-pane" style={{width: "50%", height: 
"100%"}}>
+                            
+                    <div ref={dashboardDiv} style={{position: "relative"}}>
+                        <div className="text-div" style={{height: "100vh"}}>
+                            <h2 className="i-text 
add-left-margin-feat">Easy-to-use dashboard</h2>
+                            <p className="i-text-desc add-left-margin-feat">
+                                The Apache APISIX Dashboard is designed to 
make it as easy as possible for users to operate Apache APISIX through a 
frontend interface. It’s opensource and ever evolving, feel free to contribute.
+                            </p>
+                            <div className="hero-ctas add-left-margin-feat" 
style={{bottom: "34%"}}>
+                                <Link
+                                  to={useBaseUrl("downloads")}
+                                  className="btn btn-download">
+                                  Downloads
+                                </Link>
+                                <ArrowAnim />
+                            </div>
+                        </div>
+                    </div>
+
+                    <div ref={userfDiv} style={{position: "relative"}}>
+                        <div className="text-div" style={{height: "100vh"}}>
+                            <h2 className="i-text add-left-margin-feat" 
style={{top: "34%"}}>User flexible</h2>
+                            <p className="i-text-desc add-left-margin-feat">
+                            The Apache APISIX dashboard is flexible to User 
demand, providing option to create custom modules through code matching your 
requirements, alongside the existing no-code toolchain.                         
   
+                            </p>
+                        </div>
+                    </div>
+
+                    <div ref={pluginDiv} style={{position: "relative"}}>
+                        <div className="text-div" style={{height: "100vh"}}>
+                            <h2 className="i-text 
add-left-margin-feat">Pluginised workflow</h2>
+                            <p className="i-text-desc add-left-margin-feat">
+                                No need to reinvent the wheel again and again. 
Use inbuilt plugins to create high performance systems in tight deadlines. For 
something custom, there is option of building custom plugins. 
+                            </p>
+                        </div>
+                    </div>
+

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/newsSection.jsx
##########
@@ -0,0 +1,47 @@
+import React from "react";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import "../../css/customTheme.css";
+import ChevronRight from "../../assets/icons/chevron-right.svg";
+
+function NewsSection() {
+

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/architecture.jsx
##########
@@ -0,0 +1,88 @@
+import React, { useEffect } from "react";
+import HLDesign from "../../assets/images/infographs/Architecture.svg";
+import "../../css/customTheme.css";
+import gsap from "gsap";
+import Pattern from "../../assets/images/PatternGrouped.svg";
+
+function Architecture(props) {
+
+    const screenWidth = props.screenWidth;
+
+    useEffect(() => {
+        let strokePaths = []

Review comment:
       format code 
   > space 2

##########
File path: website/src/pages/index.js
##########
@@ -1,218 +1,103 @@
-const React = require("react");
-import Link from "@docusaurus/Link";
+import React, { useState, useEffect, useLayoutEffect } from "react";
 import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
-import useBaseUrl from "@docusaurus/useBaseUrl";
 import Layout from "@theme/Layout";
-import GitHubLogo from "../assets/icons/github-logo.svg";
-import { useState, useEffect } from "react";
-import { CSSTransition } from "react-transition-group";
-import ChevronRight from "../assets/icons/chevron-right.svg";
+import useThemeContext from '@theme/hooks/useThemeContext';
+import HeroSection from "./sections/heroSection";

Review comment:
       There should be a blank line between 4 and 5, as the line after 5 is 
introduced from an external file

##########
File path: website/src/pages/sections/benefits.jsx
##########
@@ -0,0 +1,357 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import { ScrollTrigger } from "gsap/ScrollTrigger";

Review comment:
       Add blank lines directly to 5, 6

##########
File path: website/src/pages/sections/benefits.jsx
##########
@@ -0,0 +1,357 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import Performance from "../../assets/images/infographs/performance.svg";
+import Security from "../../assets/images/infographs/security.svg";
+import Scale from "../../assets/images/infographs/scale.svg";
+import Dynamic from "../../assets/images/infographs/dynamic.svg";
+import Multiplatform from "../../assets/images/infographs/multiplatform.svg";
+import "../../css/customTheme.css";
+
+function Benefits(props) {
+

Review comment:
       Extra blank lines

##########
File path: website/src/pages/index.js
##########
@@ -1,218 +1,103 @@
-const React = require("react");
-import Link from "@docusaurus/Link";
+import React, { useState, useEffect, useLayoutEffect } from "react";
 import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
-import useBaseUrl from "@docusaurus/useBaseUrl";
 import Layout from "@theme/Layout";
-import GitHubLogo from "../assets/icons/github-logo.svg";
-import { useState, useEffect } from "react";
-import { CSSTransition } from "react-transition-group";
-import ChevronRight from "../assets/icons/chevron-right.svg";
+import useThemeContext from '@theme/hooks/useThemeContext';
+import HeroSection from "./sections/heroSection";
+import Architecture from "./sections/architecture";
+import Features from "./sections/features";
+import Benefits from "./sections/benefits";
+import Comparison from "./sections/comparison";
+import OpensourcePromo from "./sections/opensourcePromo";
+import NewsSection from "./sections/newsSection";
+import EndCTA from "./sections/endcta";
+import EventPosterCard from "./sections/components/eventPosterCard";
 
-const HomeSplash = () => {
-  const [featureWordIndex, setFeatureWordIndex] = useState(0);
-  const featureWords = ["Dynamic", "Real-Time", "Performant"];
+function useWindowSize() {

Review comment:
       Hey, why don't we use arrow functions consistently? like:
   `const UseWindowSize = () => {}`

##########
File path: website/src/pages/sections/comparison.jsx
##########
@@ -0,0 +1,80 @@
+import React from "react";
+import Cross from "../../assets/icons/cross.svg";
+import Tick from "../../assets/icons/tick.svg";
+import "../../css/customTheme.css";
+
+function Comparison() {
+

Review comment:
       It is best to use arrow functions consistently
   ```
   const Comparison = () => {}
   ```

##########
File path: website/src/pages/sections/architecture.jsx
##########
@@ -0,0 +1,88 @@
+import React, { useEffect } from "react";
+import HLDesign from "../../assets/images/infographs/Architecture.svg";
+import "../../css/customTheme.css";

Review comment:
       Externally referenced documents are placed together, internally 
referenced documents are placed together

##########
File path: website/src/pages/sections/benefits.jsx
##########
@@ -0,0 +1,357 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import Performance from "../../assets/images/infographs/performance.svg";
+import Security from "../../assets/images/infographs/security.svg";
+import Scale from "../../assets/images/infographs/scale.svg";
+import Dynamic from "../../assets/images/infographs/dynamic.svg";
+import Multiplatform from "../../assets/images/infographs/multiplatform.svg";
+import "../../css/customTheme.css";
+
+function Benefits(props) {
+
+    const triggerDiv = useRef(null);
+    const performance = useRef(null);
+    const security = useRef(null);
+    const scale = useRef(null);
+    const dynamic = useRef(null);
+    const multiplatform = useRef(null);
+
+    gsap.registerPlugin(ScrollTrigger);
+    
+    const screenWidth = props.screenWidth;
+
+    useEffect(() => {
+        let tweenTls = [];
+        let observers = [];
+
+        for (let i=0; i<5; i++) {
+            tweenTls.push(gsap.timeline({
+                paused: true,
+                yoyo: true, 
+                yoyoEase: "power3.out",
+                repeat: -1,
+                defaults: {
+                    yoyo: true,
+                    ease: "power3.inOut",
+                    yoyoEase: "power3.out"
+                },
+            }));
+        }
+
+        let cirs = [];
+        let ns = [];

Review comment:
       Bad variable names

##########
File path: website/src/pages/sections/benefits.jsx
##########
@@ -0,0 +1,357 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import Performance from "../../assets/images/infographs/performance.svg";
+import Security from "../../assets/images/infographs/security.svg";
+import Scale from "../../assets/images/infographs/scale.svg";
+import Dynamic from "../../assets/images/infographs/dynamic.svg";
+import Multiplatform from "../../assets/images/infographs/multiplatform.svg";
+import "../../css/customTheme.css";
+
+function Benefits(props) {
+
+    const triggerDiv = useRef(null);
+    const performance = useRef(null);
+    const security = useRef(null);
+    const scale = useRef(null);
+    const dynamic = useRef(null);
+    const multiplatform = useRef(null);
+
+    gsap.registerPlugin(ScrollTrigger);
+    
+    const screenWidth = props.screenWidth;
+
+    useEffect(() => {
+        let tweenTls = [];
+        let observers = [];
+
+        for (let i=0; i<5; i++) {
+            tweenTls.push(gsap.timeline({
+                paused: true,
+                yoyo: true, 
+                yoyoEase: "power3.out",
+                repeat: -1,
+                defaults: {
+                    yoyo: true,
+                    ease: "power3.inOut",
+                    yoyoEase: "power3.out"
+                },
+            }));
+        }
+
+        let cirs = [];
+        let ns = [];
+        const colors = ["#FE7F80", "white", "red"];
+        const pathColors = ["#FE7F80", "black"];
+
+        for (let i=1; i<28; i++) {
+            cirs.push(".scale_svg__cir"+i);
+            ns.push(".scale_svg__n"+i);
+        }
+        
+        // Performance anim
+        tweenTls[0].fromTo(".performance_svg__network",{   
+            strokeDashoffset: 1000, 
+            stroke: "black"
+        },{
+            strokeDashoffset: 0,
+            duration: 1,
+            strokeWidth: 5,
+            stroke: "orange",
+            ease: "power2.in",
+            yoyoEase: "power2.out",
+            repeat: -1,
+        })
+        .fromTo(".performance_svg__lightning",{
+            fill: "orange",
+        }, {
+            fill: "red",
+            duration: 1,
+            repeat: -1,
+        },"-=1");
+        
+        // Security anim
+        tweenTls[1].fromTo([".security_svg__malWarn-square", 
".security_svg__malConn"],{   
+            fill: "#FA5252",
+        },{
+            fill: "yellow",
+            duration: 0.5,
+            repeat: -1,
+            repeatDelay: 0.1,
+        })
+        for (let i = 1; i < 4; i++) {
+            tweenTls[1].fromTo(".security_svg__conn"+i, {
+                strokeWidth: 4,
+                strokeDasharray: 25,
+                strokeDashoffset: 200,
+            }, {
+                strokeDashoffset: 0,
+                duration: 2.5,
+                repeat: -1,
+                ease: "linear",
+                yoyoEase: "linear",
+            })
+        }
+
+        // Scaling anim
+        for (let i = 0; i < 27; i++) { 
+            tweenTls[2].fromTo(cirs[i],{
+                fill: gsap.utils.random(colors),
+            },{
+                fill:  gsap.utils.random(colors),
+                duration: 0.3,
+                repeat: -1,
+                repeatDelay: 0.1,
+            })
+            tweenTls[2].fromTo(ns[i],{
+                stroke: gsap.utils.random(pathColors),
+            },{
+                stroke:  gsap.utils.random(pathColors),
+                duration: 0.3,
+                repeat: -1,
+                repeatDelay: 0.1,
+            })
+        }
+        
+        // Dynamic anim
+        tweenTls[3].repeatDelay(1.5);
+        tweenTls[3].fromTo([".dynamic_svg__rcard"],{
+            x: -400,
+            opacity: 0,
+        },{
+            opacity: 1,
+            x: 0,
+            ease: "sin.inOut",
+            duration: 1.5,
+        })
+        .fromTo(".dynamic_svg__arrow", {
+            opacity: 0,
+        }, {
+            opacity: 1,
+            ease: "power3.out",
+            duration: 0.5,
+        })
+        .fromTo(".dynamic_svg__lightning", {
+            opacity: 0,
+            y: 10,
+        }, {
+            opacity: 1,
+            y: 0,
+            duration: 1,
+            ease: "power2.inOut",
+        });
+
+        // Multiplatform anim
+        for(let i = 1; i < 4; i++) {
+            tweenTls[4].fromTo(".multiplatform_svg__server-port"+i,{    
+                fill: "#60E0F2",
+            },{
+                fill: "#ffdc21",
+                duration: 0.5,
+            });
+        }
+        
+        let standloneObserver = new IntersectionObserver(onIntersection, {
+            root: null,
+            threshold: 0.4,
+        })
+
+        let rot = 0;
+        const tweenArrow = gsap.fromTo(".multiplatform_svg__arrows",
+        {
+            rotation: rot,
+        },{
+            rotation: -360+rot,
+            transformOrigin:"50% 50%",
+            ease: "power3.inOut",
+            duration: 3,
+            repeat: -1,
+            paused: true,
+            onComplete: () => {
+                rot -= 360;
+            }
+        });
+        const tweenFloat = gsap.fromTo(".multiplatform_svg__lightning",{
+            y: -2.5,
+        },{
+            y: 5,
+            duration: 1,
+            ease: "linear",
+            repeat: -1,
+            yoyo: true,
+            paused: true,
+            yoyoEase: "linear",
+        });
+
+        function onIntersection(entries, opts){
+            entries.forEach(entry =>  {
+                if (entry.isIntersecting) {
+                    tweenArrow.paused(false);
+                    tweenFloat.paused(false);
+                } else {
+                    tweenArrow.paused(true);
+                    tweenFloat.paused(true);
+                }
+            });
+        }
+          
+        standloneObserver.observe(multiplatform.current);
+
+        const elems = [performance.current, security.current, scale.current, 
dynamic.current, multiplatform.current];
+        for (let i=0; i<5; i++) {
+            observers.push(new IntersectionObserver((entries, opts)=>{
+                entries.forEach(entry =>  {
+                    if (entry.isIntersecting) {
+                        tweenTls[i].paused(false);
+                    } else {
+                        tweenTls[i].paused(true);
+                    }
+                }
+              );
+            }, {
+                root: null,
+                threshold: .2
+            }));
+        }
+
+        observers.forEach((it, index)=>{
+            it.observe(elems[index]);
+        });
+
+        return () => {
+            observers.forEach((it, index)=>{
+                it.disconnect();
+            });
+            tweenTls.forEach((it, index)=>{
+                it.pause(0).kill(true);
+            });
+        }
+    }, [])
+
+    useEffect(() => {
+        let tl;
+        if(window.innerWidth <= 768)
+        {
+            tl = gsap.timeline({
+                defaults: {
+                    ease: "linear" 
+                },
+                scrollTrigger: {
+                    trigger: triggerDiv.current,
+                    start: "top top",
+                    pin: triggerDiv.current,
+                    scrub: 1,
+                    end: "+=500%"
+                }
+            });
+    
+            tl.to(performance.current,{
+                opacity: 0,
+            })
+            .to(security.current,{
+                opacity: 1,
+            })
+            .to(security.current,{
+                opacity: 0,
+            })
+            .to(scale.current,{
+                opacity: 1, 
+            })
+            .to(scale.current,{
+                opacity: 0, 
+            })
+            .to(dynamic.current,{
+                opacity: 1, 
+            })
+            .to(dynamic.current,{
+                opacity: 0, 
+            })
+            .to(multiplatform.current,{
+                opacity: 1, 
+            });
+        }
+        return () => {
+            if(window.innerWidth <= 768) {
+                tl.pause(0).kill(true);
+                ScrollTrigger.getAll().forEach(t => t.kill());
+            }
+        }
+    },[])
+    
+    return (
+        <>
+            <div ref={triggerDiv} className="benefit" style={{ position: 
"relative"}}>
+                
+                <div ref={performance} className="row-benefit" >
+                    <div style={{width: screenWidth > 768 ? "50%" : "100%"}}>
+                        <h3 className="feat-head-desc">Performance</h3>
+                        <h1 className="feat-head add-left-margin">Ultimate 
performance </h1>
+                        <p className="feat-desc add-left-margin"> 
+                        Apache APISIX uses radixtree-route-matching and etcd 
under the hood to provide you the ability to create high speed synchronized 
systems. From routing to built-in plugins, all these are designed and 
implemented to be uber performant with the minimum latency possible.            
            
+                        </p>
+                    </div>
+                    <div className="benefit-infograph">
+                        <Performance style={{width: screenWidth >=768 ? "35%" 
: "40%"}}/>
+                    </div>
+                </div>
+
+                <div ref={security} className="row-benefit row-reverse 
row-hidden" >
+                    <div className="benefit-infograph">
+                        <Security style={{width: screenWidth >=768 ? "75%" : 
"100%", position: "relative", left: screenWidth >=768 ? "3%" : "0"}}/>
+                    </div>
+                    <div style={{width: screenWidth > 768 ? "50%" : "100%"}}>
+                        <h3 className="feat-head-desc">Security</h3>
+                        <h1 className="feat-head add-left-margin">Shield 
against the malicious</h1>
+                        <p className="feat-desc add-left-margin"> 
+                        Apache APISIX provides multiple security plugins for 
identity authentication and interface verification, putting stability and 
security first. For more information, check <Link style={{color: "#e8433e"}} 
to={useBaseUrl("docs/apisix/plugins/cors/")}>here</Link>.
+                        </p>
+                    </div>
+                </div>
+
+                <div ref={scale} className="row-benefit row-hidden" >
+                    <div style={{width: screenWidth > 768 ? "50%" : "100%"}}>
+                        <h3 className="feat-head-desc">Scalability and 
availability</h3>
+                        <h1 className="feat-head add-left-margin">Scales with 
your users</h1>
+                        <p className="feat-desc add-left-margin"> 
+                            Apache APISIX provides the ability to write your 
own custom plugins, use custom Load Balancing Algorithms during the balancer 
phase for scaling and custom Routing algorithms for fine control on routing.
+                        </p>
+                    </div>
+                    <div className="benefit-infograph">
+                        <Scale style={{width: screenWidth >=768 ? "50%": 
"60%"}}/>
+                    </div>
+                </div>
+
+                <div ref={dynamic} className="row-benefit row-reverse 
row-hidden" >
+                    <div className="benefit-infograph">
+                        <Dynamic style={{width: screenWidth >=768 ? "50%" : 
"70%"}}/>
+                    </div>
+                    <div style={{width: screenWidth > 768 ? "50%" : "100%"}}>
+                        <h3 className="feat-head-desc">Fully dynamic</h3>
+                        <h1 className="feat-head add-left-margin">Save 
dev-time, design what matters </h1>
+                        <p className="feat-desc add-left-margin"> 
+                            Apache APISIX provides Hot updates and Hot 
plugins, which continuosly update configurations without restarts, saving 
development time and stress. Health checks, circuit breakers and many more 
features keep the system balanced at all times.
+                        </p>
+                    </div>
+                </div>
+
+                <div ref={multiplatform} className="row-benefit row-hidden" >
+                    <div style={{width: screenWidth > 768 ? "50%" : "100%"}}>
+                        <h3 className="feat-head-desc">Multi-platform and 
protocol</h3>
+                        <h1 className="feat-head add-left-margin">Create once, 
run anywhere</h1>
+                        <p className="feat-desc add-left-margin"> 
+                            Platform agnostic, no vendor lock-in, Apache 
APISIX can run from bare-metal to kubernetes. It supports HTTP to gRPC 
transcoding, websockets, gRPC, Dubbo, MQTT proxy and multiple platforms 
including ARM64, don’t worry about the lock-in of the infra technology.
+                        </p>
+                    </div>
+                    <div className="benefit-infograph">
+                        <Multiplatform style={{width: screenWidth >=768 ? 
"50%" : "80%"}}/>
+                    </div>
+                </div>
+

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/endcta.jsx
##########
@@ -0,0 +1,31 @@
+import React from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";

Review comment:
       ditto

##########
File path: website/src/pages/sections/benefits.jsx
##########
@@ -0,0 +1,357 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import Performance from "../../assets/images/infographs/performance.svg";
+import Security from "../../assets/images/infographs/security.svg";
+import Scale from "../../assets/images/infographs/scale.svg";
+import Dynamic from "../../assets/images/infographs/dynamic.svg";
+import Multiplatform from "../../assets/images/infographs/multiplatform.svg";
+import "../../css/customTheme.css";
+
+function Benefits(props) {
+
+    const triggerDiv = useRef(null);
+    const performance = useRef(null);
+    const security = useRef(null);
+    const scale = useRef(null);
+    const dynamic = useRef(null);
+    const multiplatform = useRef(null);
+
+    gsap.registerPlugin(ScrollTrigger);
+    
+    const screenWidth = props.screenWidth;
+
+    useEffect(() => {
+        let tweenTls = [];
+        let observers = [];
+
+        for (let i=0; i<5; i++) {
+            tweenTls.push(gsap.timeline({
+                paused: true,
+                yoyo: true, 
+                yoyoEase: "power3.out",
+                repeat: -1,
+                defaults: {
+                    yoyo: true,
+                    ease: "power3.inOut",
+                    yoyoEase: "power3.out"
+                },
+            }));
+        }
+
+        let cirs = [];
+        let ns = [];
+        const colors = ["#FE7F80", "white", "red"];
+        const pathColors = ["#FE7F80", "black"];
+
+        for (let i=1; i<28; i++) {
+            cirs.push(".scale_svg__cir"+i);
+            ns.push(".scale_svg__n"+i);
+        }
+        
+        // Performance anim
+        tweenTls[0].fromTo(".performance_svg__network",{   
+            strokeDashoffset: 1000, 
+            stroke: "black"
+        },{
+            strokeDashoffset: 0,
+            duration: 1,
+            strokeWidth: 5,
+            stroke: "orange",
+            ease: "power2.in",
+            yoyoEase: "power2.out",
+            repeat: -1,
+        })
+        .fromTo(".performance_svg__lightning",{
+            fill: "orange",
+        }, {
+            fill: "red",
+            duration: 1,
+            repeat: -1,
+        },"-=1");
+        
+        // Security anim
+        tweenTls[1].fromTo([".security_svg__malWarn-square", 
".security_svg__malConn"],{   
+            fill: "#FA5252",
+        },{
+            fill: "yellow",
+            duration: 0.5,
+            repeat: -1,
+            repeatDelay: 0.1,
+        })
+        for (let i = 1; i < 4; i++) {
+            tweenTls[1].fromTo(".security_svg__conn"+i, {
+                strokeWidth: 4,
+                strokeDasharray: 25,
+                strokeDashoffset: 200,
+            }, {
+                strokeDashoffset: 0,
+                duration: 2.5,
+                repeat: -1,
+                ease: "linear",
+                yoyoEase: "linear",
+            })
+        }
+
+        // Scaling anim
+        for (let i = 0; i < 27; i++) { 
+            tweenTls[2].fromTo(cirs[i],{
+                fill: gsap.utils.random(colors),
+            },{
+                fill:  gsap.utils.random(colors),
+                duration: 0.3,
+                repeat: -1,
+                repeatDelay: 0.1,
+            })
+            tweenTls[2].fromTo(ns[i],{
+                stroke: gsap.utils.random(pathColors),
+            },{
+                stroke:  gsap.utils.random(pathColors),
+                duration: 0.3,
+                repeat: -1,
+                repeatDelay: 0.1,
+            })
+        }
+        
+        // Dynamic anim
+        tweenTls[3].repeatDelay(1.5);
+        tweenTls[3].fromTo([".dynamic_svg__rcard"],{
+            x: -400,
+            opacity: 0,
+        },{
+            opacity: 1,
+            x: 0,
+            ease: "sin.inOut",
+            duration: 1.5,
+        })
+        .fromTo(".dynamic_svg__arrow", {
+            opacity: 0,
+        }, {
+            opacity: 1,
+            ease: "power3.out",
+            duration: 0.5,
+        })
+        .fromTo(".dynamic_svg__lightning", {
+            opacity: 0,
+            y: 10,
+        }, {
+            opacity: 1,
+            y: 0,
+            duration: 1,
+            ease: "power2.inOut",
+        });
+
+        // Multiplatform anim
+        for(let i = 1; i < 4; i++) {
+            tweenTls[4].fromTo(".multiplatform_svg__server-port"+i,{    
+                fill: "#60E0F2",
+            },{
+                fill: "#ffdc21",
+                duration: 0.5,
+            });
+        }
+        
+        let standloneObserver = new IntersectionObserver(onIntersection, {
+            root: null,
+            threshold: 0.4,
+        })
+
+        let rot = 0;
+        const tweenArrow = gsap.fromTo(".multiplatform_svg__arrows",
+        {
+            rotation: rot,
+        },{
+            rotation: -360+rot,
+            transformOrigin:"50% 50%",
+            ease: "power3.inOut",
+            duration: 3,
+            repeat: -1,
+            paused: true,
+            onComplete: () => {
+                rot -= 360;
+            }
+        });
+        const tweenFloat = gsap.fromTo(".multiplatform_svg__lightning",{
+            y: -2.5,
+        },{
+            y: 5,
+            duration: 1,
+            ease: "linear",
+            repeat: -1,
+            yoyo: true,
+            paused: true,
+            yoyoEase: "linear",
+        });
+
+        function onIntersection(entries, opts){
+            entries.forEach(entry =>  {
+                if (entry.isIntersecting) {
+                    tweenArrow.paused(false);
+                    tweenFloat.paused(false);
+                } else {
+                    tweenArrow.paused(true);
+                    tweenFloat.paused(true);
+                }
+            });
+        }
+          
+        standloneObserver.observe(multiplatform.current);
+
+        const elems = [performance.current, security.current, scale.current, 
dynamic.current, multiplatform.current];
+        for (let i=0; i<5; i++) {
+            observers.push(new IntersectionObserver((entries, opts)=>{
+                entries.forEach(entry =>  {
+                    if (entry.isIntersecting) {
+                        tweenTls[i].paused(false);
+                    } else {
+                        tweenTls[i].paused(true);
+                    }
+                }
+              );
+            }, {
+                root: null,
+                threshold: .2
+            }));
+        }
+
+        observers.forEach((it, index)=>{
+            it.observe(elems[index]);
+        });
+
+        return () => {
+            observers.forEach((it, index)=>{
+                it.disconnect();
+            });
+            tweenTls.forEach((it, index)=>{
+                it.pause(0).kill(true);
+            });
+        }
+    }, [])
+
+    useEffect(() => {
+        let tl;
+        if(window.innerWidth <= 768)
+        {
+            tl = gsap.timeline({
+                defaults: {
+                    ease: "linear" 
+                },
+                scrollTrigger: {
+                    trigger: triggerDiv.current,
+                    start: "top top",
+                    pin: triggerDiv.current,
+                    scrub: 1,
+                    end: "+=500%"
+                }
+            });
+    
+            tl.to(performance.current,{
+                opacity: 0,
+            })
+            .to(security.current,{
+                opacity: 1,
+            })
+            .to(security.current,{
+                opacity: 0,
+            })
+            .to(scale.current,{
+                opacity: 1, 
+            })
+            .to(scale.current,{
+                opacity: 0, 
+            })
+            .to(dynamic.current,{
+                opacity: 1, 
+            })
+            .to(dynamic.current,{
+                opacity: 0, 
+            })
+            .to(multiplatform.current,{
+                opacity: 1, 
+            });
+        }
+        return () => {
+            if(window.innerWidth <= 768) {
+                tl.pause(0).kill(true);
+                ScrollTrigger.getAll().forEach(t => t.kill());
+            }
+        }
+    },[])
+    
+    return (
+        <>
+            <div ref={triggerDiv} className="benefit" style={{ position: 
"relative"}}>
+                

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/features.jsx
##########
@@ -0,0 +1,221 @@
+import React, { useState, useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"

Review comment:
       ditto

##########
File path: website/src/pages/sections/comparison.jsx
##########
@@ -0,0 +1,80 @@
+import React from "react";

Review comment:
       Should be separated from externally referenced documents

##########
File path: website/src/pages/sections/endcta.jsx
##########
@@ -0,0 +1,31 @@
+import React from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import "../../css/customTheme.css";
+import ArrowAnim from "./components/arrowAnim";
+import Rocket from "../../assets/images/rocket.gif";
+
+function EndCTA() {

Review comment:
       ditto

##########
File path: website/src/pages/sections/features.jsx
##########
@@ -0,0 +1,221 @@
+import React, { useState, useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import "../../css/customTheme.css";
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import Dashboard from "../../assets/images/apisix-dashboard.png";
+import Snippet from "../../assets/images/code-sample.png";
+import Plugin from "../../assets/images/pluginised.png";
+import ArrowAnim from "./components/arrowAnim";
+
+function Features() {
+    const dashboardDiv = useRef(null);
+    const userfDiv = useRef(null);
+    const pluginDiv = useRef(null);
+    const triggerDiv = useRef(null);
+    const triggerDivCol = useRef(null);
+    const pinDiv = useRef(null);
+    const img1 = useRef(null);
+    const img1col = useRef(null);
+    const img2 = useRef(null);
+    const img2col = useRef(null);
+    const img3 = useRef(null);
+    const img3col = useRef(null);
+    const featPin = useRef(null);
+
+    gsap.registerPlugin(ScrollTrigger);
+
+    const [screenWidth, setScreenWidth] = useState(typeof window !== 
'undefined' && window.innerWidth);
+    const [screenHeight, setScreenHeight] = useState(typeof window !== 
'undefined' && window.innerWidth);
+
+    useEffect(()=>{
+        setScreenHeight(window.innerHeight);
+        setScreenWidth(window.innerWidth);
+        window.addEventListener('resize', resizeEvent, false);
+
+        function resizeEvent(event) {
+            setScreenHeight(window.innerHeight);
+            setScreenWidth(window.innerWidth);
+        }
+
+        return () => {
+            window.removeEventListener('resize', resizeEvent);
+        }
+    }, [])
+
+    useEffect(() => {
+        const value = window.innerHeight*2;
+        
+        let tl;
+        let observers = [];
+
+        if(window.innerWidth > 1100) {
+            tl = gsap.timeline({
+                defaults: {
+                    ease: "linear" 
+                },
+                scrollTrigger: {
+                    id: "feat",
+                    trigger: triggerDiv.current,
+                    start: "top top",
+                    pin: pinDiv.current,
+                    scrub: 1.5,
+                    end: value+"px"
+                }
+            });
+    
+            tl.to(img1.current,{
+                opacity: 0,
+            })
+            .to(img2.current,{
+                opacity: 1,
+            })
+            .to(img2.current,{
+                opacity: 0,
+            })
+            .to(img3.current,{
+                opacity: 1, 
+            });
+        } else {
+            // Mobile
+              
+            const elems = [img1col.current, img2col.current, img3col.current]
+            for (let i=1; i<4; i++) {
+                observers.push(new IntersectionObserver((entries, opts)=>{
+                    entries.forEach(entry =>  {
+                        if (entry.isIntersecting) {
+                            observers[i-1].disconnect();
+                            gsap.fromTo(elems[i-1],{
+                                opacity: 0,
+                                y: 90,
+                            }, {
+                                opacity: 1,
+                                y: 0,
+                                duration: 0.5,
+                                ease: "power3.out",
+                                yoyo: true,
+                                yoyoEase: "power3.inOut",
+                            });
+                        }
+                    }
+                  );
+                }, {
+                    root: null,
+                    threshold: .2
+                }));
+            }
+
+            observers.forEach((it, index)=>{
+                it.observe(elems[index]);
+            });
+        }
+
+        return ()=>{
+            ScrollTrigger.getAll().forEach(t => t.kill());
+            if(window.innerWidth > 1100) {
+                tl.pause(0).kill(true);
+            }
+        }
+    }, []);
+
+    return (
+        <>
+            <div ref={featPin} className="feat-top" style={{padding: "50px 
0"}}>
+                <h3 className="feat-head-desc">Why APISIX ?</h3>
+                <h1 className="feat-head add-left-margin">Reduce time fighting 
bugs, focus on designing world-class systems</h1>
+                <p className="feat-desc add-left-margin">
+                Apache APISIX is the first Open source API gateway, with a 
built-in low-code Dashboard offering a powerful and flexible interface for 
developers to use 
+                </p>
+            </div>
+
+            <div className="feat-container-d" ref={triggerDiv}>
+                        {/* Desktop */}
+                <div className="left-pane" style={{width: "50%", height: 
"100%"}}>
+                            
+                    <div ref={dashboardDiv} style={{position: "relative"}}>
+                        <div className="text-div" style={{height: "100vh"}}>
+                            <h2 className="i-text 
add-left-margin-feat">Easy-to-use dashboard</h2>
+                            <p className="i-text-desc add-left-margin-feat">
+                                The Apache APISIX Dashboard is designed to 
make it as easy as possible for users to operate Apache APISIX through a 
frontend interface. It’s opensource and ever evolving, feel free to contribute.
+                            </p>
+                            <div className="hero-ctas add-left-margin-feat" 
style={{bottom: "34%"}}>
+                                <Link
+                                  to={useBaseUrl("downloads")}
+                                  className="btn btn-download">
+                                  Downloads
+                                </Link>
+                                <ArrowAnim />
+                            </div>
+                        </div>
+                    </div>
+
+                    <div ref={userfDiv} style={{position: "relative"}}>
+                        <div className="text-div" style={{height: "100vh"}}>
+                            <h2 className="i-text add-left-margin-feat" 
style={{top: "34%"}}>User flexible</h2>
+                            <p className="i-text-desc add-left-margin-feat">
+                            The Apache APISIX dashboard is flexible to User 
demand, providing option to create custom modules through code matching your 
requirements, alongside the existing no-code toolchain.                         
   
+                            </p>
+                        </div>
+                    </div>
+
+                    <div ref={pluginDiv} style={{position: "relative"}}>
+                        <div className="text-div" style={{height: "100vh"}}>
+                            <h2 className="i-text 
add-left-margin-feat">Pluginised workflow</h2>
+                            <p className="i-text-desc add-left-margin-feat">
+                                No need to reinvent the wheel again and again. 
Use inbuilt plugins to create high performance systems in tight deadlines. For 
something custom, there is option of building custom plugins. 
+                            </p>
+                        </div>
+                    </div>
+
+                </div>
+
+                <div ref={pinDiv} className="right-pane" style={{width: "50%", 
height: "100vh", position: "relative", overflow: "hidden", display: "flex", 
alignItems: "center", justifyContent: "center"}}>
+                    <img ref={img1} className="i-image imagePosition" 
src={Dashboard} loading="lazy" alt="apisix-dashboard"/>
+                    <img ref={img2} className="n-image imagePosition" 
src={Snippet} loading="lazy" alt="code-snippet"/>
+                    <img ref={img3} className="n-image imagePosition" 
src={Plugin} loading="lazy" alt="plugin-workflow"/>
+                </div>
+            </div>
+
+            <div className="feat-container-m" ref={triggerDivCol} 
style={{width: "100%"}}>
+                        {/* Mobile */}
+                <div ref={img1col} className="hiddenDiv-col" style={{height: 
"fit-content", padding: "0 0 40px 0"}}>
+                    <div style={{position: "relative", height: "100%"}}>
+                    <h2 className="add-left-margin" style={{width: 
"fit-content"}}>Easy-to-use dashboard</h2>
+                    <img className="i-image-col" src={Dashboard} alt=""/>
+                        <p className="i-text-desc-col add-left-margin">
+                        The Apache APISIX Dashboard is designed to make it as 
easy as possible for users to operate Apache APISIX through a frontend 
interface. It’s opensource and ever evolving, feel free to contribute.
+                        </p>
+                        <div className="hero-ctas add-left-margin" 
style={{width: "fit-content"}}>
+                            <Link
+                              to={useBaseUrl("downloads")}
+                              className="btn btn-download">
+                              Downloads
+                            </Link>
+                            <ArrowAnim />
+                        </div>
+                    </div>
+                </div>
+
+                <div ref={img2col} className="hiddenDiv-col" style={{height: 
"fit-content", padding: "20px 0"}}>
+                    <h2 className="add-left-margin" style={{width: 
"fit-content"}}>User flexible</h2>
+                    <img className="i-image-col" src={Snippet} alt=""/>
+                    <p className="i-text-desc-col add-left-margin">
+                    The Apache APISIX dashboard is flexible to User demand, 
providing option to create custom modules through code matching your 
requirements, alongside the existing no-code toolchain.                         
   
+                    </p>
+                </div>
+
+                <div ref={img3col} className="hiddenDiv-col" style={{height: 
"fit-content", padding: "20px 0"}}>
+                    <h2 className="add-left-margin" style={{width: 
"fit-content"}}>Pluginised workflow</h2>
+                    <img className="i-image-col" src={Plugin} alt=""/>
+                    <p className="i-text-desc-col add-left-margin">
+                        No need to reinvent the wheel again and again. Use 
inbuilt plugins to create high performance systems in tight deadlines. For 
something custom, there is option of building custom plugins. 
+                    </p>
+                </div>
+

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/features.jsx
##########
@@ -0,0 +1,221 @@
+import React, { useState, useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import "../../css/customTheme.css";
+import { ScrollTrigger } from "gsap/ScrollTrigger";
+import Dashboard from "../../assets/images/apisix-dashboard.png";
+import Snippet from "../../assets/images/code-sample.png";
+import Plugin from "../../assets/images/pluginised.png";
+import ArrowAnim from "./components/arrowAnim";
+
+function Features() {
+    const dashboardDiv = useRef(null);
+    const userfDiv = useRef(null);
+    const pluginDiv = useRef(null);
+    const triggerDiv = useRef(null);
+    const triggerDivCol = useRef(null);
+    const pinDiv = useRef(null);
+    const img1 = useRef(null);
+    const img1col = useRef(null);
+    const img2 = useRef(null);
+    const img2col = useRef(null);
+    const img3 = useRef(null);
+    const img3col = useRef(null);
+    const featPin = useRef(null);
+
+    gsap.registerPlugin(ScrollTrigger);
+
+    const [screenWidth, setScreenWidth] = useState(typeof window !== 
'undefined' && window.innerWidth);
+    const [screenHeight, setScreenHeight] = useState(typeof window !== 
'undefined' && window.innerWidth);
+
+    useEffect(()=>{
+        setScreenHeight(window.innerHeight);
+        setScreenWidth(window.innerWidth);
+        window.addEventListener('resize', resizeEvent, false);
+
+        function resizeEvent(event) {
+            setScreenHeight(window.innerHeight);
+            setScreenWidth(window.innerWidth);
+        }
+
+        return () => {
+            window.removeEventListener('resize', resizeEvent);
+        }
+    }, [])
+
+    useEffect(() => {
+        const value = window.innerHeight*2;
+        
+        let tl;
+        let observers = [];
+
+        if(window.innerWidth > 1100) {
+            tl = gsap.timeline({
+                defaults: {
+                    ease: "linear" 
+                },
+                scrollTrigger: {
+                    id: "feat",
+                    trigger: triggerDiv.current,
+                    start: "top top",
+                    pin: pinDiv.current,
+                    scrub: 1.5,
+                    end: value+"px"
+                }
+            });
+    
+            tl.to(img1.current,{
+                opacity: 0,
+            })
+            .to(img2.current,{
+                opacity: 1,
+            })
+            .to(img2.current,{
+                opacity: 0,
+            })
+            .to(img3.current,{
+                opacity: 1, 
+            });
+        } else {
+            // Mobile
+              
+            const elems = [img1col.current, img2col.current, img3col.current]
+            for (let i=1; i<4; i++) {
+                observers.push(new IntersectionObserver((entries, opts)=>{
+                    entries.forEach(entry =>  {
+                        if (entry.isIntersecting) {
+                            observers[i-1].disconnect();
+                            gsap.fromTo(elems[i-1],{
+                                opacity: 0,
+                                y: 90,
+                            }, {
+                                opacity: 1,
+                                y: 0,
+                                duration: 0.5,
+                                ease: "power3.out",
+                                yoyo: true,
+                                yoyoEase: "power3.inOut",
+                            });
+                        }
+                    }
+                  );
+                }, {
+                    root: null,
+                    threshold: .2
+                }));
+            }
+
+            observers.forEach((it, index)=>{
+                it.observe(elems[index]);
+            });
+        }
+
+        return ()=>{
+            ScrollTrigger.getAll().forEach(t => t.kill());
+            if(window.innerWidth > 1100) {
+                tl.pause(0).kill(true);
+            }
+        }
+    }, []);
+
+    return (
+        <>
+            <div ref={featPin} className="feat-top" style={{padding: "50px 
0"}}>
+                <h3 className="feat-head-desc">Why APISIX ?</h3>
+                <h1 className="feat-head add-left-margin">Reduce time fighting 
bugs, focus on designing world-class systems</h1>
+                <p className="feat-desc add-left-margin">
+                Apache APISIX is the first Open source API gateway, with a 
built-in low-code Dashboard offering a powerful and flexible interface for 
developers to use 
+                </p>
+            </div>
+
+            <div className="feat-container-d" ref={triggerDiv}>
+                        {/* Desktop */}
+                <div className="left-pane" style={{width: "50%", height: 
"100%"}}>
+                            

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/heroSection.jsx
##########
@@ -0,0 +1,64 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"

Review comment:
       ditto

##########
File path: website/src/pages/sections/opensourcePromo.jsx
##########
@@ -0,0 +1,47 @@
+import React from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import GitHub from "../../assets/icons/github-logo.svg";
+import YtPromo from "../../assets/videos/apisix.mp4";
+import OssCanvas from "./components/ossCanvas"
+import "../../css/customTheme.css";
+
+function OpensourcePromo(props) {
+
+    return (

Review comment:
       format code

##########
File path: website/src/pages/sections/heroSection.jsx
##########
@@ -0,0 +1,64 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import "../../css/customTheme.css";
+import HeroCanvas from "./components/heroCanvas"
+import ArrowAnim from "./components/arrowAnim";
+
+function HeroSection(props) {
+
+    const titleRef = useRef(0)
+    const subtitleRef = useRef(0)
+    const ctaRef = useRef(0)
+    const canRef = useRef(0)
+    
+    useEffect(() => {
+        
+        let tl = gsap.timeline({
+            defaults: {
+                delay: window.innerWidth >= 768 ? 1.5 : 0.01,
+                duration: 0.5,
+                ease: "Expo.easeInOut" 
+            },
+        });
+        
+        tl.fromTo([titleRef.current, subtitleRef.current, ctaRef.current],{
+            opacity: 0,
+            y: 10
+        },{
+            opacity: 1,
+            y: 0,
+            stagger: 0.3
+        });
+
+        return () => {
+            tl.pause(0).kill(true);
+        }
+    }, [])
+
+    return (
+        <>
+            <div className="hero-sec-wrap" style={{width: "100%"}}>
+                <div className="hero-text">
+                    <h2 ref={titleRef} className="hero-title 
hide-title"><span>Effortless and smooth</span> <span style={{color: 
"#E8433E"}}>API Traffic</span> management.</h2>
+                    <h3 ref={subtitleRef} className="hero-subtitle 
hide-subtitle">Apache APISIX provides rich traffic management features like 
Load Balancing, Dynamic Upstream, Canary Release, Circuit Breaking, 
Authentication, Observability, and more...</h3>
+                    <div ref={ctaRef} className="hero-ctas hide-ctas">
+                        <Link
+                          to={useBaseUrl("downloads")}
+                          className="btn btn-download">
+                          Downloads
+                        </Link>
+                        <ArrowAnim />
+                    </div>
+                </div>
+                <div ref={canRef} className="add-margin">
+                    <HeroCanvas></HeroCanvas>
+                </div>
+            </div>
+        </>
+    );
+  }
+  
+  export default HeroSection;

Review comment:
       ```suggestion
   export default HeroSection;
   ```

##########
File path: website/src/pages/sections/heroSection.jsx
##########
@@ -0,0 +1,64 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import "../../css/customTheme.css";
+import HeroCanvas from "./components/heroCanvas"
+import ArrowAnim from "./components/arrowAnim";
+
+function HeroSection(props) {
+
+    const titleRef = useRef(0)
+    const subtitleRef = useRef(0)
+    const ctaRef = useRef(0)
+    const canRef = useRef(0)
+    
+    useEffect(() => {
+        

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/heroSection.jsx
##########
@@ -0,0 +1,64 @@
+import React, { useRef, useEffect } from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import gsap from "gsap"
+import "../../css/customTheme.css";
+import HeroCanvas from "./components/heroCanvas"
+import ArrowAnim from "./components/arrowAnim";
+
+function HeroSection(props) {
+

Review comment:
       Extra blank lines

##########
File path: website/src/pages/sections/opensourcePromo.jsx
##########
@@ -0,0 +1,47 @@
+import React from "react";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";

Review comment:
       ditto

##########
File path: website/src/pages/sections/newsSection.jsx
##########
@@ -0,0 +1,47 @@
+import React from "react";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";

Review comment:
       ditto




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to