--- template/app/src/landing-page/components/Hero/Orbit.tsx
+++ opensaas-sh/app/src/landing-page/components/Hero/Orbit.tsx
@@ -0,0 +1,217 @@
+import { useEffect, useState } from 'react';
+import logo from '../../../client/static/logo.webp';
+import nodeLogoDark from '../../../client/static/logos/nodejs-dark.webp';
+import nodeLogo from '../../../client/static/logos/nodejs-light.webp';
+import stripeLogoDark from '../../../client/static/logos/stripe-dark.webp';
+import stripeLogo from '../../../client/static/logos/stripe-light.webp';
+import tailwindLogoDark from '../../../client/static/logos/tailwind-dark.webp';
+import tailwindLogo from '../../../client/static/logos/tailwind-light.webp';
+import { cn } from '../../../lib/utils';
+import AstroLogo from '../../logos/AstroLogo';
+import OpenAILogo from '../../logos/OpenAILogo';
+import PrismaLogo from '../../logos/PrismaLogo';
+import ReactLogo from '../../logos/ReactLogo';
+import ShadCNLogo from '../../logos/ShadCNLogo';
+
+interface LogoConfig {
+ id: string;
+ component: React.ComponentType;
+ circleIndex: number;
+ position: number;
+ size?: number;
+}
+
+const ImageLogo = ({
+ src,
+ alt,
+ className,
+ dark,
+}: {
+ src: string;
+ alt: string;
+ className?: string;
+ dark?: boolean;
+}) => {
+ return (
+
+ );
+};
+
+const logoConfigs: LogoConfig[] = [
+ {
+ id: 'wasp',
+ component: () => ,
+ circleIndex: 1,
+ position: 0,
+ },
+ { id: 'openai', component: OpenAILogo, circleIndex: 1, position: 120, size: 24 },
+ { id: 'astro', component: AstroLogo, circleIndex: 1, position: 270, size: 24 },
+ { id: 'prisma', component: PrismaLogo, circleIndex: 2, position: 90, size: 24 },
+ { id: 'shadcn', component: ShadCNLogo, circleIndex: 2, position: 210, size: 24 },
+ {
+ id: 'tailwind-light',
+ component: () => (
+
+ ),
+ circleIndex: 2,
+ position: 330,
+ },
+ {
+ id: 'tailwind-dark',
+ component: () => ,
+ circleIndex: 2,
+ position: 330,
+ },
+ {
+ id: 'stripe-light',
+ component: () => ,
+ circleIndex: 3,
+ position: 180,
+ },
+ {
+ id: 'stripe-dark',
+ component: () => ,
+ circleIndex: 3,
+ position: 180,
+ },
+ { id: 'react', component: ReactLogo, circleIndex: 3, position: 300, size: 32 },
+ {
+ id: 'node-light',
+ component: () => ,
+ circleIndex: 3,
+ position: 50,
+ },
+ {
+ id: 'node-dark',
+ component: () => ,
+ circleIndex: 3,
+ position: 50,
+ },
+];
+
+const circles = [
+ { radius: 120, rotationSpeed: 0.5, circleRotationSpeed: 0.2 }, // Innermost circle
+ { radius: 180, rotationSpeed: 0.3, circleRotationSpeed: 0.15 }, // Second circle
+ { radius: 240, rotationSpeed: 0.2, circleRotationSpeed: 0.1 }, // Third circle
+ { radius: 300, rotationSpeed: 0.1, circleRotationSpeed: 0.05 }, // Outermost circle
+];
+
+const gradients = [];
+
+export default function Orbit() {
+ const [rotation, setRotation] = useState(0);
+
+ useEffect(() => {
+ const animate = () => {
+ setRotation((prev) => prev + 0.5);
+ };
+
+ const interval = setInterval(animate, 50);
+ return () => clearInterval(interval);
+ }, []);
+
+ const getLogoPosition = (circleIndex: number, position: number, rotation: number) => {
+ const circle = circles[circleIndex];
+ const totalRotation = rotation * circle.rotationSpeed + position;
+ const radians = (totalRotation * Math.PI) / 180;
+
+ return {
+ x: Math.cos(radians) * circle.radius,
+ y: Math.sin(radians) * circle.radius,
+ };
+ };
+
+ return (
+
+
+
+ {circles.map((circle, circleIndex) => {
+ const gradients = [
+ `conic-gradient(from ${rotation * circle.circleRotationSpeed}deg,
+ hsl(var(--primary) / 0.15),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.15),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.05),
+ hsl(var(--primary) / 0.15)
+ )`,
+ `conic-gradient(from ${rotation * circle.circleRotationSpeed + 45}deg,
+ hsl(var(--primary) / 0.12),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.08),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.2),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.12)
+ )`,
+ `conic-gradient(from ${rotation * circle.circleRotationSpeed + 90}deg,
+ hsl(var(--primary) / 0.1),
+ hsl(var(--primary) / 0.18),
+ hsl(var(--primary) / 0.1),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.15),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.1)
+ )`,
+ `conic-gradient(from ${rotation * circle.circleRotationSpeed + 135}deg,
+ hsl(var(--primary) / 0.08),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.16),
+ hsl(var(--primary) / 0.06),
+ hsl(var(--primary) / 0),
+ hsl(var(--primary) / 0.12),
+ hsl(var(--primary) / 0.08)
+ )`,
+ ];
+
+ return (
+
+ );
+ })}
+
+ {logoConfigs.map((logoConfig) => {
+ const { x, y } = getLogoPosition(logoConfig.circleIndex, logoConfig.position, rotation);
+ const LogoComponent = logoConfig.component;
+ const logoSize = logoConfig.size || 32;
+
+ return (
+
+
+
+ );
+ })}
+
+ );
+}