qcast-front/CLAUDE.md
sangwook yoo 26b1e31d74 docs: CLAUDE.md 최신 git 추적 현황 반영
- AGENTS.md alias 한 줄 추가 (Codex 등 타 에이전트 호환)
- .agents/skills 섹션 신설 — Vercel·Next.js 룰북 95개 위치/트리거 안내
- graphify-out 이 gitignore 된 로컬 캐시임 + 빈 상태 부트스트랩 방법 명시

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:16:36 +09:00

10 KiB

CLAUDE.md

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

루트 AGENTS.md@CLAUDE.md 한 줄짜리 alias. Codex 등 다른 코딩 에이전트도 이 문서를 그대로 따른다.

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:

  1. 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.
  2. Placement surface (hooks/surface, components/floor-plan/modal/placementShape …): slope, placement/shape drawing, object placement, bulk delete.
  3. 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.mjs sets resolve.fallback = { fs: false } and externalizes canvas, utf-8-validate, bufferutil as commonjs. Adding a node-only dep usually means adding it to that externals list.
  • experimental.staleTimes are 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 serve needs ./certificates/key.pem and cert.pem (gitignored).

Conventions that are easy to violate

  • Prettier: single quote, no semicolons, tabWidth 2, printWidth 150, trailingComma all (.prettierrc). Run yarn lint before declaring done.
  • No raw alert() — always go through useSwal / useMessage + sweetalert2. See docs/메세지 처리 가이드.pdf.
  • Path alias — prefer @/... over relative ../../.. chains.
  • Logging — never console.log directly in shipped code. Use src/util/logger.js, which no-ops unless NEXT_PUBLIC_ENABLE_LOGGING=true. src/util/debugCapture.js POSTs to /api/debug for 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.*.local is 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.

.agents/ skill 문서

.agents/skills/{next-best-practices,vercel-react-best-practices}/** 에 Vercel·Next.js 모범사례 룰북이 들어 있음(총 95개 .md). Next/React 패턴 관련 결정을 내릴 때(렌더링 최적화, RSC 경계, 번들 분할, hydration 이슈, 서버/클라이언트 캐싱 등) 우선 참조.

  • Skill 진입점: 각 디렉토리의 SKILL.md 가 인덱스, 룰은 rules/ 하위 토픽별 파일.
  • 이 문서들은 git 추적 대상이므로 변경하면 PR 에 함께 올릴 것.

graphify

A persistent knowledge graph of src/ lives at graphify-out/ (built by /graphify src). Prefer it over grep for architectural questions.

graphify-out/로컬 캐시라 git 추적 대상이 아님(.gitignore). 새 클론·워크트리에서 비어 있으면 graphify update . 로 incremental 빌드, 아예 없으면 /graphify src 로 풀 빌드.

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 use graphify query "..." / graphify path "A" "B" / graphify explain "..." — these traverse EXTRACTED + INFERRED edges instead of scanning files.
  • If graphify-out/wiki/index.md exists, prefer it over raw file reads.
  • The PreToolUse hook in .claude/settings.json will remind you when you reach for grep / rg / find.

Keeping it fresh — auto-update is wired up

  1. In-session (you, Claude): after any batch of Edit / Write on files under src/, run graphify 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.
  2. At commit (automatic): a post-commit git hook (installed via graphify 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.
  3. 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 src from scratch) unless graph.json is missing or corrupt — graphify update . is strictly faster and preserves cached analysis.
  • Don't trust INFERRED edges blindly — the AST extractor marks JS import-derived calls edges as INFERRED. Verify with the actual source when the answer hinges on call semantics (see useMessage trace example).