Skip to content

Latest commit

 

History

History
70 lines (42 loc) · 5.64 KB

File metadata and controls

70 lines (42 loc) · 5.64 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

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.

Commands

  • Dev: pnpm dev (uses Turbopack)
  • Build: pnpm build (runs prebuild script then next build, outputs to out/)
  • Prebuild: pnpm run prebuild (generates public/data/questions.json from 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

Architecture

Data Layer — CSV-based, prebuild to static JSON

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.

API Routes

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).

Client-side Caching

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.

Dashboard (Server + Client split)

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.

System Design Pages

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).

Auth (optional, Clerk)

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.

Deployment (OpenNext → Cloudflare Workers)

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.

UI Stack

  • 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

Path Aliases

@/* maps to project root (e.g., @/components, @/lib, @/utils, @/hooks).

Key Conventions

  • Package manager is pnpm (specified in packageManager field)
  • Next.js output mode is export (fully static)
  • Prettier config: double quotes, semicolons, 100 char width, es5 trailing commas
  • utils/utils.ts has general helpers (e.g., capitalizeWords); lib/utils.ts has the shadcn cn() merge utility
  • public/data/ is gitignored — generated at build time from CSVs