移除 prototype/ 下 cook-desktop 与 cook-redesign 两套静态原型稿(37 个文件), 它们是设计过程产物,不是产品源码;eslint 的对应 ignore 规则一并撤掉。 engines.node 收紧为 >=22.0.0 <25:Node 26 下 ESLint worker 会原生崩溃 (退出码 0xC0000005),实测 Node 24 下连续 6 次 lint 全部正常。
5.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Cook (食用手册) is a Chinese recipe web app for finding recipes based on available ingredients. Built with Nuxt 4 (Vue 3, CSR-only) and Ionic UI, shipped as a Web app only (browser + YunLeFun container). The UI and content are in Chinese.
Common Commands
pnpm install # Install deps (auto-runs nuxt prepare via postinstall)
pnpm convert # Convert CSV recipe data → JSON (required before first run)
pnpm validate # Validate recipe.csv (ids, ingredient/tool dictionary, values, video ids)
pnpm feedback:pull # Pull in-app feedback + search signals from CloudBase (needs .env)
pnpm eval:search # Evaluate recommendation ranking against real search signals
pnpm fixtures # Regenerate shared recommendation fixtures (after data, alias or ranking changes)
pnpm dev # Dev server on http://localhost:3333
pnpm lint # ESLint check (uses @antfu/eslint-config flat config)
pnpm lint --fix # Auto-fix lint issues
pnpm typecheck # TypeScript type checking via vue-tsc
pnpm test # Run Vitest tests
pnpm test -- --run # Run tests once without watch
pnpm build # Full production build (convert + nuxt generate)
Architecture
Data Pipeline
CSV source files (packages/data/recipe.csv, packages/data/incompatible-foods.csv) → pnpm convert (via packages/cook CLI) → JSON files (packages/data/recipe.json, packages/data/incompatible-foods.json) → consumed at runtime. Data rules, validation and the feedback loop are in docs/dev/data.md; every recipe has a permanent id column (favorites, feedback and search signals key on it): never change or reuse an id; new recipes take max id + 1.
Project decisions are recorded in docs/decisions/ — read the relevant one before changing direction, and add a new record for significant decisions.
Monorepo Structure (pnpm workspaces)
Layout follows docs/decisions/0004-web-only.md.
- apps/web — Nuxt app (main application). Root scripts (
pnpm dev,pnpm build,pnpm typecheck) proxy to it;pnpm buildcopiesapps/web/distto the rootdist/that deploy targets read - packages/data — Recipe CSV sources and the JSON generated from them (imported in the web app as
@cook/data/*), the food dictionary (food.json), pantry defaults (pantry.json), ingredient aliases (aliases.json), and recommendation fixtures (fixtures/recommend.json, regenerate withpnpm fixtures) - packages/cook — Types, recommendation/search logic, and the CLI (
convert,search) - docs — VitePress documentation site
- scripts — Build/utility scripts
- Root — Workspace tooling, tests (
test/),cloudfunctions/
App Source (apps/web/app/)
- pages/ — Nuxt file-based routing; main interface uses Ionic tabs (
tabs.vue) - components/ — Organized by feature:
recipe/,tags/,layouts/,common/ - composables/store/ — Pinia stores:
app,recipe,favorite,history,user - composables/ — Shared logic:
db.ts(IndexedDB via Dexie),dark.ts,recipe.ts,incompatible-foods.ts - data/ — typed wrappers over
packages/data/food.json(food/tool dictionary) andpantry.json - types/ — TypeScript type definitions
- styles/ — SCSS including CSS variables (
css-vars.scss)
Key Patterns
- CSR-only: SSR is disabled in
apps/web/nuxt.config.ts; app is statically generated - Client storage: Dexie (IndexedDB) for favorites, history, user preferences — enables offline support
- Styling: UnoCSS with Wind preset (Tailwind-compatible), attributify mode, and custom shortcuts (
tag,btn) - Dark mode: Class-based via
@nuxtjs/color-mode(classSuffix: '') - Icons: Iconify with multiple packs (carbon, mdi, twemoji); food tool icons dynamically safelisted in
apps/web/uno.config.ts
Prerendered Routes
/, /random, /help, /user, /404, /settings are prerendered during static generation.
Testing
Tests live in test/ directory. Vitest uses jsdom environment with setup in test/setup.ts. Config in vitest.config.ts. Run a single test file:
pnpm test -- test/recipe.test.ts
Code Style
Uses @antfu/eslint-config (flat config) with UnoCSS and formatters enabled. Pre-commit hook runs lint-staged via simple-git-hooks. Ignored paths include packages/data/**/*.json, dist/.
Environment Variables
See .env.example:
NUXT_PUBLIC_CLARITY_PROJECT_ID/NUXT_PUBLIC_CLARITY_DOMAINS— Microsoft Clarity statistics (leave the project ID empty to disable)COOK_FEEDBACK_URL/COOK_FEEDBACK_TOKEN— feedback export endpoint and its token (used bypnpm feedback:pull)
Node/Package Manager
- Node.js: 24 (pinned via
.nvmrc; Node 26 crashes ESLint natively) - pnpm: 11.21.0 (enforced via
packageManagerfield)