From a757c10b607d3ebfbde8369324e9b1330fc9b2f0 Mon Sep 17 00:00:00 2001 From: Nicholai Date: Thu, 22 Jan 2026 04:54:28 -0700 Subject: [PATCH] chore: add missing deps and project docs - add clsx, tailwind-merge, tw-animate-css deps - add src/lib/utils.ts with cn() helper - add CLAUDE.md with project overview --- CLAUDE.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ bun.lock | 7 +++++ package.json | 3 +++ src/lib/utils.ts | 6 +++++ 4 files changed, 84 insertions(+) create mode 100644 CLAUDE.md create mode 100644 src/lib/utils.ts diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6999869 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,68 @@ +dashboard-app-template +=== + +a Next.js 15 dashboard template deployed to Cloudflare Workers via OpenNext. + +tech stack +--- + +- Next.js 15.5 with Turbopack +- React 19 +- Tailwind CSS v4 +- shadcn/ui (new-york style) +- Recharts for data visualization +- Cloudflare Workers (via @opennextjs/cloudflare) + +commands +--- + +- `bun dev` - start dev server (turbopack) +- `bun build` - production build +- `bun preview` - build and preview on cloudflare runtime +- `bun deploy` - build and deploy to cloudflare +- `bun lint` - run eslint + +project structure +--- + +``` +src/ +├── app/ # Next.js app router +│ ├── dashboard/ # dashboard routes +│ ├── globals.css # tailwind + theme variables +│ ├── layout.tsx # root layout +│ └── page.tsx # home page +├── components/ +│ ├── ui/ # shadcn/ui primitives +│ └── *.tsx # app-specific components (sidebar, charts, tables) +├── hooks/ # custom react hooks +└── lib/ + └── utils.ts # cn() helper for class merging +``` + +shadcn/ui +--- + +uses shadcn/ui with new-york style. add components via: + +```bash +bunx shadcn@latest add +``` + +config in `components.json`. aliases: +- `@/components` -> src/components +- `@/components/ui` -> src/components/ui +- `@/lib` -> src/lib +- `@/hooks` -> src/hooks + +cloudflare deployment +--- + +configured in `wrangler.jsonc`. uses OpenNext for Next.js compatibility. + +env vars go in `.dev.vars` (local) or cloudflare dashboard (prod). + +key bindings: +- `ASSETS` - static asset serving +- `IMAGES` - cloudflare image optimization +- `WORKER_SELF_REFERENCE` - self-reference for caching diff --git a/bun.lock b/bun.lock index 2d03752..e4db2d5 100644 --- a/bun.lock +++ b/bun.lock @@ -40,6 +40,7 @@ "@tabler/icons-react": "^3.36.1", "@tanstack/react-table": "^8.21.3", "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "embla-carousel-react": "^8.6.0", @@ -54,6 +55,8 @@ "react-resizable-panels": "^4.4.1", "recharts": "2.15.4", "sonner": "^2.0.7", + "tailwind-merge": "^3.4.0", + "tw-animate-css": "^1.4.0", "vaul": "^1.1.2", "zod": "^4.3.5", }, @@ -1578,6 +1581,8 @@ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + "tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="], + "tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="], "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], @@ -1602,6 +1607,8 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], diff --git a/package.json b/package.json index 5dd7c26..a9e68c2 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@tabler/icons-react": "^3.36.1", "@tanstack/react-table": "^8.21.3", "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", "embla-carousel-react": "^8.6.0", @@ -62,6 +63,8 @@ "react-resizable-panels": "^4.4.1", "recharts": "2.15.4", "sonner": "^2.0.7", + "tailwind-merge": "^3.4.0", + "tw-animate-css": "^1.4.0", "vaul": "^1.1.2", "zod": "^4.3.5" }, diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..d084cca --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +}