mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
fix navbar bg issue improve tech stack section
This commit is contained in:
134
apps/web/src/app/(home)/_components/FeaturedSection.tsx
Normal file
134
apps/web/src/app/(home)/_components/FeaturedSection.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import { ArrowRight, Code2, Shield, Zap } from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
const Featured = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="w-full max-w-6xl mx-auto py-24 relative z-50">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{[
|
||||
{
|
||||
icon: Shield,
|
||||
title: "Type-Safe by Default",
|
||||
description:
|
||||
"End-to-end type safety from database to frontend. Catch errors before they happen.",
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: "Lightning Fast",
|
||||
description:
|
||||
"Built on Bun's lightning-fast runtime with optimal configurations for performance.",
|
||||
},
|
||||
{
|
||||
icon: Code2,
|
||||
title: "Developer Experience",
|
||||
description:
|
||||
"Modern tooling and intuitive APIs make development a breeze.",
|
||||
},
|
||||
].map((feature) => (
|
||||
<div
|
||||
key={feature.title}
|
||||
className="relative group p-6 bg-gray-900/50 rounded-xl border border-gray-800 hover:border-gray-700 transition-all"
|
||||
>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-500/10 to-purple-500/10 opacity-0 group-hover:opacity-100 transition-opacity rounded-xl" />
|
||||
<feature.icon className="w-10 h-10 text-blue-400 mb-4" />
|
||||
<h3 className="text-xl font-semibold text-white mb-2">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-gray-400">{feature.description}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full bg-gray-900/50 border-y border-gray-800 relative z-50">
|
||||
<div className="max-w-6xl mx-auto py-24">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-white mb-4">
|
||||
Write Better Code, Faster
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-2xl mx-auto">
|
||||
Leverage the power of TypeScript with our carefully selected tools
|
||||
and frameworks.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-12 items-center">
|
||||
<div className="space-y-6">
|
||||
{[
|
||||
{
|
||||
title: "Type-Safe API Calls",
|
||||
description:
|
||||
"No more guessing API shapes. tRPC ensures type safety across your stack.",
|
||||
},
|
||||
{
|
||||
title: "Database Type Safety",
|
||||
description:
|
||||
"Drizzle ORM provides type-safe database queries with great DX.",
|
||||
},
|
||||
{
|
||||
title: "Modern Authentication",
|
||||
description:
|
||||
"Secure authentication with Better-Auth, built for modern web apps.",
|
||||
},
|
||||
].map((item) => (
|
||||
<div
|
||||
key={item.title}
|
||||
className="flex items-start space-x-4 p-4 rounded-lg hover:bg-gray-800/50 transition-colors"
|
||||
>
|
||||
<ArrowRight className="w-6 h-6 text-blue-400 mt-1" />
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-white">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-gray-400">{item.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-500/10 to-purple-500/10 blur-xl" />
|
||||
<div className="relative bg-gray-900 rounded-lg p-6 border border-gray-800">
|
||||
<pre className="text-sm text-gray-300 overflow-x-auto">
|
||||
<code>{`// Type-safe API endpoint
|
||||
export const userRouter = router({
|
||||
get: publicProcedure
|
||||
.input(z.string())
|
||||
.query(async ({ input }) => {
|
||||
const user = await db
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.id, input));
|
||||
|
||||
return user;
|
||||
})
|
||||
});`}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full max-w-6xl mx-auto py-24 text-center relative z-50">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-white mb-6">
|
||||
Ready to Build Something Amazing?
|
||||
</h2>
|
||||
<p className="text-gray-400 max-w-xl mx-auto mb-8">
|
||||
Start your next project with Better-T Stack and experience the future
|
||||
of web development.
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
className="px-8 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-full font-semibold transition-colors inline-flex items-center group"
|
||||
>
|
||||
Get Started
|
||||
<ArrowRight className="w-5 h-5 ml-2 transform group-hover:translate-x-1 transition-transform" />
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Featured;
|
||||
@@ -56,7 +56,7 @@ const Navbar = () => {
|
||||
|
||||
<div
|
||||
className={`flex items-center backdrop-blur-md bg-white/5 rounded-full border border-white/10 py-1 px-1.5 text-sm relative transition-all duration-500 ease-out ${
|
||||
scrolled ? "w-[470px]" : "w-[335px]"
|
||||
scrolled ? "w-[475px]" : "w-[335px]"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { technologies } from "@/lib/constant";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { type JSX, useEffect, useRef, useState } from "react";
|
||||
|
||||
type TechConstellationProp = {
|
||||
fromRef: React.RefObject<HTMLElement>;
|
||||
toRef: React.RefObject<HTMLElement>;
|
||||
containerRef: React.RefObject<HTMLElement>;
|
||||
delay?: number;
|
||||
curveDirection?: number;
|
||||
};
|
||||
|
||||
const AnimatedBeam = ({
|
||||
@@ -15,6 +16,7 @@ const AnimatedBeam = ({
|
||||
toRef,
|
||||
containerRef,
|
||||
delay = 0,
|
||||
curveDirection = 50,
|
||||
}: TechConstellationProp) => {
|
||||
const [path, setPath] = useState("");
|
||||
|
||||
@@ -32,14 +34,14 @@ const AnimatedBeam = ({
|
||||
const toY = toRect.top - containerRect.top + toRect.height / 2;
|
||||
|
||||
setPath(
|
||||
`M ${fromX},${fromY} Q ${(fromX + toX) / 2},${(fromY + toY) / 2 - 50} ${toX},${toY}`,
|
||||
`M ${fromX},${fromY} Q ${(fromX + toX) / 2},${(fromY + toY) / 2 - curveDirection} ${toX},${toY}`,
|
||||
);
|
||||
};
|
||||
|
||||
updatePath();
|
||||
window.addEventListener("resize", updatePath);
|
||||
return () => window.removeEventListener("resize", updatePath);
|
||||
}, [fromRef, toRef, containerRef]);
|
||||
}, [fromRef, toRef, containerRef, curveDirection]);
|
||||
|
||||
return (
|
||||
<svg className="absolute top-0 left-0 w-full h-full pointer-events-none">
|
||||
@@ -49,7 +51,7 @@ const AnimatedBeam = ({
|
||||
fill="none"
|
||||
stroke="url(#gradient)"
|
||||
strokeWidth="2"
|
||||
className="opacity-50"
|
||||
className="opacity-30"
|
||||
>
|
||||
<animate
|
||||
attributeName="stroke-dasharray"
|
||||
@@ -76,6 +78,74 @@ const TechConstellation = () => {
|
||||
const techRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
const calculateRadius = (category: string) => {
|
||||
switch (category) {
|
||||
case "core":
|
||||
return 160;
|
||||
case "frontend":
|
||||
case "backend":
|
||||
return 240;
|
||||
default:
|
||||
return 200;
|
||||
}
|
||||
};
|
||||
|
||||
const renderCategoryBeams = (category: string) => {
|
||||
const categoryTechs = technologies.filter(
|
||||
(tech) => tech.category === category,
|
||||
);
|
||||
const beams: JSX.Element[] = [];
|
||||
|
||||
if (category !== "core") {
|
||||
categoryTechs.forEach((tech, index) => {
|
||||
const curveDirection = tech.category === "frontend" ? 50 : -50;
|
||||
beams.push(
|
||||
<AnimatedBeam
|
||||
key={`beam-center-${tech.name}`}
|
||||
fromRef={centerRef as React.RefObject<HTMLElement>}
|
||||
toRef={{ current: techRefs.current[tech.name] as HTMLElement }}
|
||||
containerRef={containerRef as React.RefObject<HTMLElement>}
|
||||
delay={index * 0.2}
|
||||
curveDirection={curveDirection}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < categoryTechs.length - 1; i++) {
|
||||
const curveDirection = category === "frontend" ? 30 : -30;
|
||||
beams.push(
|
||||
<AnimatedBeam
|
||||
key={`beam-${categoryTechs[i].name}-${categoryTechs[i + 1].name}`}
|
||||
fromRef={{
|
||||
current: techRefs.current[categoryTechs[i].name] as HTMLElement,
|
||||
}}
|
||||
toRef={{
|
||||
current: techRefs.current[categoryTechs[i + 1].name] as HTMLElement,
|
||||
}}
|
||||
containerRef={containerRef as React.RefObject<HTMLElement>}
|
||||
delay={(i + categoryTechs.length) * 0.2}
|
||||
curveDirection={curveDirection}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
|
||||
if (category === "core") {
|
||||
beams.push(
|
||||
<AnimatedBeam
|
||||
key="beam-core-connection"
|
||||
fromRef={{ current: techRefs.current.Bun as HTMLElement }}
|
||||
toRef={{ current: techRefs.current.tRPC as HTMLElement }}
|
||||
containerRef={containerRef as React.RefObject<HTMLElement>}
|
||||
delay={0}
|
||||
curveDirection={0}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
|
||||
return beams;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setIsVisible(true);
|
||||
}, []);
|
||||
@@ -83,17 +153,17 @@ const TechConstellation = () => {
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="relative w-full h-screen bg-gradient-to-b from-transparent to-gray-950 overflow-hidden flex items-center justify-center"
|
||||
className="relative w-full h-[90vh] bg-gradient-to-b from-transparent via-gray-950 to-transparent overflow-hidden flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
ref={centerRef}
|
||||
className={`absolute z-10 w-32 h-32 bg-blue-600 rounded-xl flex items-center justify-center transform transition-all duration-1000 ${isVisible ? "scale-100 opacity-100" : "scale-0 opacity-0"}`}
|
||||
className={`absolute z-10 w-24 h-24 bg-blue-600 rounded-full flex items-center justify-center transform transition-all duration-1000 ${isVisible ? "scale-100 opacity-100" : "scale-0 opacity-0"}`}
|
||||
>
|
||||
<span className="text-4xl font-bold text-white">TS</span>
|
||||
<span className="text-3xl font-bold text-white">TS</span>
|
||||
</div>
|
||||
|
||||
{technologies.map((tech, index) => {
|
||||
const radius = 250;
|
||||
const radius = calculateRadius(tech.category);
|
||||
const x = Math.cos((tech.angle * Math.PI) / 180) * radius;
|
||||
const y = Math.sin((tech.angle * Math.PI) / 180) * radius;
|
||||
|
||||
@@ -112,35 +182,32 @@ const TechConstellation = () => {
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`w-16 h-16 ${tech.color} rounded-full flex items-center justify-center
|
||||
className={`w-12 h-12 ${tech.color} rounded-full flex items-center justify-center
|
||||
transform hover:scale-125 transition-all duration-300 cursor-pointer
|
||||
shadow-lg hover:shadow-xl hover:rotate-12`}
|
||||
>
|
||||
<tech.icon className={`w-8 h-8 ${tech.textColor}`} />
|
||||
<tech.icon className={`w-6 h-6 ${tech.textColor}`} />
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="opacity-0 group-hover:opacity-100 absolute -top-12 left-1/2 transform -translate-x-1/2
|
||||
bg-gray-900 text-white px-4 py-2 rounded-lg shadow-xl transition-all duration-300
|
||||
whitespace-nowrap text-sm hover:scale-105"
|
||||
className={`opacity-100 absolute ${tech.top ? tech.top : "-top-[48px]"} ${tech.left ? tech.left : "left-1/2"} transform -translate-x-1/2
|
||||
bg-gray-900 text-white px-3 py-1.5 rounded-lg shadow-xl transition-all duration-300
|
||||
whitespace-nowrap text-xs hover:scale-105`}
|
||||
>
|
||||
<strong>{tech.name}</strong>
|
||||
<p className="text-gray-300 text-xs">{tech.description}</p>
|
||||
<p className="text-gray-300 text-[10px]">{tech.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{isVisible &&
|
||||
technologies.map((tech, index) => (
|
||||
<AnimatedBeam
|
||||
key={`beam-${tech.name}`}
|
||||
fromRef={centerRef as React.RefObject<HTMLElement>}
|
||||
toRef={{ current: techRefs.current[tech.name] as HTMLElement }}
|
||||
containerRef={containerRef as React.RefObject<HTMLElement>}
|
||||
delay={index * 0.2}
|
||||
/>
|
||||
))}
|
||||
{isVisible && (
|
||||
<>
|
||||
{renderCategoryBeams("core")}
|
||||
{renderCategoryBeams("frontend")}
|
||||
{renderCategoryBeams("backend")}
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
{[...Array(20)].map((_, i) => (
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Poppins } from "next/font/google";
|
||||
import React from "react";
|
||||
import BackgroundGradients from "./_components/BackgroundGradients";
|
||||
import CodeContainer from "./_components/CodeContainer";
|
||||
import Featured from "./_components/FeaturedSection";
|
||||
import NpmPackage from "./_components/NpmPackage";
|
||||
import SideCircles from "./_components/SideCircles";
|
||||
import Spotlight from "./_components/Spotlight";
|
||||
@@ -61,7 +62,37 @@ export default function HomePage() {
|
||||
</div>
|
||||
</div>
|
||||
<TerminalDisplay />
|
||||
<TechConstellation />
|
||||
<div className="w-full max-w-6xl mx-auto space-y-12 mt-12">
|
||||
<div className="text-center space-y-6 relative z-10">
|
||||
<h2 className="text-4xl md:text-5xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-slate-700 via-gray-100 to-stone-600 pb-2">
|
||||
A Symphony of Modern Tech
|
||||
</h2>
|
||||
<div className="space-y-4 max-w-3xl mx-auto">
|
||||
<p className="text-xl text-gray-300 leading-relaxed">
|
||||
Carefully orchestrated stack of{" "}
|
||||
<span className="text-blue-400 font-semibold">
|
||||
cutting-edge technologies
|
||||
</span>
|
||||
, working in perfect harmony to deliver an exceptional development
|
||||
experience.
|
||||
</p>
|
||||
<div className="flex flex-wrap justify-center gap-4 text-sm text-gray-400">
|
||||
<span className="px-3 py-1 bg-gray-800/50 rounded-full hover:bg-gray-800 transition-colors">
|
||||
End-to-end Type Safety
|
||||
</span>
|
||||
<span className="px-3 py-1 bg-gray-800/50 rounded-full hover:bg-gray-800 transition-colors">
|
||||
Lightning Fast Performance
|
||||
</span>
|
||||
<span className="px-3 py-1 bg-gray-800/50 rounded-full hover:bg-gray-800 transition-colors">
|
||||
Modern Development Tools
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-gray-900 via-gray-900/50 to-transparent -z-10 blur-xl" />
|
||||
</div>
|
||||
<TechConstellation />
|
||||
</div>
|
||||
<Featured />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
AppWindow,
|
||||
Binary,
|
||||
Boxes,
|
||||
Component,
|
||||
Database,
|
||||
@@ -15,38 +14,35 @@ export const technologies = [
|
||||
{
|
||||
name: "Bun",
|
||||
category: "core",
|
||||
angle: -60,
|
||||
angle: -25,
|
||||
icon: FastForward,
|
||||
color: "bg-yellow-100",
|
||||
textColor: "text-black",
|
||||
description: "Fast all-in-one JavaScript runtime",
|
||||
},
|
||||
{
|
||||
name: "TypeScript",
|
||||
category: "core",
|
||||
angle: -30,
|
||||
icon: Binary,
|
||||
color: "bg-blue-500",
|
||||
textColor: "text-white",
|
||||
description: "Type safety across the stack",
|
||||
top: "top-[2px]",
|
||||
left: "left-[10rem]",
|
||||
},
|
||||
{
|
||||
name: "tRPC",
|
||||
category: "core",
|
||||
angle: 0,
|
||||
angle: 25,
|
||||
icon: Workflow,
|
||||
color: "bg-blue-600",
|
||||
textColor: "text-white",
|
||||
description: "End-to-end type-safe APIs",
|
||||
left: "left-[5rem]",
|
||||
},
|
||||
|
||||
{
|
||||
name: "TanStack Router",
|
||||
category: "frontend",
|
||||
angle: 60,
|
||||
angle: 30,
|
||||
icon: AppWindow,
|
||||
color: "bg-red-500",
|
||||
textColor: "text-white",
|
||||
description: "Type-safe routing",
|
||||
top: "top-[2px]",
|
||||
left: "left-[7.5rem]",
|
||||
},
|
||||
{
|
||||
name: "Tailwind CSS",
|
||||
@@ -60,25 +56,28 @@ export const technologies = [
|
||||
{
|
||||
name: "shadcn/ui",
|
||||
category: "frontend",
|
||||
angle: 120,
|
||||
angle: 150,
|
||||
icon: Component,
|
||||
color: "bg-gray-900",
|
||||
textColor: "text-white",
|
||||
description: "Re-usable components",
|
||||
left: "-left-[2rem]",
|
||||
},
|
||||
|
||||
{
|
||||
name: "Hono",
|
||||
category: "backend",
|
||||
angle: 180,
|
||||
angle: -150,
|
||||
icon: ServerCog,
|
||||
color: "bg-orange-500",
|
||||
textColor: "text-white",
|
||||
description: "Ultrafast web framework",
|
||||
left: "left-[0rem]",
|
||||
},
|
||||
{
|
||||
name: "Better-Auth",
|
||||
category: "backend",
|
||||
angle: 210,
|
||||
angle: -110,
|
||||
icon: Lock,
|
||||
color: "bg-indigo-600",
|
||||
textColor: "text-white",
|
||||
@@ -87,7 +86,7 @@ export const technologies = [
|
||||
{
|
||||
name: "Drizzle ORM",
|
||||
category: "backend",
|
||||
angle: 240,
|
||||
angle: -70,
|
||||
icon: Database,
|
||||
color: "bg-green-400",
|
||||
textColor: "text-black",
|
||||
@@ -96,10 +95,11 @@ export const technologies = [
|
||||
{
|
||||
name: "libSQL",
|
||||
category: "backend",
|
||||
angle: 270,
|
||||
angle: -30,
|
||||
icon: Boxes,
|
||||
color: "bg-gray-600",
|
||||
textColor: "text-white",
|
||||
description: "SQLite-compatible database engine",
|
||||
left: "left-[6rem]",
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user