From d31b03bf776b2c452e4602cf9a21800e4a4b2bb2 Mon Sep 17 00:00:00 2001 From: fgrreloaded Date: Sun, 16 Feb 2025 14:56:18 +0530 Subject: [PATCH] added terminal design and tech stack --- .../web/src/app/(home)/_components/Navbar.tsx | 6 +- .../(home)/_components/TechConstellation.tsx | 163 ++++++++++++++++++ .../src/app/(home)/_components/Terminal.tsx | 56 ++++++ apps/web/src/app/(home)/layout.tsx | 6 + apps/web/src/app/(home)/page.tsx | 7 +- apps/web/src/app/global.css | 16 ++ apps/web/src/app/layout.tsx | 7 +- apps/web/src/lib/constant.ts | 105 +++++++++++ 8 files changed, 358 insertions(+), 8 deletions(-) create mode 100644 apps/web/src/app/(home)/_components/TechConstellation.tsx create mode 100644 apps/web/src/app/(home)/_components/Terminal.tsx create mode 100644 apps/web/src/lib/constant.ts diff --git a/apps/web/src/app/(home)/_components/Navbar.tsx b/apps/web/src/app/(home)/_components/Navbar.tsx index 19f82ba..f98c89d 100644 --- a/apps/web/src/app/(home)/_components/Navbar.tsx +++ b/apps/web/src/app/(home)/_components/Navbar.tsx @@ -55,10 +55,8 @@ const Navbar = () => {
; + toRef: React.RefObject; + containerRef: React.RefObject; + delay?: number; +}; + +const AnimatedBeam = ({ + fromRef, + toRef, + containerRef, + delay = 0, +}: TechConstellationProp) => { + const [path, setPath] = useState(""); + + useEffect(() => { + const updatePath = () => { + if (!fromRef.current || !toRef.current || !containerRef.current) return; + + const containerRect = containerRef.current.getBoundingClientRect(); + const fromRect = fromRef.current.getBoundingClientRect(); + const toRect = toRef.current.getBoundingClientRect(); + + const fromX = fromRect.left - containerRect.left + fromRect.width / 2; + const fromY = fromRect.top - containerRect.top + fromRect.height / 2; + const toX = toRect.left - containerRect.left + toRect.width / 2; + const toY = toRect.top - containerRect.top + toRect.height / 2; + + setPath( + `M ${fromX},${fromY} Q ${(fromX + toX) / 2},${(fromY + toY) / 2 - 50} ${toX},${toY}`, + ); + }; + + updatePath(); + window.addEventListener("resize", updatePath); + return () => window.removeEventListener("resize", updatePath); + }, [fromRef, toRef, containerRef]); + + return ( + + Tech Stack + + + + + + + + + + + + ); +}; + +const TechConstellation = () => { + const containerRef = useRef(null); + const centerRef = useRef(null); + const techRefs = useRef<{ [key: string]: HTMLDivElement | null }>({}); + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + setIsVisible(true); + }, []); + + return ( +
+
+ TS +
+ + {technologies.map((tech, index) => { + const radius = 250; + const x = Math.cos((tech.angle * Math.PI) / 180) * radius; + const y = Math.sin((tech.angle * Math.PI) / 180) * radius; + + return ( +
{ + techRefs.current[tech.name] = el; + }} + className={`absolute z-20 transform -translate-x-1/2 -translate-y-1/2 transition-all duration-1000 + ${isVisible ? "scale-100 opacity-100" : "scale-0 opacity-0"}`} + style={{ + left: `calc(50% + ${x}px)`, + top: `calc(50% + ${y}px)`, + transitionDelay: `${index * 100}ms`, + }} + > +
+ +
+ +
+ {tech.name} +

{tech.description}

+
+
+ ); + })} + + {isVisible && + technologies.map((tech, index) => ( + } + toRef={{ current: techRefs.current[tech.name] as HTMLElement }} + containerRef={containerRef as React.RefObject} + delay={index * 0.2} + /> + ))} + +
+ {[...Array(20)].map((_, i) => ( +
+ key={`star-${i}`} + className="absolute w-2 h-2 bg-blue-500 rounded-full opacity-20" + style={{ + left: `${Math.random() * 100}%`, + top: `${Math.random() * 100}%`, + animationDelay: `${Math.random() * 5}s`, + }} + /> + ))} +
+
+ ); +}; + +export default TechConstellation; diff --git a/apps/web/src/app/(home)/_components/Terminal.tsx b/apps/web/src/app/(home)/_components/Terminal.tsx new file mode 100644 index 0000000..431cc97 --- /dev/null +++ b/apps/web/src/app/(home)/_components/Terminal.tsx @@ -0,0 +1,56 @@ +import React from "react"; + +const TerminalDisplay = () => { + const TITLE_TEXT = ` +╔════════════════════════════════════════════════════════════╗ +║ ║ +║ ██████╗ ███████╗████████╗████████╗███████╗██████╗ ║ +║ ██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗ ║ +║ ██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝ ║ +║ ██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗ ║ +║ ██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║ ║ +║ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ║ +║ ║ +║ ████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗ ║ +║ ╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝ ║ +║ ██║ ███████╗ ██║ ███████║██║ █████╔╝ ║ +║ ██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗ ║ +║ ██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗ ║ +║ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ║ +║ ║ +║ The Modern Full-Stack Framework ║ +║ ║ +╚════════════════════════════════════════════════════════════╝ + `; + + return ( +
+
+
+
+
+
+
+
+
+ +
+
+ + ~ + $ + + npx create-better-t-stack@latest + +
+ +
+						{TITLE_TEXT}
+					
+
+
+
+ ); +}; + +export default TerminalDisplay; diff --git a/apps/web/src/app/(home)/layout.tsx b/apps/web/src/app/(home)/layout.tsx index ac646b2..0e550b5 100644 --- a/apps/web/src/app/(home)/layout.tsx +++ b/apps/web/src/app/(home)/layout.tsx @@ -1,7 +1,13 @@ import { baseOptions } from "@/app/layout.config"; import { HomeLayout } from "fumadocs-ui/layouts/home"; +import type { Metadata } from "next"; import type { ReactNode } from "react"; +export const metadata: Metadata = { + title: "Better-T-Stack", + description: "Unleash the power of better-t-stack", +}; + export default function Layout({ children }: { children: ReactNode }) { return {children}; } diff --git a/apps/web/src/app/(home)/page.tsx b/apps/web/src/app/(home)/page.tsx index f46e746..e1ae737 100644 --- a/apps/web/src/app/(home)/page.tsx +++ b/apps/web/src/app/(home)/page.tsx @@ -1,3 +1,4 @@ +"use client"; import ShinyText from "components/ShinyText/ShinyText"; import { Poppins } from "next/font/google"; import React from "react"; @@ -6,6 +7,8 @@ import CodeContainer from "./_components/CodeContainer"; import NpmPackage from "./_components/NpmPackage"; import SideCircles from "./_components/SideCircles"; import Spotlight from "./_components/Spotlight"; +import TechConstellation from "./_components/TechConstellation"; +import TerminalDisplay from "./_components/Terminal"; const poppins = Poppins({ subsets: ["latin"], @@ -21,7 +24,7 @@ export default function HomePage() { -
+
@@ -57,6 +60,8 @@ export default function HomePage() {
+ + ); } diff --git a/apps/web/src/app/global.css b/apps/web/src/app/global.css index fd35f6c..3cc1174 100644 --- a/apps/web/src/app/global.css +++ b/apps/web/src/app/global.css @@ -36,3 +36,19 @@ .shiny-text.disabled { animation: none; } + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fadeIn { + opacity: 0; + animation: fadeInUp 0.5s ease-out forwards; +} diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index d4f1c4c..5b3fe5a 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -1,16 +1,17 @@ import "./global.css"; import { RootProvider } from "fumadocs-ui/provider"; -import { Inter } from "next/font/google"; +import { Poppins } from "next/font/google"; import { type ReactNode, Suspense } from "react"; import Navbar from "./(home)/_components/Navbar"; -const inter = Inter({ +const poppins = Poppins({ subsets: ["latin"], + weight: ["400", "500", "600", "700", "800"], }); export default function Layout({ children }: { children: ReactNode }) { return ( - +