gitignore 의 *.md / .claude/ 차단을 풀어 다음 파일을 git 으로 추적. - /CLAUDE.md, /AGENTS.md (루트 에이전트 가이드) - .agents/**/*.md (skills 문서 95개) - .claude/settings.json (Claude Code 프로젝트 설정) .claude/worktrees/ 는 git worktree 메타이므로 신규 ignore 라인으로 제외. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9.2 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
The repository README.md is unusually thorough. Treat it as authoritative for stack, directory layout, env vars, routes, and troubleshooting — this file only highlights what's non-obvious or easy to get wrong.
Project at a glance
Q.CAST Front — a Next.js 14 (App Router) frontend for solar-panel layout planning, quoting, and management, targeted at the Japanese (Q.CELLS) market with ja/ko i18n. JavaScript + TypeScript (allowJs, strict: false). Path alias @/* → ./src/*.
Common commands
All scripts use env-cmd to inject the right .env.<mode> file. There is no test runner wired into package.json.
yarn dev # local dev (.env.localhost)
yarn dev:local-api # local dev pinned to http://localhost:8080 API
yarn local:dev # .env.local.dev mode
yarn build # production build (.env.production)
yarn build:dev # development build (.env.development)
yarn start:cluster1 # next start -p 5000 (.env.production) — used by PM2
yarn start:dev # next start -p 5010 (.env.development)
yarn serve # custom HTTP:3000 + HTTPS:3001 (needs ./certificates/*.pem)
yarn lint # next lint
PM2 entrypoints (ecosystem.config.js, prd1/prd2/dev/dev.local.ecosystem.config.js) wrap startscript*.js, which child_process.exec the yarn scripts above.
Architecture — the parts that span many files
Mode routing through src/config/
Runtime config is selected at module load by src/config/config.export.js, which switches on process.env.NEXT_PUBLIC_RUN_MODE between config.local.js, config.local.dev.js, config.development.js, config.production.js. Never read env values directly in feature code — import from here so mode switches stay in one place.
Session / auth gate
iron-session cookies are the session source of truth (src/lib/session.js, src/lib/authActions.js). src/app/layout.js checks the session at the root and redirects every non-login route to /login when missing. SESSION_SECRET must be set (≥32 bytes). The session also carries storeLvl (1차/2차 판매점) which drives quote-render branches, builder number, and group ID. Q-Order / Q-Musubi support autoLogin flows via NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL / NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL.
src/middleware.js injects x-pathname into request headers so the root layout can branch on the active route.
Floor Plan canvas (the heart of the app)
src/app/floor-plan/** is built on Fabric.js 5.5.2. The model has three layered concerns:
- Roof covering (
hooks/roofcover,components/floor-plan/modal/roofShape/outerlinesetting/eavesGable…): outer wall lines, auto/manual roof-shape detection, guides, eaves & kerabs, flow up/down, outer-line edit & offset, roof-face assignment. - Placement surface (
hooks/surface,components/floor-plan/modal/placementShape…): slope, placement/shape drawing, object placement, bulk delete. - Module / circuit (
hooks/module,components/floor-plan/modal/panelBatch…): basic settings, circuit & rack config, orientation.
A modal under components/floor-plan/modal/<feature> pairs with a hook under hooks/<roofcover|surface|module|object|option|...>. Keep that pairing when adding new tools.
Fabric extensions live in src/components/fabric/QLine.js, QPolygon.js and src/util/fabric-extensions.js. Prototype patches must be defined in one place and loaded together — patching elsewhere causes hard-to-debug shape issues.
Context menus are unified through useContextMenu + the contextMenu Recoil atom. The per-target menu inventory is documented in docs/Canvas Status.md — match that list when changing menu wiring.
Plan persistence (serialize/restore) is in src/lib/canvas.js and src/util/canvas-util.js. Recent commits (a5e794b3, 2aef32e0) added a three-layer guard (entry / cache / save) and SizeSetting input guards against 0-area apertures/shadows/dormers — when touching plan load/save or size inputs, do not weaken or remove these guards without understanding the failure mode (InvalidStateError from corrupted plans).
State — Recoil, split by domain
Atoms live under src/store/ and are split by domain (canvasAtom, roofAtom, estimateAtom, modalAtom, menuAtom, settingAtom, …). When adding state, find the existing domain atom rather than introducing a new global. RecoilWrapper.js mounts the root; QcastProvider.js composes the rest of the global providers (session, global data, global loading) for the App Router root layout.
Build / runtime quirks
next.config.mjssetsresolve.fallback = { fs: false }and externalizescanvas,utf-8-validate,bufferutilas commonjs. Adding a node-only dep usually means adding it to that externals list.experimental.staleTimesare all 0 on purpose — App Router cache is disabled so plan/estimate pages always refetch. Don't re-enable without checking the plan-stale failure mode.reactStrictMode: false. Don't assume double-render semantics.- HTTPS local dev via
yarn serveneeds./certificates/key.pemandcert.pem(gitignored).
Conventions that are easy to violate
- Prettier: single quote, no semicolons, tabWidth 2, printWidth 150, trailingComma all (
.prettierrc). Runyarn lintbefore declaring done. - No raw
alert()— always go throughuseSwal/useMessage+sweetalert2. Seedocs/메세지 처리 가이드.pdf. - Path alias — prefer
@/...over relative../../..chains. - Logging — never
console.logdirectly in shipped code. Usesrc/util/logger.js, which no-ops unlessNEXT_PUBLIC_ENABLE_LOGGING=true.src/util/debugCapture.jsPOSTs to/api/debugfor server-side capture (also gated by the same flag). - Commit messages follow
.gitmessage.txt:
Recent commits use a slightly tighter[일감번호] : [제목] [작업내용] :[2204] <subject> — <detail>form; mirror neighboring commits on the branch. .env.*can contain real secrets — never paste contents into PR bodies, issues, or chat..env.*.localis gitignored for machine-local overrides.
Reference docs in docs/
Canvas Status.md— canvas feature status and right-click menu inventory per target type.Qcast coding convention.pdf,Qcast development guilde.pdf— full conventions / dev guide.메세지 처리 가이드.pdf— modal & alert message rules.git commit message Convention.pdf— commit format.Nextjs 14 컴포넌트에 대해서….pdf— App Router server/client component notes.dictionary.txt— domain vocabulary (roof / panel terms in JP/KR).
Always Do
- All answers and reasoning processes must be written in Korean.
- Once the task is complete, use a sub-agent to perform lint checks, type checks, and build checks.
- When performing a lint check, ensure that any errors are resolved before proceeding, and make an effort to resolve any warnings that arise.
- When committing, write the prefix in English, while the rest of the title and content in Korean.
- Upon task completion, update the CLAUDE.md and README.md documents if necessary.
- When working, commit in meaningful units that can be explained in a single sentence.
graphify
A persistent knowledge graph of src/ lives at graphify-out/ (built by /graphify src). Prefer it over grep for architectural questions.
When to consult it
- Before answering "how does X relate to Y", "what depends on Z", or any cross-module question, read
graphify-out/GRAPH_REPORT.md(god nodes, surprising connections) and usegraphify query "..."/graphify path "A" "B"/graphify explain "..."— these traverse EXTRACTED + INFERRED edges instead of scanning files. - If
graphify-out/wiki/index.mdexists, prefer it over raw file reads. - The PreToolUse hook in
.claude/settings.jsonwill remind you when you reach forgrep/rg/find.
Keeping it fresh — auto-update is wired up
- In-session (you, Claude): after any batch of
Edit/Writeon files undersrc/, rungraphify update .to incrementally re-extract changed files. AST-only, no LLM cost, takes a few seconds. Do this before answering follow-up architectural questions on the changed code, otherwise the graph is stale. - At commit (automatic): a
post-commitgit hook (installed viagraphify hook install, lives in the main repo's.git/hooks/, shared across worktrees) re-runs AST extraction on changed code files after every commit. Combined with the "commit in meaningful units" rule above, the graph stays current with minimal effort. - Doc / image changes: the post-commit hook ignores non-code files. Run
graphify update .manually after touching docs that affect the graph (rare — this project's graph is code-only).
Don't
- Don't rebuild the whole graph (
/graphify srcfrom scratch) unlessgraph.jsonis missing or corrupt —graphify update .is strictly faster and preserves cached analysis. - Don't trust
INFERREDedges blindly — the AST extractor marks JS import-derivedcallsedges as INFERRED. Verify with the actual source when the answer hinges on call semantics (see useMessage trace example).