This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
CodeJeet is a Next.js 16 app for browsing company-wise LeetCode DSA questions and system design chapters. It uses shadcn/ui components and reads question data from CSV files at build time. Browsing is fully public and largely static. It is deployed to Cloudflare Workers via OpenNext (@opennextjs/cloudflare), so it has a real server runtime — Edge middleware (middleware.ts), route handlers, and Worker bindings (Cloudflare D1). It is NOT output: "export". Optional Clerk (GitHub) auth lets users persist solved-question progress to a D1 database; signed-out users keep working off localStorage exactly as before.
- Dev:
pnpm dev(uses Turbopack) - Build:
pnpm build(runs prebuild script thennext build, outputs toout/) - Prebuild:
pnpm run prebuild(generatespublic/data/questions.jsonfrom CSVs) - Lint:
pnpm lint/pnpm lint:fix - Format:
pnpm format(Prettier) /pnpm format:check - Pre-commit hook: Husky runs lint-staged (Prettier auto-format) on commit
All question data lives in data/*.csv (one CSV per company, ~200+ files). At build time, scripts/build-data.ts uses lib/data.ts to parse all CSVs and writes public/data/questions.json containing { questions, companies, topics }. This JSON file is served statically and fetched by the dashboard client.
The dashboard fetches the static /data/questions.json directly (generated by the tsx scripts/build-data.ts prebuild step). The one dynamic route is app/api/progress/route.ts (force-dynamic): GET/POST per-user solved-question progress, backed by Cloudflare D1. It reads the user via auth() (@clerk/nextjs/server) and the DB via getCloudflareContext().env.DB (@opennextjs/cloudflare). Signed-out GET returns { progress: {} } (200, never a redirect).
The dashboard client (app/dashboard/page.client.tsx) caches the JSON response in localStorage keyed by CACHE_VERSION from lib/cache-version.ts. When updating the data or JSON shape, bump CACHE_VERSION to bust client caches.
app/dashboard/page.tsx is a statically rendered server component (force-static) that renders page.client.tsx. The client component fetches /data/questions.json and renders LeetCodeDashboard.
Markdown-based content in public/system-design/ with numbered folders (e.g., 01. Scaling/README.md). Each markdown file uses gray-matter frontmatter with slug, optional video (YouTube), and podcast (Spotify) fields. Pages are statically generated (force-static, dynamicParams: false).
All browsing is public — sign-in is only needed to save progress. middleware.ts runs a bare clerkMiddleware() that gates nothing; the API route does its own auth() check. Keep it as middleware.ts, NOT proxy.ts: Next 16's proxy.ts convention is hardwired to the Node.js runtime, but OpenNext for Cloudflare only supports Edge middleware (opennextjs-cloudflare build exits with "Node.js middleware is not currently supported" otherwise). middleware.ts runs on Edge — the deprecation warning during build is expected and harmless. app/layout.tsx wraps the app in ClerkProvider (dark theme); Navbar shows SignInButton/UserButton. GitHub is the only enabled social connection. Pinned to Clerk v6 (@clerk/nextjs@^6): v7 dropped SignedIn/SignedOut/appearance.baseTheme.
When signed in, the dashboard syncs the localStorage leetcode-checked-items map to D1 via utils/progressUtils.ts; marking is keyed by slug (question.ID), so a question marked once shows solved across all companies.
output is NOT export. Build the worker with bun run build:worker (opennextjs-cloudflare build) and deploy with bun run deploy (wrangler deploy), or bun run preview (wrangler dev) to test the worker locally. wrangler.jsonc declares the D1 binding DB (database codejeet-progress). D1 schema lives in migrations/; apply with wrangler d1 execute codejeet-progress --local|--remote --file=migrations/0000_init.sql.
Env vars. NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY is inlined at build time (in .env.local for next dev, and present at build for the worker). CLERK_SECRET_KEY is runtime-only: .dev.vars locally, and wrangler secret put CLERK_SECRET_KEY for production (never committed). Keep the secret stable across deploys. Cloudflare binding types are hand-written in cloudflare-env.d.ts — do NOT run wrangler types, it globally overrides DOM types (e.g. Response.json() → unknown) and breaks the client code.
- shadcn/ui (new-york style) with Radix primitives — components in
components/ui/ - Tailwind CSS v3 with oklch color tokens defined in
app/globals.css - Magic UI animation components in
components/magic-ui/ - Fonts: Plus Jakarta Sans (sans) + JetBrains Mono (mono)
- Dark theme default via
next-themes
@/* maps to project root (e.g., @/components, @/lib, @/utils, @/hooks).
- Package manager is pnpm (specified in
packageManagerfield) - Next.js output mode is
export(fully static) - Prettier config: double quotes, semicolons, 100 char width, es5 trailing commas
utils/utils.tshas general helpers (e.g.,capitalizeWords);lib/utils.tshas the shadcncn()merge utilitypublic/data/is gitignored — generated at build time from CSVs