Files
toor 7920c0bba2 chore: 删除设计原型目录,锁定 Node 24
移除 prototype/ 下 cook-desktop 与 cook-redesign 两套静态原型稿(37 个文件),
它们是设计过程产物,不是产品源码;eslint 的对应 ignore 规则一并撤掉。

engines.node 收紧为 >=22.0.0 <25:Node 26 下 ESLint worker 会原生崩溃
(退出码 0xC0000005),实测 Node 24 下连续 6 次 lint 全部正常。
2026-10-21 12:43:16 +08:00

91 lines
5.0 KiB
Markdown

# 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
```bash
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 build` copies `apps/web/dist` to the root `dist/` 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 with `pnpm 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) and `pantry.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:
```bash
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 by `pnpm feedback:pull`)
## Node/Package Manager
- Node.js: 24 (pinned via `.nvmrc`; Node 26 crashes ESLint natively)
- pnpm: 11.21.0 (enforced via `packageManager` field)