From 9bfa6f456b1893d36609c6595a60af8bfbbb9605 Mon Sep 17 00:00:00 2001 From: BLACKBOX Agent Date: Mon, 10 Nov 2025 17:12:59 +0000 Subject: [PATCH] Create a 3D interactive website concept for Full L... --- fulllink-website/app/globals.css | 85 ++++++++ fulllink-website/app/layout.tsx | 19 ++ .../components/ConnectionFlow.tsx | 101 +++++++++ fulllink-website/components/FloatingCards.tsx | 129 +++++++++++ fulllink-website/components/Hero3D.tsx | 65 ++++++ fulllink-website/components/MouseFollower.tsx | 54 +++++ fulllink-website/components/Navbar.tsx | 80 +++++++ fulllink-website/components/OrbitingIcons.tsx | 202 ++++++++++++++++++ .../components/ParallaxSection.tsx | 142 ++++++++++++ fulllink-website/next.config.ts | 8 + fulllink-website/package.json | 30 +++ fulllink-website/postcss.config.js | 6 + fulllink-website/tailwind.config.ts | 48 +++++ fulllink-website/tsconfig.json | 27 +++ 14 files changed, 996 insertions(+) create mode 100644 fulllink-website/app/globals.css create mode 100644 fulllink-website/app/layout.tsx create mode 100644 fulllink-website/components/ConnectionFlow.tsx create mode 100644 fulllink-website/components/FloatingCards.tsx create mode 100644 fulllink-website/components/Hero3D.tsx create mode 100644 fulllink-website/components/MouseFollower.tsx create mode 100644 fulllink-website/components/Navbar.tsx create mode 100644 fulllink-website/components/OrbitingIcons.tsx create mode 100644 fulllink-website/components/ParallaxSection.tsx create mode 100644 fulllink-website/next.config.ts create mode 100644 fulllink-website/package.json create mode 100644 fulllink-website/postcss.config.js create mode 100644 fulllink-website/tailwind.config.ts create mode 100644 fulllink-website/tsconfig.json diff --git a/fulllink-website/app/globals.css b/fulllink-website/app/globals.css new file mode 100644 index 000000000..890c7872b --- /dev/null +++ b/fulllink-website/app/globals.css @@ -0,0 +1,85 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=Cairo:wght@300;400;600;700;900&display=swap'); + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: 'Inter', sans-serif; + background-color: #0A1628; + color: #ffffff; + overflow-x: hidden; +} + +.arabic { + font-family: 'Cairo', sans-serif; + direction: rtl; +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: #0A1628; +} + +::-webkit-scrollbar-thumb { + background: #00D4FF; + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: #33ddff; +} + +/* Glow effects */ +.glow-text { + text-shadow: 0 0 10px rgba(0, 212, 255, 0.5), + 0 0 20px rgba(0, 212, 255, 0.3), + 0 0 30px rgba(0, 212, 255, 0.2); +} + +.glow-box { + box-shadow: 0 0 20px rgba(0, 212, 255, 0.3), + 0 0 40px rgba(0, 212, 255, 0.2), + inset 0 0 20px rgba(0, 212, 255, 0.1); +} + +/* Glass morphism */ +.glass { + background: rgba(255, 255, 255, 0.05); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +/* Gradient text */ +.gradient-text { + background: linear-gradient(135deg, #ffffff 0%, #00D4FF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Neon border */ +.neon-border { + border: 2px solid #00D4FF; + box-shadow: 0 0 10px rgba(0, 212, 255, 0.5), + inset 0 0 10px rgba(0, 212, 255, 0.2); +} + +/* Smooth transitions */ +.transition-smooth { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} diff --git a/fulllink-website/app/layout.tsx b/fulllink-website/app/layout.tsx new file mode 100644 index 000000000..00753fb36 --- /dev/null +++ b/fulllink-website/app/layout.tsx @@ -0,0 +1,19 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "Full Link - Connect Your World in One Link", + description: "Smart digital tool that combines all social media profiles, business links, and contact info into one customizable link.", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/fulllink-website/components/ConnectionFlow.tsx b/fulllink-website/components/ConnectionFlow.tsx new file mode 100644 index 000000000..4196f3cd5 --- /dev/null +++ b/fulllink-website/components/ConnectionFlow.tsx @@ -0,0 +1,101 @@ +"use client"; + +import { useRef } from 'react'; +import { useFrame } from '@react-three/fiber'; +import * as THREE from 'three'; + +function FlowingLine({ start, end, color, delay }: { start: THREE.Vector3; end: THREE.Vector3; color: string; delay: number }) { + const lineRef = useRef(null); + const materialRef = useRef(null); + + useFrame((state) => { + if (materialRef.current) { + const opacity = (Math.sin(state.clock.getElapsedTime() * 2 + delay) + 1) / 2; + materialRef.current.opacity = opacity * 0.8; + } + }); + + const points = []; + const segments = 20; + + for (let i = 0; i <= segments; i++) { + const t = i / segments; + const x = start.x + (end.x - start.x) * t; + const y = start.y + (end.y - start.y) * t + Math.sin(t * Math.PI) * 0.5; + const z = start.z + (end.z - start.z) * t; + points.push(new THREE.Vector3(x, y, z)); + } + + const geometry = new THREE.BufferGeometry().setFromPoints(points); + + return ( + + + + ); +} + +function Node({ position, color }: { position: [number, number, number]; color: string }) { + const meshRef = useRef(null); + + useFrame((state) => { + if (meshRef.current) { + const scale = 1 + Math.sin(state.clock.getElapsedTime() * 3) * 0.2; + meshRef.current.scale.set(scale, scale, scale); + } + }); + + return ( + + + + + + ); +} + +export default function ConnectionFlow() { + const nodes = [ + { pos: [-3, 2, 0] as [number, number, number], color: '#E4405F' }, + { pos: [-2, -1, 0] as [number, number, number], color: '#25D366' }, + { pos: [0, 2.5, 0] as [number, number, number], color: '#0A66C2' }, + { pos: [2, -1, 0] as [number, number, number], color: '#FF0000' }, + { pos: [3, 1.5, 0] as [number, number, number], color: '#1DA1F2' }, + { pos: [0, 0, 0] as [number, number, number], color: '#00D4FF' }, + ]; + + return ( + <> + + + + {/* Nodes */} + {nodes.map((node, index) => ( + + ))} + + {/* Connecting lines to center */} + {nodes.slice(0, -1).map((node, index) => ( + + ))} + + ); +} diff --git a/fulllink-website/components/FloatingCards.tsx b/fulllink-website/components/FloatingCards.tsx new file mode 100644 index 000000000..beef07f60 --- /dev/null +++ b/fulllink-website/components/FloatingCards.tsx @@ -0,0 +1,129 @@ +"use client"; + +import { motion } from 'framer-motion'; +import { useState } from 'react'; + +interface CardProps { + title: string; + description: string; + icon: string; + delay: number; +} + +function Card({ title, description, icon, delay }: CardProps) { + const [isHovered, setIsHovered] = useState(false); + + return ( + setIsHovered(true)} + onHoverEnd={() => setIsHovered(false)} + className="glass rounded-2xl p-8 relative overflow-hidden group cursor-pointer" + > + {/* Glow effect on hover */} + + + {/* Icon */} + + {icon} + + + {/* Content */} +

