mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
feat(web): design overhaul
This commit is contained in:
@@ -84,7 +84,7 @@ export default function FeatureCard({
|
||||
layout
|
||||
>
|
||||
<div>
|
||||
<h4 className="pb-2 text-center font-mono font-semibold text-foreground text-sm">
|
||||
<h4 className="pb-2 text-center font-semibold text-foreground text-sm">
|
||||
{title}
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
@@ -25,13 +25,13 @@ const CodeContainer = () => {
|
||||
const packageManagers: Array<"npm" | "pnpm" | "bun"> = ["bun", "pnpm", "npm"];
|
||||
|
||||
return (
|
||||
<div className="mx-auto mt-6 w-full max-w-3xl px-2 font-mono md:px-0">
|
||||
<div className="mx-auto mt-6 w-full max-w-3xl px-2 md:px-0">
|
||||
<div className="overflow-hidden rounded-lg border border-border bg-muted/30 shadow-sm">
|
||||
<div className="flex items-center justify-between border-border border-b bg-muted/50 px-4 py-2">
|
||||
<span className="text-muted-foreground text-xs">
|
||||
Package manager:
|
||||
</span>
|
||||
<div className="flex items-center rounded-md border border-border bg-background p-0.5">
|
||||
<div className="flex items-center rounded-md border border-border p-0.5">
|
||||
{packageManagers.map((pm) => (
|
||||
<button
|
||||
type="button"
|
||||
@@ -51,7 +51,7 @@ const CodeContainer = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative bg-background p-4 text-sm">
|
||||
<div className="relative p-4 text-sm">
|
||||
<div className="flex items-center gap-2 overflow-x-auto pb-1">
|
||||
<span className="select-none text-muted-foreground">$</span>
|
||||
<code className="whitespace-pre text-foreground">
|
||||
@@ -64,7 +64,7 @@ const CodeContainer = () => {
|
||||
type="button"
|
||||
onClick={copyToClipboard}
|
||||
className={cn(
|
||||
"flex h-7 w-7 items-center justify-center rounded border bg-background text-muted-foreground transition-all duration-150 hover:border-border hover:bg-muted hover:text-foreground",
|
||||
"flex h-7 w-7 items-center justify-center rounded border text-muted-foreground transition-all duration-150 hover:border-border hover:bg-muted hover:text-foreground",
|
||||
copied
|
||||
? "border-chart-4/50 bg-chart-4/10 text-chart-4"
|
||||
: "border-border",
|
||||
|
||||
@@ -3,7 +3,7 @@ import StackBuilder from "./stack-builder";
|
||||
|
||||
export default function CustomizableSection() {
|
||||
return (
|
||||
<section className="relative z-10 mx-auto mt-20 w-full max-w-7xl space-y-16 px-4 sm:px-6">
|
||||
<section className="relative z-10 mx-auto mt-20 w-full space-y-16 px-4 sm:px-6">
|
||||
<div className="relative space-y-8 text-center">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
@@ -12,7 +12,7 @@ export default function CustomizableSection() {
|
||||
transition={{ duration: 0.5 }}
|
||||
className="relative"
|
||||
>
|
||||
<h2 className="font-bold font-mono text-2xl tracking-tight sm:text-3xl md:text-4xl lg:text-5xl">
|
||||
<h2 className="font-bold text-2xl tracking-tight sm:text-3xl md:text-4xl lg:text-5xl">
|
||||
<span className="border-primary border-b-2 pb-1 text-foreground dark:text-primary">
|
||||
Roll Your Own Stack
|
||||
</span>
|
||||
@@ -26,7 +26,7 @@ export default function CustomizableSection() {
|
||||
transition={{ duration: 0.5, delay: 0.2 }}
|
||||
className="mx-auto max-w-3xl space-y-6"
|
||||
>
|
||||
<p className="font-mono text-lg text-muted-foreground leading-relaxed sm:text-xl">
|
||||
<p className=" text-lg text-muted-foreground leading-relaxed sm:text-xl">
|
||||
Build your perfect TypeScript stack.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
@@ -3,8 +3,8 @@ import Link from "next/link";
|
||||
|
||||
const Footer = () => {
|
||||
return (
|
||||
<footer className="relative w-full border-border border-t font-mono">
|
||||
<div className="mx-auto max-w-7xl px-4 py-12 sm:px-6">
|
||||
<footer className="relative w-full border-border border-t ">
|
||||
<div className="mx-auto px-4 py-12 sm:px-6">
|
||||
<div className="mb-12 grid gap-8 md:grid-cols-3">
|
||||
<div>
|
||||
<h3 className="mb-4 flex items-center gap-2 font-semibold text-base text-foreground">
|
||||
@@ -95,7 +95,7 @@ const Footer = () => {
|
||||
</h3>
|
||||
<div className="space-y-2.5 text-muted-foreground">
|
||||
<p className="flex items-center">
|
||||
<span className="mr-2 rounded bg-muted px-2 py-1 font-mono text-sm">
|
||||
<span className="mr-2 rounded bg-muted px-2 py-1 text-sm">
|
||||
$
|
||||
</span>
|
||||
<span>amanvarshney.work@gmail.com</span>
|
||||
|
||||
@@ -98,11 +98,11 @@ export default function Navbar() {
|
||||
className={cn(
|
||||
"fixed top-0 z-[100] w-full transition-all duration-300 ease-in-out",
|
||||
scrolled
|
||||
? "border-border border-b bg-background/80 shadow-sm backdrop-blur-md"
|
||||
? " border- border-border shadow-sm backdrop-blur-md"
|
||||
: "border-transparent border-b bg-transparent",
|
||||
)}
|
||||
>
|
||||
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6 lg:px-8">
|
||||
<div className="mx-auto flex h-16 items-center justify-between px-4 sm:px-6 lg:px-8">
|
||||
<Link href="/" className="flex flex-shrink-0 items-center gap-2">
|
||||
<Image
|
||||
src="/logo.svg"
|
||||
@@ -123,7 +123,7 @@ export default function Navbar() {
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
target={link.target}
|
||||
className="relative flex items-center gap-1.5 rounded-md px-3 py-1.5 font-mono text-muted-foreground text-sm transition-colors hover:bg-muted hover:text-primary"
|
||||
className="relative flex items-center gap-1.5 rounded-md px-3 py-1.5 text-muted-foreground text-sm transition-colors hover:bg-muted hover:text-primary"
|
||||
>
|
||||
{link.icon}
|
||||
<span>{link.label}</span>
|
||||
@@ -137,7 +137,7 @@ export default function Navbar() {
|
||||
<Link
|
||||
href="https://github.com/sponsors/AmanVarshney01"
|
||||
target="_blank"
|
||||
className="inline-flex items-center gap-1.5 rounded-md border border-border bg-muted/90 px-3 py-1.5 font-mono text-muted-foreground text-xs backdrop-blur-sm transition-colors hover:bg-muted hover:text-foreground"
|
||||
className="inline-flex items-center gap-1.5 rounded-md border border-border bg-muted/90 px-3 py-1.5 text-muted-foreground text-xs backdrop-blur-sm transition-colors hover:bg-muted hover:text-foreground"
|
||||
title="Sponsor on GitHub"
|
||||
>
|
||||
<Heart className="size-3.5" />
|
||||
@@ -145,7 +145,7 @@ export default function Navbar() {
|
||||
</Link>
|
||||
<Link
|
||||
href="/new"
|
||||
className="inline-flex items-center gap-1.5 rounded-md border border-primary/50 bg-primary/10 px-3 py-1.5 font-mono text-primary text-xs transition-colors hover:bg-primary/20"
|
||||
className="inline-flex items-center gap-1.5 rounded-md border border-primary/50 bg-primary/10 px-3 py-1.5 text-primary text-xs transition-colors hover:bg-primary/20"
|
||||
title="Stack Builder"
|
||||
>
|
||||
<Maximize2 className="size-3.5" />
|
||||
@@ -183,7 +183,7 @@ export default function Navbar() {
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.2, ease: "easeInOut" }}
|
||||
className="fixed inset-0 z-[98] bg-background/50 backdrop-blur-sm lg:hidden"
|
||||
className=" fixed inset-0 z-[98 backdrop-blur-sm lg:hidden"
|
||||
onClick={closeMobileMenu}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
@@ -193,7 +193,7 @@ export default function Navbar() {
|
||||
animate={{ x: 0 }}
|
||||
exit={{ x: "100%" }}
|
||||
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
||||
className="fixed top-0 right-0 bottom-0 z-[99] h-full w-full max-w-xs overflow-y-auto border-border border-l bg-background shadow-lg lg:hidden"
|
||||
className="fixed top-0 right-0 bottom-0 z-[99] h-full w-full max-w-xs overflow-y-auto border-border border-l shadow-lg lg:hidden"
|
||||
aria-modal="true"
|
||||
>
|
||||
<div className="flex h-16 items-center justify-between border-border border-b px-4">
|
||||
@@ -218,7 +218,7 @@ export default function Navbar() {
|
||||
href={link.href}
|
||||
target={link.target}
|
||||
onClick={closeMobileMenu}
|
||||
className="flex items-center gap-3 rounded-md px-3 py-3 font-mono text-base text-muted-foreground transition-colors hover:bg-muted hover:text-primary"
|
||||
className="flex items-center gap-3 rounded-md px-3 py-3 text-base text-muted-foreground transition-colors hover:bg-muted hover:text-primary"
|
||||
>
|
||||
{link.icon ? (
|
||||
<span className="flex w-5 items-center justify-center">
|
||||
@@ -236,7 +236,7 @@ export default function Navbar() {
|
||||
<Link
|
||||
href="/new"
|
||||
onClick={closeMobileMenu}
|
||||
className="flex w-full items-center justify-center gap-2 rounded-md border border-primary/50 bg-primary/10 px-4 py-2.5 font-mono text-primary text-sm transition-colors hover:bg-primary/20"
|
||||
className="flex w-full items-center justify-center gap-2 rounded-md border border-primary/50 bg-primary/10 px-4 py-2.5 text-primary text-sm transition-colors hover:bg-primary/20"
|
||||
>
|
||||
<Maximize2 className="size-4" />
|
||||
Stack Builder
|
||||
@@ -245,7 +245,7 @@ export default function Navbar() {
|
||||
href="https://github.com/sponsors/AmanVarshney01"
|
||||
target="_blank"
|
||||
onClick={closeMobileMenu}
|
||||
className="flex w-full items-center justify-center gap-2 rounded-md border border-border bg-muted/90 px-4 py-2.5 font-mono text-muted-foreground text-sm backdrop-blur-sm transition-colors hover:bg-muted hover:text-foreground"
|
||||
className="flex w-full items-center justify-center gap-2 rounded-md border border-border bg-muted/90 px-4 py-2.5 text-muted-foreground text-sm backdrop-blur-sm transition-colors hover:bg-muted hover:text-foreground"
|
||||
>
|
||||
<Heart className="size-4" />
|
||||
Sponsor on GitHub
|
||||
|
||||
@@ -35,7 +35,7 @@ const NpmPackage = () => {
|
||||
versionLoading && "animate-pulse",
|
||||
)}
|
||||
/>
|
||||
<span className="font-mono text-muted-foreground text-xl">
|
||||
<span className=" text-muted-foreground text-xl">
|
||||
{versionLoading ? "[v?.?.?]" : `[v${version}]`}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -54,73 +54,69 @@ export default function SponsorsSection() {
|
||||
<div className="mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-5 w-5 text-primary" />
|
||||
<span className="font-bold font-mono text-lg sm:text-xl">
|
||||
<span className="font-bold text-lg sm:text-xl">
|
||||
SPONSORS_DATABASE.JSON
|
||||
</span>
|
||||
</div>
|
||||
<div className="hidden h-px flex-1 bg-border sm:block" />
|
||||
<span className="w-full text-right font-mono text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
<span className="w-full text-right text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
[{loadingSponsors ? "LOADING..." : sponsors.length} RECORDS]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover mb-8 rounded border border-border bg-muted/20 p-4">
|
||||
<div className="mb-8 rounded border border-border p-4">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-foreground">
|
||||
# Amazing organizations and individuals supporting this project
|
||||
<span className=" text-foreground">
|
||||
Amazing organizations and individuals supporting this project
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
# Your support helps maintain and improve Better-T-Stack
|
||||
<span className=" text-muted-foreground">
|
||||
Your support helps maintain and improve Better-T-Stack
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{loadingSponsors ? (
|
||||
<div className="terminal-block-hover rounded border border-border bg-muted/20 p-8">
|
||||
<div className="rounded border border-border p-8">
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<div className="h-2 w-2 animate-pulse rounded-full bg-primary" />
|
||||
<span className="font-mono text-muted-foreground">
|
||||
LOADING_SPONSORS.EXE
|
||||
</span>
|
||||
<span className=" text-muted-foreground">LOADING_SPONSORS.EXE</span>
|
||||
<div className="h-2 w-2 animate-pulse rounded-full bg-primary" />
|
||||
</div>
|
||||
</div>
|
||||
) : sponsorError ? (
|
||||
<div className="terminal-block-hover rounded border border-border bg-destructive/10 p-8">
|
||||
<div className="rounded border border-border bg-destructive/10 p-8">
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<span className="text-destructive">✗</span>
|
||||
<span className="font-mono text-destructive">
|
||||
ERROR: {sponsorError}
|
||||
</span>
|
||||
<span className=" text-destructive">ERROR: {sponsorError}</span>
|
||||
</div>
|
||||
</div>
|
||||
) : sponsors.length === 0 ? (
|
||||
<div className="space-y-4">
|
||||
<div className="terminal-block-hover rounded border border-border bg-muted/20 p-8">
|
||||
<div className="rounded border border-border p-8">
|
||||
<div className="text-center">
|
||||
<div className="mb-4 flex items-center justify-center gap-2">
|
||||
<span className="font-mono text-muted-foreground">
|
||||
<span className=" text-muted-foreground">
|
||||
NO_SPONSORS_FOUND.NULL
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
# Be the first to support this project!
|
||||
<span className=" text-muted-foreground">
|
||||
Be the first to support this project!
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="terminal-block-hover rounded border border-border bg-background p-4">
|
||||
<div className="rounded border border-border p-4">
|
||||
<a
|
||||
href="https://github.com/sponsors/AmanVarshney01"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-2 font-mono text-primary transition-colors hover:text-accent"
|
||||
className="flex items-center justify-center gap-2 text-primary transition-colors hover:text-accent"
|
||||
>
|
||||
<Heart className="h-4 w-4" />
|
||||
<span>BECOME_SPONSOR.EXE</span>
|
||||
@@ -138,10 +134,10 @@ export default function SponsorsSection() {
|
||||
return (
|
||||
<div
|
||||
key={entry.sponsor.login}
|
||||
className="terminal-block-hover rounded border border-border bg-background"
|
||||
className="rounded border border-border"
|
||||
style={{ animationDelay: `${index * 50}ms` }}
|
||||
>
|
||||
<div className="border-border border-b bg-muted/20 px-3 py-2">
|
||||
<div className="border-border border-b px-3 py-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<div className="ml-auto flex items-center gap-2 text-muted-foreground text-xs">
|
||||
@@ -159,17 +155,17 @@ export default function SponsorsSection() {
|
||||
alt={entry.sponsor.name || entry.sponsor.login}
|
||||
width={100}
|
||||
height={100}
|
||||
className="rounded border border-border bg-background transition-colors duration-300"
|
||||
className="rounded border border-border transition-colors duration-300"
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
<div className="min-w-0 flex-1 space-y-2">
|
||||
<div>
|
||||
<h3 className="truncate font-mono font-semibold text-foreground text-sm">
|
||||
<h3 className="truncate font-semibold text-foreground text-sm">
|
||||
{entry.sponsor.name || entry.sponsor.login}
|
||||
</h3>
|
||||
{entry.tierName && (
|
||||
<p className="font-mono text-primary text-xs">
|
||||
<p className=" text-primary text-xs">
|
||||
{entry.tierName}
|
||||
</p>
|
||||
)}
|
||||
@@ -179,7 +175,7 @@ export default function SponsorsSection() {
|
||||
href={`https://github.com/${entry.sponsor.login}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group flex items-center gap-2 font-mono text-muted-foreground text-xs transition-colors hover:text-primary"
|
||||
className="group flex items-center gap-2 text-muted-foreground text-xs transition-colors hover:text-primary"
|
||||
>
|
||||
<Github className="h-4 w-4" />
|
||||
<span className="truncate">
|
||||
@@ -195,7 +191,7 @@ export default function SponsorsSection() {
|
||||
}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group flex items-center gap-2 font-mono text-muted-foreground text-xs transition-colors hover:text-primary"
|
||||
className="group flex items-center gap-2 text-muted-foreground text-xs transition-colors hover:text-primary"
|
||||
>
|
||||
<Globe className="h-4 w-4" />
|
||||
<span className="truncate">
|
||||
@@ -209,7 +205,7 @@ export default function SponsorsSection() {
|
||||
</a>
|
||||
)}
|
||||
|
||||
{/* <div className="flex items-center gap-2 font-mono text-muted-foreground text-xs">
|
||||
{/* <div className="flex items-center gap-2 text-muted-foreground text-xs">
|
||||
<span className="text-xs">👤</span>
|
||||
<span>{entry.sponsor.type.toUpperCase()}</span>
|
||||
</div> */}
|
||||
@@ -222,12 +218,12 @@ export default function SponsorsSection() {
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background p-4">
|
||||
<div className="rounded border border-border p-4">
|
||||
<a
|
||||
href="https://github.com/sponsors/AmanVarshney01"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-2 font-mono text-primary transition-colors hover:text-accent"
|
||||
className="flex items-center justify-center gap-2 text-primary transition-colors hover:text-accent"
|
||||
>
|
||||
<Heart className="h-4 w-4" />
|
||||
<span>SUPPORT_PROJECT.EXE</span>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import {
|
||||
Check,
|
||||
ClipboardCopy,
|
||||
Github,
|
||||
InfoIcon,
|
||||
RefreshCw,
|
||||
Settings,
|
||||
@@ -14,13 +13,11 @@ import {
|
||||
} from "lucide-react";
|
||||
import { motion } from "motion/react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useTheme } from "next-themes";
|
||||
import { useQueryStates } from "nuqs";
|
||||
import type React from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { ThemeToggle } from "@/components/theme-toggle";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import {
|
||||
Tooltip,
|
||||
@@ -37,7 +34,6 @@ import {
|
||||
} from "@/lib/constant";
|
||||
import { stackParsers, stackQueryStatesOptions } from "@/lib/stack-url-state";
|
||||
import { cn } from "@/lib/utils";
|
||||
import discordLogo from "@/public/icon/discord.svg";
|
||||
|
||||
const validateProjectName = (name: string): string | undefined => {
|
||||
const INVALID_CHARS = ["<", ">", ":", '"', "|", "?", "*"];
|
||||
@@ -1455,49 +1451,9 @@ const StackBuilder = () => {
|
||||
<TooltipProvider>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-svh flex-col overflow-hidden border-border bg-background text-foreground",
|
||||
"grid grid-cols-1 overflow-hidden border-border text-foreground",
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"grid w-full flex-shrink-0 grid-cols-2 items-center justify-center border-border border-b bg-background px-2 py-2 sm:grid-cols-3 sm:px-4",
|
||||
)}
|
||||
>
|
||||
<Link href={"/"}>
|
||||
<div className="mr-auto font-mono text-muted-foreground text-xs">
|
||||
Home
|
||||
</div>
|
||||
</Link>
|
||||
<div className="mx-auto hidden font-mono text-muted-foreground text-xs sm:block">
|
||||
Create Better T Stack
|
||||
</div>
|
||||
<div className="ml-auto flex space-x-2">
|
||||
<Link
|
||||
href={"https://github.com/AmanVarshney01/create-better-t-stack"}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={cn(
|
||||
"text-muted-foreground transition-colors hover:text-foreground",
|
||||
)}
|
||||
title="GitHub Repository"
|
||||
>
|
||||
<Github className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link
|
||||
href={"https://discord.gg/ZYsbjpDaM5"}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={cn(
|
||||
"text-muted-foreground transition-colors hover:text-foreground",
|
||||
)}
|
||||
title="Join Discord"
|
||||
>
|
||||
<Image src={discordLogo} alt="discord" className="size-4" />{" "}
|
||||
</Link>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 overflow-hidden sm:grid-cols-[auto_1fr]">
|
||||
<div className="flex h-full max-w-full flex-col justify-between border-border border-r p-4 sm:max-w-3xs md:max-w-xs lg:max-w-sm">
|
||||
<div className="flex flex-col space-y-4">
|
||||
@@ -1513,7 +1469,7 @@ const StackBuilder = () => {
|
||||
setStack({ projectName: newValue });
|
||||
}}
|
||||
className={cn(
|
||||
"w-full rounded border bg-background px-2 py-1 font-mono text-sm focus:outline-none",
|
||||
"w-full rounded border px-2 py-1 text-sm focus:outline-none",
|
||||
projectNameError
|
||||
? "border-destructive bg-destructive/10 text-destructive-foreground"
|
||||
: "border-border focus:border-primary",
|
||||
@@ -1530,7 +1486,7 @@ const StackBuilder = () => {
|
||||
<button
|
||||
type="button"
|
||||
onClick={resetStack}
|
||||
className="flex items-center gap-1 rounded border border-border bg-background px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
className="flex items-center gap-1 rounded border border-border px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
title="Reset to defaults"
|
||||
>
|
||||
<RefreshCw className="h-3 w-3" />
|
||||
@@ -1539,7 +1495,7 @@ const StackBuilder = () => {
|
||||
<button
|
||||
type="button"
|
||||
onClick={getRandomStack}
|
||||
className="flex items-center gap-1 rounded border border-border bg-background px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
className="flex items-center gap-1 rounded border border-border px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
title="Generate a random stack"
|
||||
>
|
||||
<Shuffle className="h-3 w-3" />
|
||||
@@ -1549,7 +1505,7 @@ const StackBuilder = () => {
|
||||
<button
|
||||
type="button"
|
||||
onClick={loadSavedStack}
|
||||
className="flex items-center gap-1 rounded border border-border bg-background px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
className="flex items-center gap-1 rounded border border-border px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
title="Load saved preferences"
|
||||
>
|
||||
<Settings className="h-3 w-3" />
|
||||
@@ -1559,7 +1515,7 @@ const StackBuilder = () => {
|
||||
<button
|
||||
type="button"
|
||||
onClick={saveCurrentStack}
|
||||
className="flex items-center gap-1 rounded border border-border bg-background px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
className="flex items-center gap-1 rounded border border-border px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
title="Save current preferences"
|
||||
>
|
||||
<Star className="h-3 w-3" />
|
||||
@@ -1568,14 +1524,14 @@ const StackBuilder = () => {
|
||||
<button
|
||||
type="button"
|
||||
onClick={shareToTwitter}
|
||||
className="flex items-center gap-1 rounded border border-border bg-background px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
className="flex items-center gap-1 rounded border border-border px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted"
|
||||
title="Share to Twitter"
|
||||
>
|
||||
<Share2 className="h-3 w-3" />
|
||||
Share
|
||||
</button>
|
||||
</div>
|
||||
<div className="relative rounded border border-border bg-background p-2">
|
||||
<div className="relative rounded border border-border p-2">
|
||||
<div className="flex">
|
||||
<span className="mr-2 select-none text-chart-4">$</span>
|
||||
<code className="block break-all text-muted-foreground text-xs sm:text-sm">
|
||||
@@ -1625,7 +1581,7 @@ const StackBuilder = () => {
|
||||
type="button"
|
||||
key={preset.id}
|
||||
onClick={() => applyPreset(preset.id)}
|
||||
className="rounded border border-border bg-background p-2 text-left transition-colors hover:bg-muted"
|
||||
className="rounded border border-border p-2 text-left transition-colors hover:bg-muted"
|
||||
title={preset.description}
|
||||
>
|
||||
<div className="font-medium text-foreground text-sm">
|
||||
@@ -1687,7 +1643,7 @@ const StackBuilder = () => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4">
|
||||
<div className="grid grid-cols-2 gap-3 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4">
|
||||
{filteredOptions.map((tech) => {
|
||||
let isSelected = false;
|
||||
const category = categoryKey as keyof StackState;
|
||||
|
||||
@@ -118,11 +118,11 @@ export default function Testimonials() {
|
||||
ease: "easeOut",
|
||||
}}
|
||||
>
|
||||
<div className="terminal-block-hover w-full min-w-0 overflow-hidden rounded border border-border bg-background">
|
||||
<div className="sticky top-0 z-10 border-border border-b bg-muted/20 px-3 py-2">
|
||||
<div className="w-full min-w-0 overflow-hidden rounded border border-border">
|
||||
<div className="sticky top-0 z-10 border-border border-b px-3 py-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-xs">
|
||||
<span className=" font-semibold text-xs">
|
||||
[TWEET_{String(index + 1).padStart(3, "0")}]
|
||||
</span>
|
||||
</div>
|
||||
@@ -141,27 +141,27 @@ export default function Testimonials() {
|
||||
<div className="mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-5 w-5 text-primary" />
|
||||
<span className="font-bold font-mono text-lg sm:text-xl">
|
||||
<span className="font-bold text-lg sm:text-xl">
|
||||
DEVELOPER_TESTIMONIALS.LOG
|
||||
</span>
|
||||
</div>
|
||||
<div className="hidden h-px flex-1 bg-border sm:block" />
|
||||
<span className="w-full text-right font-mono text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
<span className="w-full text-right text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
[{TWEET_IDS.length} ENTRIES]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover mb-8 rounded border border-border bg-muted/20 p-4">
|
||||
<div className="mb-8 rounded border border-border p-4">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-foreground">
|
||||
# Community feedback from X (Twitter)
|
||||
<span className=" text-foreground">
|
||||
Community feedback from X (Twitter)
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
# Real developers sharing their experience
|
||||
<span className=" text-muted-foreground">
|
||||
Real developers sharing their experience
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart";
|
||||
import discordLogo from "@/public/icon/discord.svg";
|
||||
import Navbar from "../_components/navbar";
|
||||
|
||||
interface AnalyticsData {
|
||||
date: string;
|
||||
@@ -947,40 +946,39 @@ export default function AnalyticsPage() {
|
||||
const hourlyDistributionData = getHourlyDistributionData();
|
||||
|
||||
return (
|
||||
<div className="terminal-scanlines min-h-screen bg-background font-mono">
|
||||
<Navbar />
|
||||
<div className="terminal-matrix-bg container mx-auto max-w-7xl space-y-8 px-4 py-8 pt-28">
|
||||
<div className="min-h-svh">
|
||||
<div className="container mx-auto space-y-8 px-4 py-8 pt-16">
|
||||
<div className="mb-8">
|
||||
<div className="mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-5 w-5 text-primary" />
|
||||
<span className="font-bold font-mono text-lg sm:text-xl">
|
||||
<span className="font-bold text-lg sm:text-xl">
|
||||
ANALYTICS_DASHBOARD.EXE
|
||||
</span>
|
||||
</div>
|
||||
<div className="hidden h-px flex-1 bg-border sm:block" />
|
||||
<span className="w-full text-right font-mono text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
<span className="w-full text-right text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
[{totalProjects} PROJECTS_ANALYZED]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded rounded-b-none border border-border bg-muted/20 p-4">
|
||||
<div className="rounded rounded-b-none border border-border p-4">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-foreground">
|
||||
<span className=" text-foreground">
|
||||
Analytics from Better-T-Stack CLI usage data
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
<span className=" text-muted-foreground">
|
||||
Uses PostHog - no personal info tracked, runs on each project
|
||||
creation
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
<span className=" text-muted-foreground">
|
||||
Source:{" "}
|
||||
<Link
|
||||
href="https://github.com/amanvarshney01/create-better-t-stack/blob/main/apps/cli/src/utils/analytics.ts"
|
||||
@@ -1003,7 +1001,7 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
<span className=" text-muted-foreground">
|
||||
Last updated:{" "}
|
||||
{loadingLastUpdated
|
||||
? "CHECKING..."
|
||||
@@ -1018,23 +1016,27 @@ export default function AnalyticsPage() {
|
||||
href="https://discord.gg/ZYsbjpDaM5"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="terminal-block-hover block rounded rounded-t-none border border-border border-t-0 bg-background"
|
||||
className="block rounded rounded-t-none border border-border border-t-0"
|
||||
>
|
||||
<div className="flex items-center justify-between p-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<Image src={discordLogo} alt="discord" className="h-4 w-4" />
|
||||
<Image
|
||||
src={discordLogo}
|
||||
alt="discord"
|
||||
className="h-4 w-4 invert-0 dark:invert"
|
||||
/>
|
||||
<div>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
DISCORD_NOTIFICATIONS.IRC
|
||||
</span>
|
||||
<p className="font-mono text-muted-foreground text-xs">
|
||||
<p className=" text-muted-foreground text-xs">
|
||||
Join for LIVE project creation alerts
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1 rounded border border-border bg-primary/10 px-2 py-1">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-primary text-xs">
|
||||
<span className=" font-semibold text-primary text-xs">
|
||||
JOIN
|
||||
</span>
|
||||
</div>
|
||||
@@ -1044,162 +1046,144 @@ export default function AnalyticsPage() {
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<span className="font-bold font-mono text-lg">
|
||||
SYSTEM_METRICS.LOG
|
||||
</span>
|
||||
<span className="font-bold text-lg">SYSTEM_METRICS.LOG</span>
|
||||
<div className="h-px flex-1 bg-border" />
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-4">
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
TOTAL_PROJECTS
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">TOTAL_PROJECTS</span>
|
||||
<Terminal className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="font-bold font-mono text-2xl text-primary">
|
||||
<div className="font-bold text-2xl text-primary">
|
||||
{totalProjects.toLocaleString()}
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
$ ./create-better-t-stack executions
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
TOP_FRONTEND
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">TOP_FRONTEND</span>
|
||||
<Cpu className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="truncate font-bold font-mono text-accent text-lg">
|
||||
<div className="truncate font-bold text-accent text-lg">
|
||||
{mostPopularFrontend}
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
$ most_selected_frontend.sh
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
TOP_BACKEND
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">TOP_BACKEND</span>
|
||||
<Terminal className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="truncate font-bold font-mono text-accent text-lg">
|
||||
<div className="truncate font-bold text-accent text-lg">
|
||||
{mostPopularBackend}
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
$ most_selected_backend.sh
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
TOP_ORM
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">TOP_ORM</span>
|
||||
<Download className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="truncate font-bold font-mono text-accent text-lg">
|
||||
<div className="truncate font-bold text-accent text-lg">
|
||||
{getORMData().length > 0 ? getORMData()[0].name : "None"}
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
$ most_selected_orm.sh
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
TOP_API
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">TOP_API</span>
|
||||
<TrendingUp className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="truncate font-bold font-mono text-accent text-lg">
|
||||
<div className="truncate font-bold text-accent text-lg">
|
||||
{getAPIData().length > 0 ? getAPIData()[0].name : "None"}
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
$ most_selected_api.sh
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
AUTH_ADOPTION
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">AUTH_ADOPTION</span>
|
||||
<Users className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="font-bold font-mono text-2xl text-primary">
|
||||
<div className="font-bold text-2xl text-primary">
|
||||
{authEnabledPercent}%
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
$ auth_enabled_percentage.sh
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
TOP_PKG_MGR
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">TOP_PKG_MGR</span>
|
||||
<Terminal className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="truncate font-bold font-mono text-accent text-lg">
|
||||
<div className="truncate font-bold text-accent text-lg">
|
||||
{getPackageManagerData().length > 0
|
||||
? getPackageManagerData()[0].name
|
||||
: "npm"}
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
$ most_used_package_manager.sh
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
AVG_DAILY
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">AVG_DAILY</span>
|
||||
<TrendingUp className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="font-bold font-mono text-2xl text-primary">
|
||||
<div className="font-bold text-2xl text-primary">
|
||||
{avgProjectsPerDay.toFixed(1)}
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
$ average_projects_per_day.sh
|
||||
</p>
|
||||
</div>
|
||||
@@ -1209,23 +1193,21 @@ export default function AnalyticsPage() {
|
||||
|
||||
<div className="space-y-6">
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<span className="font-bold font-mono text-lg">
|
||||
TIMELINE_ANALYSIS.CHARTS
|
||||
</span>
|
||||
<span className="font-bold text-lg">TIMELINE_ANALYSIS.CHARTS</span>
|
||||
<div className="h-px flex-1 bg-border" />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
PROJECT_TIMELINE.CHART
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Daily project creation timeline from actual data
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Daily project creation timeline from actual data
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1258,16 +1240,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
MONTHLY_TRENDS.CHART
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Monthly project creation trends
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Monthly project creation trends
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1282,7 +1264,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
@@ -1296,16 +1278,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
PLATFORM_DISTRIBUTION.PIE
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Operating system distribution
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Operating system distribution
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1342,16 +1324,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
HOURLY_DISTRIBUTION.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Projects created by hour of day (UTC)
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Projects created by hour of day (UTC)
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1366,7 +1348,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip
|
||||
@@ -1387,26 +1369,26 @@ export default function AnalyticsPage() {
|
||||
<div className="space-y-6">
|
||||
<div className="mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-bold font-mono text-lg sm:text-xl">
|
||||
<span className="font-bold text-lg sm:text-xl">
|
||||
STACK_CONFIGURATION.DB
|
||||
</span>
|
||||
</div>
|
||||
<div className="hidden h-px flex-1 bg-border sm:block" />
|
||||
<span className="w-full text-right font-mono text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
<span className="w-full text-right text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
[CORE_COMPONENTS]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
POPULAR_STACK_COMBINATIONS.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Most popular frontend + backend combinations
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Most popular frontend + backend combinations
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1421,7 +1403,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
@@ -1435,16 +1417,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
FRONTEND_FRAMEWORKS.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Frontend framework and meta-framework usage
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Frontend framework and meta-framework usage
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1459,7 +1441,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
@@ -1477,16 +1459,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
BACKEND_FRAMEWORKS.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Backend framework distribution
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Backend framework distribution
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1517,16 +1499,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
DATABASE_DISTRIBUTION.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Database technology distribution
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Database technology distribution
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1557,16 +1539,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
ORM_DISTRIBUTION.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# ORM/Database layer distribution
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
ORM/Database layer distribution
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1594,16 +1576,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
DATABASE_HOSTING.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Database hosting service preferences
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Database hosting service preferences
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1634,16 +1616,14 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
API_LAYER.PIE
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">API_LAYER.PIE</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# API layer technology distribution
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
API layer technology distribution
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1673,16 +1653,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
AUTH_ADOPTION.PIE
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Authentication implementation rate
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Authentication implementation rate
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1718,16 +1698,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
RUNTIME_DISTRIBUTION.PIE
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# JavaScript runtime preference distribution
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
JavaScript runtime preference distribution
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1763,16 +1743,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
PROJECT_TYPES.PIE
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Full-stack vs Frontend-only vs Backend-only projects
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Full-stack vs Frontend-only vs Backend-only projects
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1809,16 +1789,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
DATABASE_ORM_COMBINATIONS.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Popular database + ORM combinations
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Popular database + ORM combinations
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1833,7 +1813,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
@@ -1843,16 +1823,14 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
ADDONS_USAGE.BAR
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">ADDONS_USAGE.BAR</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Additional features and tooling adoption
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Additional features and tooling adoption
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1867,7 +1845,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
@@ -1884,16 +1862,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
EXAMPLES_USAGE.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Example applications included in projects
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Example applications included in projects
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1908,7 +1886,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
@@ -1928,23 +1906,21 @@ export default function AnalyticsPage() {
|
||||
|
||||
<div className="space-y-6">
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<span className="font-bold font-mono text-lg">
|
||||
DEV_ENVIRONMENT.CONFIG
|
||||
</span>
|
||||
<span className="font-bold text-lg">DEV_ENVIRONMENT.CONFIG</span>
|
||||
<div className="h-px flex-1 bg-border" />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
GIT_INITIALIZATION.PIE
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Git repository initialization rate
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Git repository initialization rate
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -1977,16 +1953,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
PACKAGE_MANAGER.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Package manager usage distribution
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Package manager usage distribution
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -2017,16 +1993,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
INSTALL_PREFERENCE.PIE
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Automatic dependency installation preference
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Automatic dependency installation preference
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -2062,16 +2038,16 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
<span className=" font-semibold text-sm">
|
||||
NODE_VERSIONS.BAR
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# Node.js version distribution (major versions)
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
Node.js version distribution (major versions)
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -2086,7 +2062,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
@@ -2097,16 +2073,14 @@ export default function AnalyticsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="rounded border border-border">
|
||||
<div className="border-border border-b px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-primary text-xs">▶</span>
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
CLI_VERSIONS.BAR
|
||||
</span>
|
||||
<span className=" font-semibold text-sm">CLI_VERSIONS.BAR</span>
|
||||
</div>
|
||||
<p className="mt-1 font-mono text-muted-foreground text-xs">
|
||||
# CLI version distribution across project creations
|
||||
<p className="mt-1 text-muted-foreground text-xs">
|
||||
CLI version distribution across project creations
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
@@ -2121,7 +2095,7 @@ export default function AnalyticsPage() {
|
||||
tickLine={false}
|
||||
tickMargin={10}
|
||||
axisLine={false}
|
||||
className="font-mono text-xs"
|
||||
className=" text-xs"
|
||||
/>
|
||||
<YAxis hide />
|
||||
<ChartTooltip content={<ChartTooltipContent />} />
|
||||
|
||||
@@ -1,9 +1,32 @@
|
||||
import { type ReactNode, Suspense } from "react";
|
||||
"use client";
|
||||
|
||||
import { HomeLayout } from "fumadocs-ui/layouts/home";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { type ReactNode, useEffect } from "react";
|
||||
import { baseOptions } from "@/app/layout.config";
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => {
|
||||
const header = document.querySelector("#nd-nav");
|
||||
if (!header) return;
|
||||
|
||||
const main = document.querySelector("main");
|
||||
if (!main) return;
|
||||
|
||||
if (pathname === "/new") {
|
||||
header.classList.remove("*:mx-auto", "*:max-w-fd-container");
|
||||
main.classList.remove("max-w-[1400px]", "mx-auto", "min-h-svh");
|
||||
} else {
|
||||
header.classList.add("*:mx-auto", "*:max-w-fd-container");
|
||||
main.classList.add("max-w-[1400px]", "mx-auto", "min-h-svh");
|
||||
}
|
||||
}, [pathname]);
|
||||
|
||||
return (
|
||||
<main className="relative z-10 grid min-h-svh grid-cols-1 grid-rows-[auto_1fr_auto] overflow-hidden">
|
||||
<Suspense>{children}</Suspense>
|
||||
</main>
|
||||
<HomeLayout {...baseOptions}>
|
||||
<main className="h-full w-full">{children}</main>
|
||||
</HomeLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
"use client";
|
||||
|
||||
import { motion } from "motion/react";
|
||||
import { Suspense } from "react";
|
||||
import StackBuilder from "../_components/stack-builder";
|
||||
|
||||
export default function FullScreenStackBuilder() {
|
||||
return (
|
||||
<div className="flex h-svh flex-col bg-background">
|
||||
<Suspense>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="w-full flex-1"
|
||||
className="grid h-[calc(100vh-64px)] w-full flex-1 grid-cols-1 overflow-hidden"
|
||||
>
|
||||
<StackBuilder />
|
||||
</motion.div>
|
||||
</div>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,12 +10,10 @@ import {
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { TECH_OPTIONS } from "@/lib/constant";
|
||||
import { cn } from "@/lib/utils";
|
||||
import discordLogo from "@/public/icon/discord.svg";
|
||||
import Footer from "./_components/footer";
|
||||
import PackageIcon from "./_components/icons";
|
||||
import Navbar from "./_components/navbar";
|
||||
import NpmPackage from "./_components/npm-package";
|
||||
import SponsorsSection from "./_components/sponsors-section";
|
||||
import Testimonials from "./_components/testimonials";
|
||||
@@ -59,81 +57,9 @@ export default function HomePage() {
|
||||
setTimeout(() => setCopiedCommand(null), 2000);
|
||||
};
|
||||
|
||||
const frontendOptions = [
|
||||
...TECH_OPTIONS.webFrontend.filter((option) => option.id !== "none"),
|
||||
...TECH_OPTIONS.nativeFrontend.filter((option) => option.id !== "none"),
|
||||
];
|
||||
|
||||
const backendOptions = TECH_OPTIONS.backend.filter(
|
||||
(option) => option.id !== "none",
|
||||
);
|
||||
const databaseOptions = TECH_OPTIONS.database.filter(
|
||||
(option) => option.id !== "none",
|
||||
);
|
||||
const runtimeOptions = TECH_OPTIONS.runtime;
|
||||
const packageManagerOptions = TECH_OPTIONS.packageManager;
|
||||
const apiOptions = TECH_OPTIONS.api.filter((option) => option.id !== "none");
|
||||
const ormOptions = TECH_OPTIONS.orm.filter((option) => option.id !== "none");
|
||||
const dbSetupOptions = TECH_OPTIONS.dbSetup.filter(
|
||||
(option) => option.id !== "none",
|
||||
);
|
||||
const authOptions = TECH_OPTIONS.auth.filter(
|
||||
(option) => option.id !== "false",
|
||||
);
|
||||
const addonsOptions = TECH_OPTIONS.addons;
|
||||
const examplesOptions = TECH_OPTIONS.examples;
|
||||
|
||||
const techStackCategories = [
|
||||
{
|
||||
category: "Frontend",
|
||||
options: frontendOptions,
|
||||
},
|
||||
{
|
||||
category: "Backend",
|
||||
options: backendOptions,
|
||||
},
|
||||
{
|
||||
category: "Database",
|
||||
options: databaseOptions,
|
||||
},
|
||||
{
|
||||
category: "Runtime",
|
||||
options: runtimeOptions,
|
||||
},
|
||||
{
|
||||
category: "API",
|
||||
options: apiOptions,
|
||||
},
|
||||
{
|
||||
category: "ORM",
|
||||
options: ormOptions,
|
||||
},
|
||||
{
|
||||
category: "Database Setup",
|
||||
options: dbSetupOptions,
|
||||
},
|
||||
{
|
||||
category: "Authentication",
|
||||
options: authOptions,
|
||||
},
|
||||
{
|
||||
category: "Package Managers",
|
||||
options: packageManagerOptions,
|
||||
},
|
||||
{
|
||||
category: "Addons",
|
||||
options: addonsOptions,
|
||||
},
|
||||
{
|
||||
category: "Examples",
|
||||
options: examplesOptions,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="terminal-scanlines min-h-screen bg-background font-mono">
|
||||
<Navbar />
|
||||
<main className="terminal-matrix-bg mx-auto max-w-7xl p-6 pt-28">
|
||||
<div className="min-h-svh">
|
||||
<main className="mx-auto px-4 pt-16">
|
||||
<div className="mb-8 flex items-center justify-center">
|
||||
<div className="flex flex-wrap items-center justify-center gap-2 sm:gap-4 md:gap-6">
|
||||
<pre className="ascii-art text-primary text-xs leading-tight sm:text-sm">
|
||||
@@ -179,30 +105,29 @@ export default function HomePage() {
|
||||
</div>
|
||||
|
||||
<div className="mb-6 text-center">
|
||||
<p className="mx-auto font-mono text-lg text-muted-foreground">
|
||||
# Modern CLI for scaffolding end-to-end type-safe TypeScript
|
||||
projects
|
||||
<p className="mx-auto text-lg text-muted-foreground">
|
||||
Modern CLI for scaffolding end-to-end type-safe TypeScript projects
|
||||
</p>
|
||||
<p className="mx-auto mt-2 max-w-2xl font-mono text-muted-foreground text-sm">
|
||||
# Production-ready • Customizable • Best practices included
|
||||
<p className="mx-auto mt-2 max-w-2xl text-muted-foreground text-sm">
|
||||
Production-ready • Customizable • Best practices included
|
||||
</p>
|
||||
<NpmPackage />
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover mb-8 rounded border border-border bg-muted/20 p-4">
|
||||
<div className=" mb-8 rounded border border-border p-4">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-4 w-4 text-primary" />
|
||||
<span className="font-semibold text-sm">QUICK_START</span>
|
||||
</div>
|
||||
<div className="flex items-center rounded border border-border bg-background p-0.5">
|
||||
<div className="flex items-center rounded border border-border p-0.5">
|
||||
{(["bun", "pnpm", "npm"] as const).map((pm) => (
|
||||
<button
|
||||
type="button"
|
||||
key={pm}
|
||||
onClick={() => setSelectedPM(pm)}
|
||||
className={cn(
|
||||
"flex items-center gap-1.5 rounded px-2 py-1 font-mono text-xs transition-colors duration-150",
|
||||
"flex items-center gap-1.5 rounded px-2 py-1 text-xs transition-colors duration-150",
|
||||
selectedPM === pm
|
||||
? "bg-primary/20 text-primary"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
@@ -216,17 +141,15 @@ export default function HomePage() {
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between rounded border border-border bg-background p-3">
|
||||
<div className="flex items-center justify-between rounded border border-border p-3">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-foreground">
|
||||
{commands[selectedPM]}
|
||||
</span>
|
||||
<span className=" text-foreground">{commands[selectedPM]}</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyCommand(commands[selectedPM], selectedPM)}
|
||||
className="terminal-block-hover flex items-center gap-1 rounded border border-border bg-muted/20 px-2 py-1 text-xs hover:bg-muted/50"
|
||||
className="flex items-center gap-1 rounded border border-border px-2 py-1 text-xs hover:bg-muted/50"
|
||||
>
|
||||
{copiedCommand === selectedPM ? (
|
||||
<Check className="h-3 w-3 text-primary" />
|
||||
@@ -241,14 +164,12 @@ export default function HomePage() {
|
||||
|
||||
<div className="mb-12 grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||
<Link href="/new">
|
||||
<div className="group terminal-block-hover cursor-pointer rounded border border-border bg-background p-4">
|
||||
<div className="group cursor-pointer rounded border border-border p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<ChevronRight className="h-4 w-4 text-primary" />
|
||||
<span className="font-mono font-semibold">
|
||||
STACK_BUILDER.EXE
|
||||
</span>
|
||||
<span className=" font-semibold">STACK_BUILDER.EXE</span>
|
||||
</div>
|
||||
<p className="mt-2 font-mono text-muted-foreground text-sm">
|
||||
<p className="mt-2 text-muted-foreground text-sm">
|
||||
[EXEC] Interactive configuration wizard
|
||||
</p>
|
||||
</div>
|
||||
@@ -259,22 +180,20 @@ export default function HomePage() {
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<div className="group terminal-block-hover cursor-pointer rounded border border-border bg-background p-4">
|
||||
<div className="group cursor-pointer rounded border border-border p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Github className="h-4 w-4 text-primary" />
|
||||
<span className="font-mono font-semibold">
|
||||
GITHUB_REPO.GIT
|
||||
</span>
|
||||
<span className=" font-semibold">GITHUB_REPO.GIT</span>
|
||||
</div>
|
||||
{stars !== null && !isLoadingStars && (
|
||||
<div className="flex items-center gap-1 rounded border border-border bg-muted/30 px-2 py-1 font-mono text-xs">
|
||||
<div className="flex items-center gap-1 rounded border border-border bg-muted/30 px-2 py-1 text-xs">
|
||||
<Star className="h-3 w-3 text-accent" />
|
||||
{stars}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<p className="mt-2 font-mono text-muted-foreground text-sm">
|
||||
<p className="mt-2 text-muted-foreground text-sm">
|
||||
[LINK] Star the repository on GitHub
|
||||
</p>
|
||||
</div>
|
||||
@@ -285,131 +204,22 @@ export default function HomePage() {
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<div className="group terminal-block-hover cursor-pointer rounded border border-border bg-background p-4">
|
||||
<div className="group cursor-pointer rounded border border-border p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Image src={discordLogo} alt="discord" className="h-4 w-4" />
|
||||
<span className="font-mono font-semibold">
|
||||
DISCORD_CHAT.IRC
|
||||
</span>
|
||||
<Image
|
||||
src={discordLogo}
|
||||
alt="discord"
|
||||
className="h-4 w-4 invert-0 dark:invert"
|
||||
/>
|
||||
<span className=" font-semibold">DISCORD_CHAT.IRC</span>
|
||||
</div>
|
||||
<p className="mt-2 font-mono text-muted-foreground text-sm">
|
||||
<p className="mt-2 text-muted-foreground text-sm">
|
||||
[JOIN] Connect to developer community
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="mb-12">
|
||||
<div className="mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-5 w-5 text-primary" />
|
||||
<span className="font-bold font-mono text-lg sm:text-xl">
|
||||
TECH_STACK_MATRIX.DB
|
||||
</span>
|
||||
</div>
|
||||
<div className="hidden h-px flex-1 bg-border sm:block" />
|
||||
<span className="w-full text-right font-mono text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
[
|
||||
{techStackCategories.reduce(
|
||||
(acc, cat) => acc + cat.options.length,
|
||||
0,
|
||||
)}{" "}
|
||||
PACKAGES]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-4 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-4 w-4 text-primary" />
|
||||
<span className="font-mono font-semibold text-sm">
|
||||
/tech-stack/packages/
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3 p-4">
|
||||
{techStackCategories.map((category, categoryIndex) => (
|
||||
<div key={category.category} className="space-y-2">
|
||||
<div className="directory-header flex items-center gap-2 rounded px-2 py-2 transition-colors">
|
||||
<span className="font-mono font-semibold text-foreground text-sm">
|
||||
{category.category.toLowerCase().replace(/\s+/g, "-")}/
|
||||
</span>
|
||||
<span className="font-mono text-muted-foreground text-xs">
|
||||
({category.options.length} items)
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="ml-6 grid grid-cols-1 gap-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
{category.options.map((option, optionIndex) => (
|
||||
<div
|
||||
key={option.id}
|
||||
className="file-browser-item file-load-animation flex items-center gap-3 rounded border border-border bg-muted/10 px-3 py-2"
|
||||
style={{
|
||||
animationDelay: `${
|
||||
categoryIndex * 100 + optionIndex * 30
|
||||
}ms`,
|
||||
}}
|
||||
>
|
||||
{option.icon !== "" && (
|
||||
<Image
|
||||
src={option.icon}
|
||||
alt={option.name}
|
||||
height={16}
|
||||
width={16}
|
||||
unoptimized
|
||||
className="file-icon h-4 w-4 flex-shrink-0"
|
||||
/>
|
||||
)}
|
||||
<span className="flex-1 truncate font-mono text-xs">
|
||||
{option.name.toLowerCase().replace(/\s+/g, "-")}
|
||||
</span>
|
||||
<span className="font-mono text-muted-foreground text-xs opacity-0 transition-opacity group-hover:opacity-100">
|
||||
-rw-r--r--
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="border-border border-t bg-muted/20 px-4 py-2">
|
||||
<div className="flex items-center justify-between text-xs">
|
||||
<span className="font-mono text-muted-foreground">
|
||||
$ ls -la /tech-stack/packages/
|
||||
</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
{techStackCategories.length} directories,{" "}
|
||||
{techStackCategories.reduce(
|
||||
(acc, cat) => acc + cat.options.length,
|
||||
0,
|
||||
)}{" "}
|
||||
files
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover mb-8 rounded border border-border bg-muted/20 p-4">
|
||||
<div className="mb-2 font-mono font-semibold text-sm">
|
||||
SYSTEM_INFO.LOG
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-2 font-mono text-xs md:grid-cols-3">
|
||||
<div>
|
||||
<span className="text-primary">OS:</span> TypeScript_Runtime_v5.x
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-primary">ARCH:</span> Full_Stack_Framework
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-primary">STATUS:</span>{" "}
|
||||
<span className="text-accent">READY</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SponsorsSection />
|
||||
<Testimonials />
|
||||
</main>
|
||||
|
||||
@@ -26,11 +26,11 @@ export default function ShowcaseItem({
|
||||
const projectId = `PROJECT_${String(index + 1).padStart(3, "0")}`;
|
||||
|
||||
return (
|
||||
<div className="terminal-block-hover flex h-full flex-col overflow-hidden rounded border border-border bg-background">
|
||||
<div className="border-border border-b bg-muted/20 px-3 py-2">
|
||||
<div className="flex h-full flex-col overflow-hidden rounded border border-border">
|
||||
<div className="border-border border-b px-3 py-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<File className="h-3 w-3 text-primary" />
|
||||
<span className="font-mono font-semibold text-foreground text-xs">
|
||||
<span className=" font-semibold text-foreground text-xs">
|
||||
{projectId}.PROJECT
|
||||
</span>
|
||||
<div className="ml-auto flex items-center gap-2 text-muted-foreground text-xs">
|
||||
@@ -52,17 +52,15 @@ export default function ShowcaseItem({
|
||||
</div>
|
||||
|
||||
<div className="flex flex-1 flex-col p-4">
|
||||
<h3 className="mb-2 font-bold font-mono text-lg text-primary">
|
||||
{title}
|
||||
</h3>
|
||||
<h3 className="mb-2 font-bold text-lg text-primary">{title}</h3>
|
||||
|
||||
<p className="mb-4 flex-grow font-mono text-muted-foreground text-sm leading-relaxed">
|
||||
<p className="mb-4 flex-grow text-muted-foreground text-sm leading-relaxed">
|
||||
{description}
|
||||
</p>
|
||||
|
||||
<div className="mb-4">
|
||||
<div className="mb-2 flex items-center gap-2">
|
||||
<span className="font-mono text-muted-foreground text-xs">
|
||||
<span className=" text-muted-foreground text-xs">
|
||||
DEPENDENCIES:
|
||||
</span>
|
||||
</div>
|
||||
@@ -70,7 +68,7 @@ export default function ShowcaseItem({
|
||||
{tags.map((tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="rounded border border-border bg-muted/30 px-2 py-1 font-mono text-foreground text-xs transition-colors hover:bg-muted/50"
|
||||
className="rounded border border-border bg-muted/30 px-2 py-1 text-foreground text-xs transition-colors hover:bg-muted/50"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
@@ -85,7 +83,7 @@ export default function ShowcaseItem({
|
||||
href={liveUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-2 rounded border border-border bg-primary/10 px-3 py-2 font-mono text-primary text-sm transition-all hover:bg-primary/20 hover:text-primary"
|
||||
className="flex items-center gap-2 rounded border border-border bg-primary/10 px-3 py-2 text-primary text-sm transition-all hover:bg-primary/20 hover:text-primary"
|
||||
>
|
||||
<Monitor className="h-3 w-3" />
|
||||
<span>LAUNCH_DEMO.EXE</span>
|
||||
@@ -97,7 +95,7 @@ export default function ShowcaseItem({
|
||||
href={sourceUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-2 rounded border border-border bg-muted/20 px-3 py-2 font-mono text-muted-foreground text-sm transition-all hover:bg-muted/40 hover:text-foreground"
|
||||
className="flex items-center gap-2 rounded border border-border px-3 py-2 text-muted-foreground text-sm transition-all hover:bg-muted/40 hover:text-foreground"
|
||||
>
|
||||
<Github className="h-3 w-3" />
|
||||
<span>VIEW_SOURCE.GIT</span>
|
||||
@@ -109,12 +107,12 @@ export default function ShowcaseItem({
|
||||
<div className="border-border border-t pt-2">
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
<span className=" text-muted-foreground">
|
||||
echo "Status: READY"
|
||||
</span>
|
||||
<div className="ml-auto flex items-center gap-1">
|
||||
<div className="h-1 w-1 animate-pulse rounded-full bg-green-400" />
|
||||
<span className="font-mono text-green-400 text-xs">ONLINE</span>
|
||||
<span className=" text-green-400 text-xs">ONLINE</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { FolderOpen, Terminal } from "lucide-react";
|
||||
import Navbar from "../_components/navbar";
|
||||
import { Terminal } from "lucide-react";
|
||||
import ShowcaseItem from "./_components/ShowcaseItem";
|
||||
|
||||
const showcaseProjects = [
|
||||
@@ -71,79 +70,61 @@ const showcaseProjects = [
|
||||
|
||||
export default function ShowcasePage() {
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<main className="flex min-h-svh flex-col items-center bg-background px-4 pt-24 pb-10 sm:px-6 md:px-8 md:pt-28 lg:pt-32">
|
||||
<div className="mx-auto w-full max-w-6xl">
|
||||
<div className="mb-8">
|
||||
<div className="mb-6 flex items-center gap-2">
|
||||
<main className="min-h-svh">
|
||||
<div className="container mx-auto space-y-8 px-4 py-8 pt-16">
|
||||
<div className="mb-8">
|
||||
<div className="mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-4 w-4 text-primary" />
|
||||
<span className="font-bold font-mono text-lg">
|
||||
<span className="font-bold text-lg sm:text-xl">
|
||||
PROJECT_SHOWCASE.EXE
|
||||
</span>
|
||||
<div className="h-px flex-1 bg-border" />
|
||||
<span className="font-mono text-muted-foreground text-xs">
|
||||
[{showcaseProjects.length} PROJECTS FOUND]
|
||||
</div>
|
||||
<div className="h-px flex-1 bg-border" />
|
||||
<span className=" text-muted-foreground text-xs">
|
||||
[{showcaseProjects.length} PROJECTS FOUND]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="mb-8 rounded border border-border p-4">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className=" text-foreground">
|
||||
user@dev-machine:~/showcase$ ls -la
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover mb-8 rounded border border-border bg-muted/20 p-4">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-foreground">
|
||||
user@dev-machine:~/showcase$ ls -la
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
# Discover amazing projects built with Better-T-Stack
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
# Real-world implementations showcasing stack capabilities
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className=" text-muted-foreground">
|
||||
Discover amazing projects built with Better-T-Stack
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="terminal-block-hover rounded border border-border bg-background p-3">
|
||||
<div className="flex items-center gap-2 font-mono text-sm">
|
||||
<FolderOpen className="h-4 w-4 text-blue-400" />
|
||||
<span className="text-foreground">/showcase/projects/</span>
|
||||
<div className="ml-auto text-muted-foreground text-xs">
|
||||
drwxr-xr-x {showcaseProjects.length} items
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3">
|
||||
{showcaseProjects.map((project, index) => (
|
||||
<ShowcaseItem key={project.title} {...project} index={index} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-8">
|
||||
<div className="terminal-block-hover rounded border border-border bg-muted/20 p-4">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-muted-foreground">
|
||||
# Want to showcase your project? Submit via GitHub issues
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className="font-mono text-foreground">
|
||||
echo "Built something amazing? We'd love to feature
|
||||
it!"
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className=" text-muted-foreground">
|
||||
Real-world implementations showcasing stack capabilities
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3">
|
||||
{showcaseProjects.map((project, index) => (
|
||||
<ShowcaseItem key={project.title} {...project} index={index} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mt-8">
|
||||
<div className="rounded border border-border p-4">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">$</span>
|
||||
<span className=" text-muted-foreground">
|
||||
Want to showcase your project? Submit via GitHub issues
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Features from "components/features";
|
||||
import * as TabsComponents from "fumadocs-ui/components/tabs";
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||
import {
|
||||
DocsBody,
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
DocsTitle,
|
||||
} from "fumadocs-ui/page";
|
||||
import { notFound } from "next/navigation";
|
||||
import { LLMCopyButton, ViewOptions } from "@/components/ai/page-actions";
|
||||
import { source } from "@/lib/source";
|
||||
|
||||
export default async function Page(props: {
|
||||
@@ -22,8 +23,15 @@ export default async function Page(props: {
|
||||
<DocsPage toc={page.data.toc} full={page.data.full}>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<DocsDescription>{page.data.description}</DocsDescription>
|
||||
<div className="flex flex-row items-center gap-2 border-b pt-2 pb-6">
|
||||
<LLMCopyButton markdownUrl={`${page.url}.mdx`} />
|
||||
<ViewOptions
|
||||
markdownUrl={`${page.url}.mdx`}
|
||||
githubUrl={`https://github.com/amanvarshney01/create-better-t-stack/blob/dev/apps/docs/content/docs/${page.path}`}
|
||||
/>
|
||||
</div>
|
||||
<DocsBody>
|
||||
<MDX components={{ ...defaultMdxComponents, Features }} />
|
||||
<MDX components={{ ...defaultMdxComponents, ...TabsComponents }} />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
);
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
@import "tailwindcss";
|
||||
@import "fumadocs-ui/css/shadcn.css";
|
||||
@import "fumadocs-ui/css/neutral.css";
|
||||
@import "fumadocs-ui/css/preset.css";
|
||||
@import "tw-animate-css";
|
||||
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
/* .bg-noise {
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%' height='100%' filter='url(%23noise)' opacity='0.4'/%3E%3C/svg%3E");
|
||||
} */
|
||||
:root {
|
||||
/* --fd-layout-width: 1400px; */
|
||||
/* --max-w-fh-container: 100%; */
|
||||
}
|
||||
|
||||
.react-tweet-theme {
|
||||
--tweet-container-margin: 0 !important;
|
||||
@apply !bg-background !border-none !h-full !border-transparent !w-full;
|
||||
@apply !bg-fd-background !border-none !h-full !border-transparent !w-full;
|
||||
max-width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
@@ -215,15 +216,20 @@
|
||||
--spacing: 0.25rem;
|
||||
--shadow-2xs: 0px 4px 6px 0px hsl(240 30% 25% / 0.06);
|
||||
--shadow-xs: 0px 4px 6px 0px hsl(240 30% 25% / 0.06);
|
||||
--shadow-sm: 0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 1px 2px -1px
|
||||
--shadow-sm:
|
||||
0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 1px 2px -1px
|
||||
hsl(240 30% 25% / 0.12);
|
||||
--shadow: 0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 1px 2px -1px
|
||||
--shadow:
|
||||
0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 1px 2px -1px
|
||||
hsl(240 30% 25% / 0.12);
|
||||
--shadow-md: 0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 2px 4px -1px
|
||||
--shadow-md:
|
||||
0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 2px 4px -1px
|
||||
hsl(240 30% 25% / 0.12);
|
||||
--shadow-lg: 0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 4px 6px -1px
|
||||
--shadow-lg:
|
||||
0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 4px 6px -1px
|
||||
hsl(240 30% 25% / 0.12);
|
||||
--shadow-xl: 0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 8px 10px -1px
|
||||
--shadow-xl:
|
||||
0px 4px 6px 0px hsl(240 30% 25% / 0.12), 0px 8px 10px -1px
|
||||
hsl(240 30% 25% / 0.12);
|
||||
--shadow-2xl: 0px 4px 6px 0px hsl(240 30% 25% / 0.3);
|
||||
--tracking-normal: 0em;
|
||||
@@ -278,28 +284,33 @@
|
||||
--spacing: 0.25rem;
|
||||
--shadow-2xs: 0px 2px 4px 0px hsl(240 30% 5% / 0.15);
|
||||
--shadow-xs: 0px 2px 4px 0px hsl(240 30% 5% / 0.15);
|
||||
--shadow-sm: 0px 4px 8px 0px hsl(240 30% 5% / 0.2), 0px 1px 2px -1px
|
||||
--shadow-sm:
|
||||
0px 4px 8px 0px hsl(240 30% 5% / 0.2), 0px 1px 2px -1px
|
||||
hsl(240 30% 5% / 0.15);
|
||||
--shadow: 0px 4px 8px 0px hsl(240 30% 5% / 0.2), 0px 1px 2px -1px
|
||||
--shadow:
|
||||
0px 4px 8px 0px hsl(240 30% 5% / 0.2), 0px 1px 2px -1px
|
||||
hsl(240 30% 5% / 0.15);
|
||||
--shadow-md: 0px 6px 12px 0px hsl(240 30% 5% / 0.25), 0px 2px 4px -1px
|
||||
--shadow-md:
|
||||
0px 6px 12px 0px hsl(240 30% 5% / 0.25), 0px 2px 4px -1px
|
||||
hsl(240 30% 5% / 0.2);
|
||||
--shadow-lg: 0px 8px 16px 0px hsl(240 30% 5% / 0.3), 0px 4px 6px -1px
|
||||
--shadow-lg:
|
||||
0px 8px 16px 0px hsl(240 30% 5% / 0.3), 0px 4px 6px -1px
|
||||
hsl(240 30% 5% / 0.25);
|
||||
--shadow-xl: 0px 12px 24px 0px hsl(240 30% 5% / 0.35), 0px 8px 10px -1px
|
||||
--shadow-xl:
|
||||
0px 12px 24px 0px hsl(240 30% 5% / 0.35), 0px 8px 10px -1px
|
||||
hsl(240 30% 5% / 0.3);
|
||||
--shadow-2xl: 0px 16px 32px 0px hsl(240 30% 5% / 0.4);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
/* @layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
@apply text-foreground;
|
||||
letter-spacing: var(--tracking-normal);
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
.terminal-cursor {
|
||||
animation: blink 1s infinite;
|
||||
@@ -339,10 +350,6 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.terminal-block-hover {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.terminal-block-hover:hover {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 10px rgba(136, 57, 239, 0.3);
|
||||
|
||||
@@ -1,16 +1,61 @@
|
||||
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
|
||||
import Image from "next/image";
|
||||
import discordLogo from "@/public/icon/discord.svg";
|
||||
import mainLogo from "@/public/logo.svg";
|
||||
|
||||
export const logo = (
|
||||
<>
|
||||
<Image
|
||||
alt="better-t-stack"
|
||||
src={mainLogo}
|
||||
className="w-8"
|
||||
aria-label="better-t-stack"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
/**
|
||||
* Shared layout configurations
|
||||
*
|
||||
* you can configure layouts individually from:
|
||||
* Home Layout: app/(home)/layout.tsx
|
||||
* Docs Layout: app/docs/layout.tsx
|
||||
*/
|
||||
export const baseOptions: BaseLayoutProps = {
|
||||
nav: {
|
||||
title: "Better-T-Stack",
|
||||
enabled: false,
|
||||
title: (
|
||||
<>
|
||||
{logo}
|
||||
|
||||
<span className="font-medium [.uwu_&]:hidden [header_&]:text-[15px]">
|
||||
Better T Stack
|
||||
</span>
|
||||
</>
|
||||
),
|
||||
// enabled: false,
|
||||
},
|
||||
links: [
|
||||
{
|
||||
text: "Docs",
|
||||
url: "/docs",
|
||||
},
|
||||
{
|
||||
text: "Builder",
|
||||
url: "/new",
|
||||
},
|
||||
{
|
||||
text: "Analytics",
|
||||
url: "/analytics",
|
||||
},
|
||||
{
|
||||
text: "Showcase",
|
||||
url: "/showcase",
|
||||
},
|
||||
{
|
||||
text: (
|
||||
<Image
|
||||
src={discordLogo}
|
||||
alt="discord"
|
||||
className="size-5 invert-0 dark:invert"
|
||||
/>
|
||||
),
|
||||
url: "https://discord.gg/ZYsbjpDaM5",
|
||||
external: true,
|
||||
secondary: true,
|
||||
},
|
||||
],
|
||||
githubUrl: "https://github.com/AmanVarshney01/create-better-t-stack",
|
||||
};
|
||||
|
||||
183
apps/web/src/components/ai/page-actions.tsx
Normal file
183
apps/web/src/components/ai/page-actions.tsx
Normal file
@@ -0,0 +1,183 @@
|
||||
"use client";
|
||||
import { cva } from "class-variance-authority";
|
||||
import { buttonVariants } from "fumadocs-ui/components/ui/button";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "fumadocs-ui/components/ui/popover";
|
||||
import { useCopyButton } from "fumadocs-ui/utils/use-copy-button";
|
||||
import {
|
||||
Check,
|
||||
ChevronDown,
|
||||
Copy,
|
||||
ExternalLinkIcon,
|
||||
MessageCircleIcon,
|
||||
} from "lucide-react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { cn } from "../../../lib/cn";
|
||||
|
||||
const cache = new Map<string, string>();
|
||||
|
||||
export function LLMCopyButton({
|
||||
/**
|
||||
* A URL to fetch the raw Markdown/MDX content of page
|
||||
*/
|
||||
markdownUrl,
|
||||
}: {
|
||||
markdownUrl: string;
|
||||
}) {
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
const [checked, onClick] = useCopyButton(async () => {
|
||||
const cached = cache.get(markdownUrl);
|
||||
if (cached) return navigator.clipboard.writeText(cached);
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
await navigator.clipboard.write([
|
||||
new ClipboardItem({
|
||||
"text/plain": fetch(markdownUrl).then(async (res) => {
|
||||
const content = await res.text();
|
||||
cache.set(markdownUrl, content);
|
||||
|
||||
return content;
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<button
|
||||
disabled={isLoading}
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: "secondary",
|
||||
size: "sm",
|
||||
className: "gap-2 [&_svg]:size-3.5 [&_svg]:text-fd-muted-foreground",
|
||||
}),
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
{checked ? <Check /> : <Copy />}
|
||||
Copy Markdown
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
const optionVariants = cva(
|
||||
"inline-flex items-center gap-2 rounded-lg p-2 text-sm hover:bg-fd-accent hover:text-fd-accent-foreground [&_svg]:size-4",
|
||||
);
|
||||
|
||||
export function ViewOptions({
|
||||
markdownUrl,
|
||||
githubUrl,
|
||||
}: {
|
||||
/**
|
||||
* A URL to the raw Markdown/MDX content of page
|
||||
*/
|
||||
markdownUrl: string;
|
||||
|
||||
/**
|
||||
* Source file URL on GitHub
|
||||
*/
|
||||
githubUrl: string;
|
||||
}) {
|
||||
const items = useMemo(() => {
|
||||
const fullMarkdownUrl =
|
||||
typeof window !== "undefined"
|
||||
? new URL(markdownUrl, window.location.origin)
|
||||
: "loading";
|
||||
const q = `Read ${fullMarkdownUrl}, I want to ask questions about it.`;
|
||||
|
||||
return [
|
||||
{
|
||||
title: "Open in GitHub",
|
||||
href: githubUrl,
|
||||
icon: (
|
||||
<svg fill="currentColor" role="img" viewBox="0 0 24 24">
|
||||
<title>GitHub</title>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Open in ChatGPT",
|
||||
href: `https://chatgpt.com/?${new URLSearchParams({
|
||||
hints: "search",
|
||||
q,
|
||||
})}`,
|
||||
icon: (
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>OpenAI</title>
|
||||
<path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z" />
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Open in Claude",
|
||||
href: `https://claude.ai/new?${new URLSearchParams({
|
||||
q,
|
||||
})}`,
|
||||
icon: (
|
||||
<svg
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>Anthropic</title>
|
||||
<path d="M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z" />
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Open in T3 Chat",
|
||||
href: `https://t3.chat/new?${new URLSearchParams({
|
||||
q,
|
||||
})}`,
|
||||
icon: <MessageCircleIcon />,
|
||||
},
|
||||
];
|
||||
}, [githubUrl, markdownUrl]);
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger
|
||||
className={cn(
|
||||
buttonVariants({
|
||||
color: "secondary",
|
||||
size: "sm",
|
||||
className: "gap-2",
|
||||
}),
|
||||
)}
|
||||
>
|
||||
Open
|
||||
<ChevronDown className="size-3.5 text-fd-muted-foreground" />
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="flex flex-col overflow-auto">
|
||||
{items.map((item) => (
|
||||
<a
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
className={cn(optionVariants())}
|
||||
>
|
||||
{item.icon}
|
||||
{item.title}
|
||||
<ExternalLinkIcon className="ms-auto size-3.5 text-fd-muted-foreground" />
|
||||
</a>
|
||||
))}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
@@ -31,7 +31,7 @@ export function ThemeToggle({ className }: { className?: string }) {
|
||||
disabled
|
||||
aria-label="Toggle theme (loading)"
|
||||
>
|
||||
<span className="block h-3 w-3 rounded-full bg-background shadow-lg ring-0" />
|
||||
<span className="block h-3 w-3 rounded-full shadow-lg ring-0" />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -48,7 +48,7 @@ export function ThemeToggle({ className }: { className?: string }) {
|
||||
>
|
||||
<SwitchPrimitives.Thumb
|
||||
className={cn(
|
||||
"pointer-events-none flex h-3 w-3 items-center justify-center rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0",
|
||||
"pointer-events-none flex h-3 w-3 items-center justify-center rounded-full shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0",
|
||||
)}
|
||||
>
|
||||
{isChecked ? (
|
||||
|
||||
Reference in New Issue
Block a user