11 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What this is
Two independent apps in one repo:
- Frontend (repo root) — a Vite + React 19 + TypeScript marketing/content site for "اندیشکده فولاد آینده" (a steel-industry think tank). Persian-first, RTL, bilingual (fa/en). Deploys as a static build via Docker to Hugging Face Spaces on port 7860.
- Admin panel (
panel/) — a standalone Node/Express + SQLite app with its ownpackage.jsonandnode_modules. Manages content the site is meant to publish. The frontend does NOT consume the panel yet — every section renders hardcoded mock data. Wiring them is a deliberate future step.
These two have no shared build or dependency tree. Treat panel/ as a separate project.
Commands
Frontend (run from repo root):
npm run dev # Vite dev server (HMR)
npm run build # tsc -b && vite build (type-checks then bundles)
npm run lint # eslint .
npm run preview # serve the production build
npx tsc -b --noEmit # type-check only — the fast inner loop; use after every edit
There is no test framework configured. "Verifying" a change means npx tsc -b --noEmit (must be clean) and looking at the running dev server.
Admin panel (run from panel/):
cd panel
npm install # first time only
npm run seed # create the admin user from .env (ADMIN_USERNAME/PASSWORD)
npm start # node server.js → http://localhost:3001
npm run dev # node --watch server.js
npm rebuild better-sqlite3 # REQUIRED if Node's ABI changed — native addon, fails to load otherwise
Critical build gotcha
panel/ lives inside the frontend's project root, so Vite's dependency scanner reads panel/package.json. If that file (or anything Vite scans) has unresolved git merge-conflict markers (<<<<<<<), npm run dev/build fails with a cryptic JSONError ... expected value at line 1. Keep panel/package.json valid JSON.
Frontend architecture
- Routing:
src/app/router.tsx(createBrowserRouter).RootLayout(src/app/layout/RootLayout.tsx) wraps every page withHeader,Footer, and the smooth-scroll engine. Pages live insrc/pages/<Name>/<Name>.tsx; the homepage composes section components fromsrc/pages/Home/sections/. - Language:
useLang()fromsrc/context/LangContextreturns{ lang: 'fa'|'en', toggle }. Components hold inline{ fa: {...}, en: {...} }objects and index bylang. RTL is driven bydir={lang==='fa'?'rtl':'ltr'}near the page root; many flex containers forcedirection:'ltr'locally to stop RTL from reversing their child order, then set inner text back tortl. - Smooth scroll:
RootLayoutruns Lenis synced to the GSAP ticker (the joinspread.app recipe) — one shared RAF clock so scroll-driven animations don't stutter. It is desktop-only: on touch/coarse pointers it hands off to native momentum (avoids the iOS double-smoothing lag). Do not re-add CSSscroll-behavior: smooth— it fights Lenis. - Hero (
src/pages/Home/sections/HeroSection.tsx): a GSAPScrollTriggerscrub timeline pinned over a200vhsection (de-zoom + satellite scatter). This is GSAP, not framer-motion. - Styling: mostly inline
styleobjects, with Tailwind utility classes for responsive overrides (max-md:,max-lg:) and a few!importantoverrides. Global CSS variables insrc/index.css(--ink,--paper,--red,--color-orange, etc.). Brand colors are gold#CD9E53and navy#032340— these are also hardcoded asconst GOLD/const NAVYin many section files, so a rebrand is a repo-wide find-and-replace, not just a CSS-var change. - Globe (
src/components/ui/globe.tsx): three-globe mounted in react-three-fiber via<primitive>(NOT viaextend/JSX-element augmentation — that augmentation poisons global JSX types and breaks unrelated components likeReact.ElementTypeicons). Country polygons load at runtime frompublic/globe-countries.geojson(bundled, public-domain Natural Earth). - Calendar (
src/components/ui/EventCalendar.tsx): a native Jalali (Persian) month grid built withIntl.DateTimeFormat('en-US-u-ca-persian', …)— no date library. It walks GregorianDates and reads their Persian parts to lay out the grid. - Content layer:
src/content/*.tsand inline arrays hold all section data. These are mock/seed data and are explicitly intended to be replaced byfetchcalls to the panel API later (see "Wiring", below). Keep new editorial data in this shape so the swap stays mechanical.
Admin panel architecture (panel/)
- Stack: Express 4 +
better-sqlite3(single filepanel/data.db),bcryptjs+jsonwebtoken(HTTP-only cookie namedsession),multeruploads topanel/uploads/. Admin UI is a vanilla-JS SPA inpanel/public/(app.js, no build step). - Schema:
panel/db.js(users,articles,risk_signals,prices) plus row→object mappers.articlesis a flexible universal content model discriminated bycategory/type. - API (
panel/server.js): public reads (GET /api/articles,/api/risks,/api/prices) + auth-gated writes via theauthRequiredmiddleware. CRUD for articles, risk signals, and users;/api/uploads;/api/contact. CORS is gated by theALLOWED_ORIGINSenv var. - Prices are scraped from tgju.org by
panel/scraper.json a 120s interval when the server runs. - Config:
panel/.env(copy from.env.example) —JWT_SECRET,ADMIN_*,PORT(3001),ALLOWED_ORIGINS, mail creds.
Wiring the panel to the site (not done yet)
When asked to make published content appear on the site: add a frontend fetch client (e.g. src/lib/api.ts reading import.meta.env.VITE_API_URL), replace a section's src/content/* import with a hook that calls GET /api/articles?category=<section>, and keep the static file as the loading fallback. Do it one section at a time. The articles table's category column is the per-section discriminator. Recommended schema additions before going live: a status (draft/published) column, and an events resource for the calendar.
RTK (Rust Token Killer) - Token-Optimized Commands
Golden Rule
Always prefix commands with rtk. If RTK has a dedicated filter, it uses it. If not, it passes through unchanged. This means RTK is always safe to use.
Important: Even in command chains with &&, use rtk:
# ❌ Wrong
git add . && git commit -m "msg" && git push
# ✅ Correct
rtk git add . && rtk git commit -m "msg" && rtk git push
RTK Commands by Workflow
Build & Compile (80-90% savings)
rtk cargo build # Cargo build output
rtk cargo check # Cargo check output
rtk cargo clippy # Clippy warnings grouped by file (80%)
rtk tsc # TypeScript errors grouped by file/code (83%)
rtk lint # ESLint/Biome violations grouped (84%)
rtk prettier --check # Files needing format only (70%)
rtk next build # Next.js build with route metrics (87%)
Test (60-99% savings)
rtk cargo test # Cargo test failures only (90%)
rtk go test # Go test failures only (90%)
rtk jest # Jest failures only (99.5%)
rtk vitest # Vitest failures only (99.5%)
rtk playwright test # Playwright failures only (94%)
rtk pytest # Python test failures only (90%)
rtk rake test # Ruby test failures only (90%)
rtk rspec # RSpec test failures only (60%)
rtk test <cmd> # Generic test wrapper - failures only
Git (59-80% savings)
rtk git status # Compact status
rtk git log # Compact log (works with all git flags)
rtk git diff # Compact diff (80%)
rtk git show # Compact show (80%)
rtk git add # Ultra-compact confirmations (59%)
rtk git commit # Ultra-compact confirmations (59%)
rtk git push # Ultra-compact confirmations
rtk git pull # Ultra-compact confirmations
rtk git branch # Compact branch list
rtk git fetch # Compact fetch
rtk git stash # Compact stash
rtk git worktree # Compact worktree
Note: Git passthrough works for ALL subcommands, even those not explicitly listed.
GitHub (26-87% savings)
rtk gh pr view <num> # Compact PR view (87%)
rtk gh pr checks # Compact PR checks (79%)
rtk gh run list # Compact workflow runs (82%)
rtk gh issue list # Compact issue list (80%)
rtk gh api # Compact API responses (26%)
JavaScript/TypeScript Tooling (70-90% savings)
rtk pnpm list # Compact dependency tree (70%)
rtk pnpm outdated # Compact outdated packages (80%)
rtk pnpm install # Compact install output (90%)
rtk npm run <script> # Compact npm script output
rtk npx <cmd> # Compact npx command output
rtk prisma # Prisma without ASCII art (88%)
Files & Search (60-75% savings)
rtk ls <path> # Tree format, compact (65%)
rtk read <file> # Code reading with filtering (60%)
rtk grep <pattern> # Search grouped by file (75%). Format flags (-c, -l, -L, -o, -Z) run raw.
rtk find <pattern> # Find grouped by directory (70%)
Analysis & Debug (70-90% savings)
rtk err <cmd> # Filter errors only from any command
rtk log <file> # Deduplicated logs with counts
rtk json <file> # JSON structure without values
rtk deps # Dependency overview
rtk env # Environment variables compact
rtk summary <cmd> # Smart summary of command output
rtk diff # Ultra-compact diffs
Infrastructure (85% savings)
rtk docker ps # Compact container list
rtk docker images # Compact image list
rtk docker logs <c> # Deduplicated logs
rtk kubectl get # Compact resource list
rtk kubectl logs # Deduplicated pod logs
Network (65-70% savings)
rtk curl <url> # Compact HTTP responses (70%)
rtk wget <url> # Compact download output (65%)
Meta Commands
rtk gain # View token savings statistics
rtk gain --history # View command history with savings
rtk discover # Analyze Claude Code sessions for missed RTK usage
rtk proxy <cmd> # Run command without filtering (for debugging)
rtk init # Add RTK instructions to CLAUDE.md
rtk init --global # Add RTK to ~/.claude/CLAUDE.md
Token Savings Overview
| Category | Commands | Typical Savings |
|---|---|---|
| Tests | vitest, playwright, cargo test | 90-99% |
| Build | next, tsc, lint, prettier | 70-87% |
| Git | status, log, diff, add, commit | 59-80% |
| GitHub | gh pr, gh run, gh issue | 26-87% |
| Package Managers | pnpm, npm, npx | 70-90% |
| Files | ls, read, grep, find | 60-75% |
| Infrastructure | docker, kubectl | 85% |
| Network | curl, wget | 65-70% |
Overall average: 60-90% token reduction on common development operations.