{title}

+

{description}

+ + {/* Animated border */} + + + ); +} + +export default function FloatingCards() { + const cards = [ + { + title: "One Link", + description: "Combine all your social media, websites, and contact information into a single, powerful link.", + icon: "🔗", + }, + { + title: "Customizable", + description: "Design your page to match your brand with custom themes, colors, and layouts.", + icon: "🎨", + }, + { + title: "Analytics", + description: "Track clicks, views, and engagement with detailed analytics and insights.", + icon: "📊", + }, + { + title: "Fast & Secure", + description: "Lightning-fast loading times with enterprise-grade security for your data.", + icon: "⚡", + }, + { + title: "Mobile First", + description: "Optimized for mobile devices to ensure the best experience for your audience.", + icon: "📱", + }, + { + title: "Easy Setup", + description: "Get started in minutes with our intuitive interface and simple setup process.", + icon: "✨", + }, + ]; + + return ( +
+ {/* Background gradient */} +
+ +
+ {/* Section header */} + +

+ Why Choose Full Link? +

+

+ Everything you need to create a powerful digital presence in one place +

+
+ + {/* Cards grid */} +
+ {cards.map((card, index) => ( + + ))} +
+
+
+ ); +} diff --git a/fulllink-website/components/Hero3D.tsx b/fulllink-website/components/Hero3D.tsx new file mode 100644 index 000000000..deda89e2e --- /dev/null +++ b/fulllink-website/components/Hero3D.tsx @@ -0,0 +1,65 @@ +"use client"; + +import { Canvas } from '@react-three/fiber'; +import { OrbitControls, PerspectiveCamera } from '@react-three/drei'; +import { Suspense } from 'react'; +import OrbitingIcons from './OrbitingIcons'; + +export default function Hero3D() { + return ( +
+ + + + + + + + + + + {/* Hero text overlay */} +
+
+

+ Full Link +

+ +

+ Connect Your World in One Link +

+ +

+ ربط عالمك برابط واحد +

+ +
+ + +
+
+
+ + {/* Scroll indicator */} +
+
+
+
+
+
+ ); +} diff --git a/fulllink-website/components/MouseFollower.tsx b/fulllink-website/components/MouseFollower.tsx new file mode 100644 index 000000000..07660de7d --- /dev/null +++ b/fulllink-website/components/MouseFollower.tsx @@ -0,0 +1,54 @@ +"use client"; + +import { useEffect, useState } from 'react'; +import { motion, useSpring } from 'framer-motion'; + +export default function MouseFollower() { + const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); + + const springConfig = { damping: 25, stiffness: 150 }; + const x = useSpring(0, springConfig); + const y = useSpring(0, springConfig); + + useEffect(() => { + const handleMouseMove = (e: MouseEvent) => { + setMousePosition({ x: e.clientX, y: e.clientY }); + x.set(e.clientX); + y.set(e.clientY); + }; + + window.addEventListener('mousemove', handleMouseMove); + return () => window.removeEventListener('mousemove', handleMouseMove); + }, [x, y]); + + return ( + <> + {/* Main cursor glow */} + +
+
+ + {/* Secondary glow */} + +
+
+ + ); +} diff --git a/fulllink-website/components/Navbar.tsx b/fulllink-website/components/Navbar.tsx new file mode 100644 index 000000000..cfb2834ba --- /dev/null +++ b/fulllink-website/components/Navbar.tsx @@ -0,0 +1,80 @@ +"use client"; + +import { motion, useScroll, useTransform } from 'framer-motion'; +import { useState, useEffect } from 'react'; + +export default function Navbar() { + const [isScrolled, setIsScrolled] = useState(false); + const { scrollY } = useScroll(); + const backgroundColor = useTransform( + scrollY, + [0, 100], + ['rgba(10, 22, 40, 0)', 'rgba(10, 22, 40, 0.95)'] + ); + + useEffect(() => { + const handleScroll = () => { + setIsScrolled(window.scrollY > 50); + }; + + window.addEventListener('scroll', handleScroll); + return () => window.removeEventListener('scroll', handleScroll); + }, []); + + return ( + +
+
+ {/* Logo */} + +
+ FL +
+ Full Link +
+ + {/* Navigation Links */} + + {['Features', 'Pricing', 'About', 'Contact'].map((item, index) => ( + + {item} + + + ))} + + + {/* CTA Button */} + + Sign Up + +
+
+
+ ); +} diff --git a/fulllink-website/components/OrbitingIcons.tsx b/fulllink-website/components/OrbitingIcons.tsx new file mode 100644 index 000000000..86f41e923 --- /dev/null +++ b/fulllink-website/components/OrbitingIcons.tsx @@ -0,0 +1,202 @@ +"use client"; + +import { useRef, useMemo } from 'react'; +import { useFrame } from '@react-three/fiber'; +import { Text, RoundedBox } from '@react-three/drei'; +import * as THREE from 'three'; + +interface IconProps { + position: [number, number, number]; + color: string; + label: string; + delay: number; +} + +function SocialIcon({ position, color, label, delay }: IconProps) { + const meshRef = useRef(null); + const groupRef = useRef(null); + + useFrame((state) => { + if (groupRef.current) { + const time = state.clock.getElapsedTime() + delay; + + // Orbital rotation + groupRef.current.position.x = Math.cos(time * 0.5) * 3; + groupRef.current.position.z = Math.sin(time * 0.5) * 3; + groupRef.current.position.y = Math.sin(time * 0.3) * 1.5; + + // Self rotation + groupRef.current.rotation.y = time * 0.5; + } + + if (meshRef.current) { + // Floating animation + meshRef.current.position.y = Math.sin(state.clock.getElapsedTime() * 2 + delay) * 0.1; + } + }); + + return ( + + + + + + {/* Glow effect */} + + + {/* Icon label */} + + {label} + + + ); +} + +function CentralHub() { + const meshRef = useRef(null); + const glowRef = useRef(null); + + useFrame((state) => { + if (meshRef.current) { + meshRef.current.rotation.y = state.clock.getElapsedTime() * 0.3; + meshRef.current.rotation.x = Math.sin(state.clock.getElapsedTime() * 0.2) * 0.2; + } + + if (glowRef.current) { + const scale = 1 + Math.sin(state.clock.getElapsedTime() * 2) * 0.1; + glowRef.current.scale.set(scale, scale, scale); + } + }); + + return ( + + {/* Main hub */} + + + + + + {/* Inner sphere */} + + + + + + {/* Glow sphere */} + + + + + + {/* Central light */} + + + ); +} + +export default function OrbitingIcons() { + const socialIcons = useMemo(() => [ + { label: 'IG', color: '#E4405F', delay: 0 }, + { label: 'WA', color: '#25D366', delay: 1 }, + { label: 'TT', color: '#000000', delay: 2 }, + { label: 'LI', color: '#0A66C2', delay: 3 }, + { label: 'YT', color: '#FF0000', delay: 4 }, + { label: 'TW', color: '#1DA1F2', delay: 5 }, + ], []); + + return ( + <> + {/* Ambient lighting */} + + + {/* Main directional light */} + + + {/* Central hub */} + + + {/* Orbiting social icons */} + {socialIcons.map((icon, index) => ( + + ))} + + {/* Particle field */} + + + ); +} + +function Stars() { + const count = 200; + const positions = useMemo(() => { + const pos = new Float32Array(count * 3); + for (let i = 0; i < count; i++) { + pos[i * 3] = (Math.random() - 0.5) * 20; + pos[i * 3 + 1] = (Math.random() - 0.5) * 20; + pos[i * 3 + 2] = (Math.random() - 0.5) * 20; + } + return pos; + }, []); + + return ( + + + + + + + ); +} diff --git a/fulllink-website/components/ParallaxSection.tsx b/fulllink-website/components/ParallaxSection.tsx new file mode 100644 index 000000000..f77ea99e5 --- /dev/null +++ b/fulllink-website/components/ParallaxSection.tsx @@ -0,0 +1,142 @@ +"use client"; + +import { motion, useScroll, useTransform } from 'framer-motion'; +import { useRef } from 'react'; +import { Canvas } from '@react-three/fiber'; +import { Suspense } from 'react'; +import ConnectionFlow from './ConnectionFlow'; + +interface SectionProps { + title: string; + description: string; + features: string[]; + index: number; +} + +function FeatureSection({ title, description, features, index }: SectionProps) { + const ref = useRef(null); + const { scrollYProgress } = useScroll({ + target: ref, + offset: ["start end", "end start"] + }); + + const y = useTransform(scrollYProgress, [0, 1], [100, -100]); + const opacity = useTransform(scrollYProgress, [0, 0.3, 0.7, 1], [0, 1, 1, 0]); + const scale = useTransform(scrollYProgress, [0, 0.3, 0.7, 1], [0.8, 1, 1, 0.8]); + + return ( + +
+ {/* Content */} +
+ + {title} + + + + {description} + + + + {features.map((feature, idx) => ( + +
+ + {feature} + +
+ ))} +
+
+ + {/* 3D Visualization */} + + + + + + + +
+
+ ); +} + +export default function ParallaxSections() { + const sections = [ + { + title: "For Businesses", + description: "Streamline your digital presence and make it easy for customers to find everything they need in one place.", + features: [ + "Centralize all business links", + "Track engagement analytics", + "Custom branding options", + "QR code generation" + ] + }, + { + title: "For Influencers", + description: "Maximize your reach by connecting all your social platforms and content in a single, shareable link.", + features: [ + "Multi-platform integration", + "Monetization tools", + "Audience insights", + "Content scheduling" + ] + }, + { + title: "For Creators", + description: "Showcase your portfolio, products, and services with a beautiful, customizable landing page.", + features: [ + "Portfolio showcase", + "E-commerce integration", + "Booking system", + "Media gallery" + ] + } + ]; + + return ( +
+ {sections.map((section, index) => ( + + ))} +
+ ); +} diff --git a/fulllink-website/next.config.ts b/fulllink-website/next.config.ts new file mode 100644 index 000000000..7bab987f0 --- /dev/null +++ b/fulllink-website/next.config.ts @@ -0,0 +1,8 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + reactStrictMode: true, + transpilePackages: ['three'], +}; + +export default nextConfig; diff --git a/fulllink-website/package.json b/fulllink-website/package.json new file mode 100644 index 000000000..98830b75f --- /dev/null +++ b/fulllink-website/package.json @@ -0,0 +1,30 @@ +{ + "name": "fulllink-website", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@react-three/drei": "^9.117.3", + "@react-three/fiber": "^8.17.10", + "framer-motion": "^11.11.17", + "next": "^15.0.3", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "three": "^0.170.0" + }, + "devDependencies": { + "@types/node": "^22.9.0", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "@types/three": "^0.170.0", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3" + } +} diff --git a/fulllink-website/postcss.config.js b/fulllink-website/postcss.config.js new file mode 100644 index 000000000..12a703d90 --- /dev/null +++ b/fulllink-website/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/fulllink-website/tailwind.config.ts b/fulllink-website/tailwind.config.ts new file mode 100644 index 000000000..dca47abaa --- /dev/null +++ b/fulllink-website/tailwind.config.ts @@ -0,0 +1,48 @@ +import type { Config } from "tailwindcss"; + +const config: Config = { + content: [ + "./pages/**/*.{js,ts,jsx,tsx,mdx}", + "./components/**/*.{js,ts,jsx,tsx,mdx}", + "./app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + navy: { + DEFAULT: '#0A1628', + light: '#1a2942', + dark: '#050b14', + }, + electric: { + DEFAULT: '#00D4FF', + light: '#33ddff', + dark: '#00a8cc', + }, + }, + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + 'neon-glow': 'radial-gradient(circle at center, rgba(0, 212, 255, 0.3) 0%, transparent 70%)', + }, + animation: { + 'float': 'float 6s ease-in-out infinite', + 'pulse-slow': 'pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite', + 'glow': 'glow 2s ease-in-out infinite alternate', + }, + keyframes: { + float: { + '0%, 100%': { transform: 'translateY(0px)' }, + '50%': { transform: 'translateY(-20px)' }, + }, + glow: { + '0%': { boxShadow: '0 0 5px rgba(0, 212, 255, 0.5), 0 0 10px rgba(0, 212, 255, 0.3)' }, + '100%': { boxShadow: '0 0 20px rgba(0, 212, 255, 0.8), 0 0 30px rgba(0, 212, 255, 0.5)' }, + }, + }, + }, + }, + plugins: [], +}; + +export default config; diff --git a/fulllink-website/tsconfig.json b/fulllink-website/tsconfig.json new file mode 100644 index 000000000..d8b93235f --- /dev/null +++ b/fulllink-website/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +}