mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
Add demo link in navbar and fix stack in tech showcase
This commit is contained in:
@@ -2,8 +2,8 @@ const PackageIcon = ({ pm, className }: { pm: string; className?: string }) => {
|
||||
switch (pm) {
|
||||
case "npm":
|
||||
return (
|
||||
// biome-ignore lint/a11y/noSvgWithoutTitle: <explanation>
|
||||
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
|
||||
<title>npm</title>
|
||||
<path d="M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -62,7 +62,7 @@ const Navbar = () => {
|
||||
<div className="flex justify-center">
|
||||
<div
|
||||
className={`flex items-center backdrop-blur-md bg-black/40 rounded-md border border-blue-500/30 py-1 px-1.5 text-sm relative transition-all duration-500 ease-out ${
|
||||
scrolled ? "w-[280px]" : "sm:w-[180px] w-[180px]"
|
||||
scrolled ? "w-[342px]" : "sm:w-[240px] w-[280px]"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
@@ -92,6 +92,18 @@ const Navbar = () => {
|
||||
<PackageIcon pm="github" className="w-4 h-4" />{" "}
|
||||
<span className="max-sm:hidden">github</span>
|
||||
</Link> */}
|
||||
<Link
|
||||
href="https://my-better-t-app-client.pages.dev/"
|
||||
target="_blank"
|
||||
ref={(ref) => {
|
||||
linkRefs.current.demo = ref;
|
||||
}}
|
||||
onMouseOver={() => setActiveLink("demo")}
|
||||
onMouseLeave={() => setActiveLink("home")}
|
||||
className="text-gray-300 hidden hover:text-blue-300 transition-colors py-2 px-4 rounded-md relative sm:flex gap-2 items-center font-mono"
|
||||
>
|
||||
<span>demo</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="https://www.npmjs.com/package/create-better-t-stack"
|
||||
target="_blank"
|
||||
@@ -105,6 +117,7 @@ const Navbar = () => {
|
||||
<PackageIcon pm="npm" className="w-4 h-4 rounded-full" />{" "}
|
||||
<span>npm</span>
|
||||
</Link>
|
||||
|
||||
{/* <span
|
||||
className="text-blue-500 transition-all duration-300"
|
||||
style={{
|
||||
@@ -149,7 +162,7 @@ const Navbar = () => {
|
||||
}`}
|
||||
>
|
||||
<PackageIcon pm="github" className="w-4 h-4" />{" "}
|
||||
<span className="max-sm:hidden">github</span>
|
||||
<span className="">github</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -103,7 +103,6 @@ export default function TechMatrix() {
|
||||
const [isTyping, setIsTyping] = useState(false);
|
||||
const fullCommand = "show tech-stack --category all";
|
||||
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
|
||||
useEffect(() => {
|
||||
if (isTyping) return;
|
||||
|
||||
@@ -120,7 +119,7 @@ export default function TechMatrix() {
|
||||
}, 80);
|
||||
|
||||
return () => clearInterval(typeInterval);
|
||||
}, []);
|
||||
}, [isTyping]);
|
||||
|
||||
const categories = Array.from(
|
||||
new Set(techStack.map((item) => item.category)),
|
||||
@@ -199,8 +198,7 @@ export default function TechMatrix() {
|
||||
<div className="font-mono text-sm text-gray-300 mb-6 flex items-center">
|
||||
<span className="text-green-400 mr-2">$</span>
|
||||
<span>{typedCommand}</span>
|
||||
{/* biome-ignore lint/style/useSelfClosingElements: <explanation> */}
|
||||
<span className="h-4 w-2 bg-gray-400 animate-blink ml-1"></span>
|
||||
<span className="h-4 w-2 bg-gray-400 animate-blink ml-1" />
|
||||
</div>
|
||||
|
||||
{/* Category filters */}
|
||||
@@ -210,10 +208,9 @@ export default function TechMatrix() {
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.3, duration: 0.5 }}
|
||||
>
|
||||
{/* biome-ignore lint/style/useSelfClosingElements: <explanation> */}
|
||||
<div className="absolute inset-0 -m-2 bg-gradient-to-r from-blue-500/0 via-blue-500/5 to-purple-500/0 rounded-lg blur-md -z-10"></div>
|
||||
{/* biome-ignore lint/a11y/useButtonType: <explanation> */}
|
||||
<div className="absolute inset-0 -m-2 bg-gradient-to-r from-blue-500/0 via-blue-500/5 to-purple-500/0 rounded-lg blur-md -z-10" />
|
||||
<button
|
||||
type="button"
|
||||
className={`px-3 py-1 text-xs font-mono rounded-md transition-all duration-300 ${
|
||||
!selectedCategory
|
||||
? "bg-blue-500/20 text-blue-300 border border-blue-500/30 shadow-[0_0_10px_rgba(59,130,246,0.3)]"
|
||||
@@ -225,8 +222,8 @@ export default function TechMatrix() {
|
||||
</button>
|
||||
|
||||
{categories.map((category) => (
|
||||
// biome-ignore lint/a11y/useButtonType: <explanation>
|
||||
<button
|
||||
type="button"
|
||||
key={category}
|
||||
className={`px-3 py-1 text-xs font-mono rounded-md transition-all duration-300 ${
|
||||
selectedCategory === category
|
||||
@@ -249,10 +246,10 @@ export default function TechMatrix() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* biome-ignore lint/style/noUnusedTemplateLiteral: <explanation> */}
|
||||
<div className="text-blue-400 mb-4">{`// Better-T Stack Tech Matrix`}</div>
|
||||
{/* biome-ignore lint/style/noUnusedTemplateLiteral: <explanation> */}
|
||||
<div className="text-purple-400">{`const techStack = {`}</div>
|
||||
<div className="text-blue-400 mb-4">
|
||||
{"// Better-T Stack Tech Matrix"}
|
||||
</div>
|
||||
<div className="text-purple-400">{"const techStack = {"}</div>
|
||||
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
@@ -329,8 +326,7 @@ export default function TechMatrix() {
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
|
||||
{/* biome-ignore lint/style/noUnusedTemplateLiteral: <explanation> */}
|
||||
<div className="text-purple-400">{`};`}</div>
|
||||
<div className="text-purple-400">{"};"}</div>
|
||||
|
||||
{/* Terminal footer */}
|
||||
<div className="mt-6 text-gray-400 border-t border-gray-800/50 pt-4 flex items-center justify-between">
|
||||
|
||||
@@ -4,39 +4,28 @@ import React, { useState } from "react";
|
||||
interface TechItem {
|
||||
name: string;
|
||||
description: string;
|
||||
category:
|
||||
| "frontend"
|
||||
| "backend"
|
||||
| "database"
|
||||
| "tooling"
|
||||
| "deployment"
|
||||
| "core";
|
||||
category: "frontend" | "backend" | "database" | "tooling" | "core";
|
||||
}
|
||||
|
||||
const techStack: TechItem[] = [
|
||||
{
|
||||
name: "Bun",
|
||||
description: "Fast all-in-one JavaScript runtime",
|
||||
category: "core",
|
||||
},
|
||||
{
|
||||
name: "TypeScript",
|
||||
description: "Type safety across the stack",
|
||||
description: "Type safety across the entire stack",
|
||||
category: "core",
|
||||
},
|
||||
{
|
||||
name: "tRPC",
|
||||
description: "End-to-end type-safe APIs",
|
||||
category: "core",
|
||||
},
|
||||
{
|
||||
name: "React (Vite)",
|
||||
name: "React",
|
||||
description: "JavaScript library for user interfaces",
|
||||
category: "frontend",
|
||||
},
|
||||
{
|
||||
name: "TanStack Router",
|
||||
description: "Type-safe routing",
|
||||
description: "Type-safe routing with file-based routes",
|
||||
category: "frontend",
|
||||
},
|
||||
{
|
||||
name: "TanStack Query",
|
||||
description: "Powerful data synchronization",
|
||||
category: "frontend",
|
||||
},
|
||||
{
|
||||
@@ -46,7 +35,7 @@ const techStack: TechItem[] = [
|
||||
},
|
||||
{
|
||||
name: "shadcn/ui",
|
||||
description: "Re-usable components",
|
||||
description: "Re-usable UI components",
|
||||
category: "frontend",
|
||||
},
|
||||
{
|
||||
@@ -54,6 +43,11 @@ const techStack: TechItem[] = [
|
||||
description: "Ultrafast web framework",
|
||||
category: "backend",
|
||||
},
|
||||
{
|
||||
name: "tRPC",
|
||||
description: "End-to-end type-safe APIs",
|
||||
category: "backend",
|
||||
},
|
||||
{
|
||||
name: "Better-Auth",
|
||||
description: "Modern authentication solution",
|
||||
@@ -61,7 +55,7 @@ const techStack: TechItem[] = [
|
||||
},
|
||||
{
|
||||
name: "Drizzle ORM",
|
||||
description: "TypeScript ORM",
|
||||
description: "TypeScript-first ORM",
|
||||
category: "database",
|
||||
},
|
||||
{
|
||||
@@ -70,10 +64,45 @@ const techStack: TechItem[] = [
|
||||
category: "database",
|
||||
},
|
||||
{
|
||||
name: "libSQL",
|
||||
description: "SQLite-compatible database engine",
|
||||
name: "SQLite + Turso",
|
||||
description: "Serverless SQLite with edge replication",
|
||||
category: "database",
|
||||
},
|
||||
{
|
||||
name: "PostgreSQL",
|
||||
description: "Advanced open-source relational database",
|
||||
category: "database",
|
||||
},
|
||||
{
|
||||
name: "Biome",
|
||||
description: "Fast formatter and linter",
|
||||
category: "tooling",
|
||||
},
|
||||
{
|
||||
name: "Husky",
|
||||
description: "Git hooks made easy",
|
||||
category: "tooling",
|
||||
},
|
||||
{
|
||||
name: "PWA",
|
||||
description: "Progressive Web App support",
|
||||
category: "tooling",
|
||||
},
|
||||
{
|
||||
name: "Tauri",
|
||||
description: "Build desktop and mobile apps with web tech",
|
||||
category: "tooling",
|
||||
},
|
||||
{
|
||||
name: "Docker",
|
||||
description: "Containerized deployments",
|
||||
category: "tooling",
|
||||
},
|
||||
{
|
||||
name: "Turborepo",
|
||||
description: "Optimized build system for monorepos",
|
||||
category: "core",
|
||||
},
|
||||
];
|
||||
|
||||
const categoryIcons = {
|
||||
@@ -81,8 +110,7 @@ const categoryIcons = {
|
||||
backend: "⚙️",
|
||||
database: "🗄️",
|
||||
tooling: "🔧",
|
||||
deployment: "🚀",
|
||||
core: "🔑",
|
||||
core: "⚡",
|
||||
};
|
||||
|
||||
export default function TechShowcase() {
|
||||
@@ -106,8 +134,8 @@ export default function TechShowcase() {
|
||||
return (
|
||||
<section className="w-full max-w-6xl mx-auto py-16 px-4">
|
||||
<div className="mb-8 flex flex-wrap justify-center gap-3">
|
||||
{/* biome-ignore lint/a11y/useButtonType: <explanation> */}
|
||||
<button
|
||||
type="button"
|
||||
className={`px-4 py-2 rounded-md font-mono text-sm transition-colors ${
|
||||
activeCategory === null
|
||||
? "bg-blue-500 text-white"
|
||||
@@ -119,9 +147,9 @@ export default function TechShowcase() {
|
||||
</button>
|
||||
|
||||
{categories.map((category) => (
|
||||
// biome-ignore lint/a11y/useButtonType: <explanation>
|
||||
<button
|
||||
key={category}
|
||||
type="button"
|
||||
className={`px-4 py-2 rounded-md font-mono text-sm transition-colors ${
|
||||
activeCategory === category
|
||||
? "bg-blue-500 text-white"
|
||||
@@ -149,7 +177,20 @@ export default function TechShowcase() {
|
||||
</h3>
|
||||
<p className="text-gray-400 text-sm">{tech.description}</p>
|
||||
<div className="mt-3 text-xs text-gray-500 font-mono">
|
||||
<code>--package={tech.name.toLowerCase()}</code>
|
||||
{tech.category === "tooling" || tech.category === "database" ? (
|
||||
<span>
|
||||
{tech.name === "Drizzle ORM" ||
|
||||
tech.name === "Prisma" ||
|
||||
tech.name === "SQLite + Turso" ||
|
||||
tech.name === "PostgreSQL" ? (
|
||||
<code>--{tech.name.toLowerCase().split(" ")[0]}</code>
|
||||
) : (
|
||||
<code>--{tech.name.toLowerCase()}</code>
|
||||
)}
|
||||
</span>
|
||||
) : (
|
||||
<span>Included by default</span>
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
@@ -183,7 +224,10 @@ export default function TechShowcase() {
|
||||
{tech.name}
|
||||
</h3>
|
||||
<div className="bg-gray-800 px-2 py-1 rounded text-xs font-mono text-gray-400">
|
||||
core
|
||||
{group.category === "tooling" ||
|
||||
tech.category === "database"
|
||||
? "optional"
|
||||
: "core"}
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-gray-400 text-sm mt-2">
|
||||
@@ -191,10 +235,19 @@ export default function TechShowcase() {
|
||||
</p>
|
||||
<div className="mt-3 pt-2 border-t border-gray-800 flex items-center justify-between">
|
||||
<span className="text-xs text-gray-500 font-mono">
|
||||
include: true
|
||||
{group.category === "tooling" ||
|
||||
tech.category === "database"
|
||||
? tech.name === "Drizzle ORM" ||
|
||||
tech.name === "Prisma" ||
|
||||
tech.name === "SQLite + Turso" ||
|
||||
tech.name === "PostgreSQL"
|
||||
? `--${tech.name.toLowerCase().split(" ")[0]}`
|
||||
: `--${tech.name.toLowerCase()}`
|
||||
: "included by default"}
|
||||
</span>
|
||||
{/* biome-ignore lint/style/useSelfClosingElements: <explanation> */}
|
||||
<span className="h-2 w-2 bg-green-500 rounded-full"></span>
|
||||
<span
|
||||
className={`h-2 w-2 ${group.category === "tooling" || tech.category === "database" ? "bg-yellow-500" : "bg-green-500"} rounded-full`}
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
@@ -207,9 +260,8 @@ export default function TechShowcase() {
|
||||
|
||||
<div className="mt-10 text-center">
|
||||
<div className="inline-block bg-gray-900/50 backdrop-blur-sm border border-gray-800 rounded-md px-5 py-3 font-mono text-sm text-gray-400">
|
||||
<span className="text-green-400">$</span> The perfect tech stack,
|
||||
carefully selected for{" "}
|
||||
<span className="text-blue-400">maximum developer happiness</span>
|
||||
<span className="text-green-400">$</span> npx create-better-t-stack
|
||||
<span className="text-blue-400"> —your-options</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user