# HowToCook User Guide

`HowToCook` (`程序员在家做饭方法指南`) is a community-curated, Mandarin-language
cookbook of home recipes maintained by Anduin Xue and contributors. The repository
ships hundreds of plain-text Markdown recipe files — one dish per file — together
with photographs, fundamentals tutorials, and a star-rated meal-planning tier
system. There is **no application to install** and no service to run: the corpus
itself is the product. You browse it directly on GitHub, on the official static
mirror at [cook.aiursoft.com](https://cook.aiursoft.com), or by cloning it for
offline reading.

This guide explains how to find recipes, how to use the structured corpus
programmatically, how to contribute a new dish that passes the project's
automated lint gates, and the conventions you need to interpret the files
correctly. For repository internals — directory architecture, the markdown lint
toolchain, the Docker build, and developer-facing improvement areas — see the
companion HowToCook Administrator & Developer Guide.

> [!NOTE]
> The recipe corpus is written in Simplified Chinese. This English-language
> guide explains how to navigate and contribute to the project; it does not
> translate the recipes themselves. Each example references the original Chinese
> file or directory name in backticks so you can locate it precisely on disk
> or on GitHub.

---

## 1. Quick Start

The fastest path to a working recipe is to open the repository's `dishes/` tree
on GitHub and drill into a category folder. Every dish is a self-contained
Markdown file with ingredients, equipment, step-by-step instructions, and at
least one finished-dish photograph. Nothing needs to be installed.

### 1.1 The 30-second tour

1. Open [github.com/Anduin2017/HowToCook](https://github.com/Anduin2017/HowToCook).
2. Click into the `dishes/` directory.
3. Pick a category — for example, `meat_dish/` (荤菜) or `vegetable_dish/` (素菜).
4. Click any `.md` file. GitHub renders the recipe with images inline.
5. Cook from the rendered page on your phone, tablet, or laptop.

You can also browse the rendered, paginated mirror at
[cook.aiursoft.com](https://cook.aiursoft.com), which is regenerated from the
same source files and adds search and a printable layout. The mirror is
maintained by the project under the same `Anduin2017/HowToCook` source.

> [!TIP]
> The fastest way to find a specific dish is GitHub's per-repo file finder.
> Press `t` on any repository page to focus the file-tree filter, then type
> a Pinyin or Chinese substring of the dish name (e.g., `gongbao` or `宫保`).
> GitHub matches paths case-insensitively across the whole tree.

### 1.2 What the corpus contains

| Resource | What it is | Where it lives |
|---|---|---|
| **Dish recipes** | One Markdown file per dish, optionally with images in a sibling folder | `dishes/<category>/<dish>.md` or `dishes/<category>/<dish>/<dish>.md` |
| **Fundamentals tutorials** | Cross-cutting lessons (frying, boiling, marinating) | `tips/learn/` |
| **Advanced techniques** | Sugar-color, oil-temperature, accompaniment skills | `tips/advanced/` |
| **Kitchen prep + safety** | Pantry stocking, food-safety, ingredient compatibility | `tips/` |
| **Star-difficulty system** | Curated dish-flight menus by skill level | `starsystem/` |
| **Recipe template** | Authoring template every new dish must follow | `dishes/template/示例菜/` |
| **Build/lint configuration** | Dependency manifests and lint rules | `package.json`, `requirements.txt`, `.textlintrc`, `.markdownlint.json` |

### 1.3 Prerequisites

You need exactly one of the following to read recipes: a web browser pointed at
GitHub, a web browser pointed at the cook.aiursoft.com mirror, or a local clone
with any Markdown viewer (VS Code, Typora, Obsidian, Marked, or `cat` plus a
brain). Cooking a dish itself naturally requires a kitchen and the listed
ingredients.

### 1.4 First recipe — try a 番茄炒鸡蛋 (tomato + scrambled egg)

The canonical "first dish" cited across most beginner stir-fry tutorials is
`dishes/vegetable_dish/西红柿炒鸡蛋.md` (stir-fried tomato with eggs). To open
it:

```bash
# In a browser, navigate to:
# https://github.com/Anduin2017/HowToCook/blob/master/dishes/vegetable_dish/西红柿炒鸡蛋.md
```

The file will render the ingredient list, equipment list, calculations
(per-serving portion math), preparation steps, and finishing notes. Every
recipe in the project follows the same template, so once you've read one you
can read them all.

> [!IMPORTANT]
> The repository deliberately encodes Chinese characters in file paths and
> directory names. When cloning on Windows or older filesystems, ensure your
> `git config core.quotePath false` is set so path display and `git status`
> work as expected with non-ASCII names.

### 1.5 What to do next

- Browse a category that matches what's in your fridge — see Section 4.
- Walk through a fundamentals tutorial in `tips/learn/` before tackling any dish.
- Pick a difficulty floor in `starsystem/` and stick to dishes at or below it.
- Contribute back: see Section 5 and the project's `CONTRIBUTING.md`.

---

## 2. Installation

`HowToCook` is a documentation repository, not a software package. There is no
binary, no CLI, and no service to run for end users. "Installation" here means
choosing how you want to read the corpus and, optionally, setting up the
contributor toolchain so you can lint your own recipe submissions before opening
a pull request.

### 2.1 The four supported reading paths

| Method | Best for | Cost |
|---|---|---|
| Read on GitHub | Casual browsing, sharing links, mobile reading | Free, no setup |
| Read the `cook.aiursoft.com` mirror | Searchable, paginated, printable layout | Free, no setup |
| `git clone` for offline use | Cooking without internet, local search, archiving | Disk space + git |
| Build the static site locally | Self-hosting the rendered cookbook | Python + Node toolchain |

> [!TIP]
> For day-to-day cooking, the recommended path is **read on GitHub** from
> your phone. You do not need to clone, install Node, or run any tooling.

### 2.2 Clone for offline reading

```bash
git clone https://github.com/Anduin2017/HowToCook.git
cd HowToCook
```

```text
Cloning into 'HowToCook'...
remote: Enumerating objects: ...
Receiving objects: 100% (...), done.
Resolving deltas: 100% (...), done.
```

After cloning, every recipe is a Markdown file you can open with any editor.
Images live alongside the recipe in a sibling folder; relative image paths
work without any rewriting.

> [!NOTE]
> The repository contains many image files (JPEG, PNG, WebP, JPEG variants).
> A full clone is several hundred megabytes. Use `git clone --depth 1` if you
> only need the current state and want to skip history.

### 2.3 Set up the contributor toolchain (only for PR authors)

If you intend to submit a new recipe or a fix, you need Node.js and the
project's lint stack. The lint toolchain is what every pull request runs in
CI; getting a clean local pass before pushing avoids review back-and-forth.

```bash
# In the repository root
npm install
```

```text
added N packages, and audited N+1 packages in Ms
found 0 vulnerabilities
```

This installs the four direct lint dependencies declared in `package.json`:

| Package | Pinned version | Role |
|---|---|---|
| `textlint` | `^12.1.0` | Prose linter that runs across the whole repo |
| `textlint-rule-ja-space-between-half-and-full-width` | `^2.2.0` | Enforces spacing between Latin and CJK characters |
| `textlint-rule-zh-half-and-full-width-bracket` | `^1.1.0` | Normalises bracket widths in Chinese text |
| `markdownlint-cli` | `0.41.0` | Structural Markdown linter (headings, lists) |
| `glob` (devDependency) | `^7.2.0` | Used by the manual lint script |

> [!IMPORTANT]
> The contributor toolchain requires Node.js. Use a recent LTS release
> (Node 18 or newer is safe) so that `npm install` resolves the modern
> `markdownlint-cli` and `textlint` versions cleanly.

### 2.4 Build the static cookbook site (optional)

The repository also ships a Python-based static site stack — declared in
`requirements.txt` — used to render the printable, searchable mirror.

```bash
pip install -r requirements.txt
```

```text
Successfully installed mkdocs-material mkdocs-same-dir mkdocs-minify-plugin mkdocs-with-pdf weasyprint
```

The Python stack consists of:

- `mkdocs-material` — Material-themed static site generator
- `mkdocs-same-dir` — keeps `mkdocs.yml` and content roots colocated
- `mkdocs-minify-plugin` — minifies generated HTML
- `mkdocs-with-pdf` — adds a printable PDF target alongside the HTML site
- `weasyprint` — the PDF rendering engine consumed by `mkdocs-with-pdf`

The Admin Guide covers the site-build workflow, the corresponding `Dockerfile`,
and the deployment topology for the public mirror.

### 2.5 Verify your setup

```bash
node -v && npm -v
```

```text
v20.x.x
10.x.x
```

```bash
# (Optional) Run all linters to confirm the toolchain is wired up
npm run lint
```

```text
Lint finished. All passed.
```

> [!WARNING]
> Running `npm run lint` against an untouched clone of `master` should pass.
> If it fails on files you did not edit, your locale or text-encoding settings
> may be mangling Chinese characters during checkout — set `core.quotePath`
> and `core.autocrlf` to `false` and re-clone before debugging further.

---

## 3. Configuration

There is no user-facing runtime configuration. The corpus is plain Markdown,
read either on GitHub or as static files. The only configurable surface is the
contributor toolchain, and it has just three pieces of state:

### 3.1 Lint rule overrides

`markdownlint` is intentionally relaxed for the recipe-writing style this
project favours. The full list of disabled rules lives in `.markdownlint.json`:

```json
{
    "MD036": false,
    "MD024": false,
    "MD004": false,
    "MD029": false,
    "MD013": false,
    "MD007": false
}
```

| Rule | Disabled because |
|---|---|
| `MD036` | Recipes use bold-text "headings" (e.g., **食材**) inline |
| `MD024` | The same sub-heading (e.g., 步骤) appears in many sibling recipes |
| `MD004` | Mixed bullet styles are tolerated in step lists |
| `MD029` | Numbered steps don't always restart from 1 |
| `MD013` | No fixed line-length budget — long instruction lines are fine |
| `MD007` | Indented sub-bullets are allowed at any depth |

If you fork the repository for your own kitchen, override these in your fork's
`.markdownlint.json`; you do not need a personal config.

### 3.2 Prose-lint rules

`textlint` is configured via `.textlintrc` to enforce two house-style rules
that keep Chinese-Latin mixing readable:

- Half-width vs. full-width spacing between Chinese and Latin characters.
- Half-width vs. full-width bracket usage in Chinese sentences.

> [!NOTE]
> Both rules are auto-fixable with `npm run textlint`, which runs `textlint . --fix`.
> Running this before opening a pull request will silently fix most spacing
> issues that would otherwise fail CI.

### 3.3 Build scripts

`package.json` defines the only commands you will ever invoke. They are listed
in full in Section 4.4. There are no environment variables to set, no `.env`
file, and no `config/` directory. **The repository is config-free for readers.**

For the deeper toolchain — the Python static-site stack, the Docker build, the
GitHub Actions wiring — see the Admin Guide's Configuration Reference.

---

## 4. Core Usage

The repository is organised so that any path in the tree gives you a useful
landing page. The four roots you will use most are `dishes/`, `tips/`,
`starsystem/`, and the root-level fundamentals files. This section walks
through each one.

### 4.1 The `dishes/` directory — every recipe in the project

The recipe corpus is partitioned into 11 categories. Each category folder
contains a flat list of single-file recipes plus, for dishes that ship
photographs, a same-named subdirectory holding the `.md` and the images.

| Category folder | English label | What's inside |
|---|---|---|
| `dishes/aquatic/` | Aquatic / seafood (`水产`) | Fish, prawn, shrimp, crab, sea-cucumber dishes |
| `dishes/breakfast/` | Breakfast (`早餐`) | Eggs, congee, toast, sandwiches, oatmeal, pan-fried items |
| `dishes/condiment/` | Sauces & condiments (`酱料`) | Sauces, oils, sugar-syrups, dipping mixes |
| `dishes/dessert/` | Dessert (`甜品`) | Cakes, ice creams, jellies, scones, tiramisu |
| `dishes/drink/` | Drinks (`饮品`) | Cocktails, teas, milk drinks, juices, special blends |
| `dishes/meat_dish/` | Meat dishes (`荤菜`) | Pork, beef, lamb, chicken, duck, frog stir-fries and braises |
| `dishes/semi-finished/` | Semi-finished products (`半成品加工`) | Air-fryer dishes, frozen-product handling |
| `dishes/soup/` | Soups & congee (`汤与粥`) | Broths, congees, herbal soups |
| `dishes/staple/` | Staples (`主食`) | Rice, noodles, dumplings, breads, flatbreads, fried rice |
| `dishes/vegetable_dish/` | Vegetable dishes (`素菜`) | Tofu, leafy greens, mushrooms, eggplant, vegetable stir-fries |
| `dishes/template/` | Recipe template (`示例菜`) | The reference template every new recipe copies |

> [!NOTE]
> The categories above are the eleven top-level folders that exist under
> `dishes/` in the repository. A handful of dishes legitimately straddle
> categories (for example, `dishes/meat_dish/麻婆豆腐.md` — Mapo tofu — is filed
> under meat because it traditionally contains minced meat). When in doubt,
> use the file-finder shortcut from Section 1 rather than guessing the category.

#### 4.1.1 How a single recipe is laid out

Every recipe — without exception — follows the template at
`dishes/template/示例菜/示例菜.md`. The headings are stable across the corpus
so tools and humans both know where to look.

| Section | Chinese heading | Content |
|---|---|---|
| Frontmatter | (file title) | The dish's name, repeated as the H1 |
| Necessary materials | `必要原料` | Equipment and pantry items the cook supplies themselves |
| Calculations | `计算` | Per-serving portion math, multipliers, scaling notes |
| Operations / steps | `操作` | Numbered preparation and cooking steps |
| Additional notes | `附加内容` | Variations, substitutions, troubleshooting, finishing tips |

> [!TIP]
> Because every recipe uses the same headings, you can grep across the entire
> tree for an ingredient. For example, `grep -r "花椒" dishes/` lists every
> dish in the corpus that calls for Sichuan peppercorn. This is how the
> cook.aiursoft.com mirror builds its ingredient index.

### 4.2 The `tips/` directory — fundamentals before recipes

`tips/` holds standalone tutorials that aren't tied to any one dish. New cooks
should read these first; experienced cooks dip in for refreshers.

| Path | Topic | What it teaches |
|---|---|---|
| `tips/厨房准备.md` | Kitchen prep | Pantry, equipment, knife and pan inventory |
| `tips/如何选择现在吃什么.md` | Decision aid | Heuristics for "what should I cook tonight?" |
| `tips/食材相克与禁忌.md` | Food-safety taboos | Ingredient combinations to avoid |
| `tips/learn/学习炒与煎.md` | Stir-frying & pan-frying | The two most common heat techniques |
| `tips/learn/学习煮.md` | Boiling | Plain-water cooking for noodles, vegetables, eggs |
| `tips/learn/学习蒸.md` | Steaming | Steamed dishes, mantou, dumplings |
| `tips/learn/学习焯水.md` | Blanching | Pre-cook blanching for meats and vegetables |
| `tips/learn/学习腌.md` | Marinating | Marinade ratios, timing, tenderising agents |
| `tips/learn/学习凉拌.md` | Cold-tossed dishes | Dressing-driven cold preparations |
| `tips/learn/去腥.md` | De-fishing / de-gaming | Removing odour from fish, mutton, offal |
| `tips/learn/食品安全.md` | Food safety | Storage, raw-meat handling, cross-contamination |
| `tips/learn/微波炉.md` | Microwave use | Microwave-only cooking patterns |
| `tips/learn/空气炸锅.md` | Air-fryer use | Time and temperature heuristics for an air fryer |
| `tips/learn/高压力锅.md` | Pressure cooker | Pressure-cooker-only cooking patterns |
| `tips/advanced/油温判断技巧.md` | Oil-temperature judging | Visual cues for 三成热, 五成热, etc. |
| `tips/advanced/糖色的炒制.md` | Sugar-colour technique | Caramelising sugar for braises (红烧) |
| `tips/advanced/辅料技巧.md` | Aromatics technique | Use of ginger, scallions, garlic, peppercorns |
| `tips/advanced/高级专业术语.md` | Advanced terminology | Restaurant-kitchen jargon for hobbyist cooks |

> [!IMPORTANT]
> Several recipes assume you have read the relevant `tips/learn/` file. For
> example, dishes that say "焯水后..." (after blanching...) presume you know
> the blanching procedure from `tips/learn/学习焯水.md`. If a recipe step
> seems too terse, check the corresponding fundamentals file.

### 4.3 The `starsystem/` directory — meal-planning by difficulty

`starsystem/` contains nine curated, increasing-difficulty menus from
`0Star.md` (literally cannot fail) to `8Star.md` (full multi-course feasts).
Each star file lists dishes in the corpus that match that difficulty floor.

| File | Difficulty band | Use it when |
|---|---|---|
| `starsystem/0Star.md` | Zero-difficulty (raw or microwave-only) | First time in your own kitchen |
| `starsystem/1Star.md` | One-pot or single-pan, low-skill | First week of self-cooking |
| `starsystem/2Star.md` | Basic stir-fry and boiling | Comfortable with one burner |
| `starsystem/3Star.md` | Multi-step, multi-ingredient | Standard dinner-party fare |
| `starsystem/4Star.md` | Technique-driven (braises, marinades) | Confident weeknight cook |
| `starsystem/5Star.md` | Multi-day or fermented preparations | Hobbyist territory |
| `starsystem/7Star.md` | Restaurant-grade single dishes | Showpiece weekend project |
| `starsystem/8Star.md` | Full menus / banquets | Hosting an event |

> [!NOTE]
> The star system jumps from `5Star.md` to `7Star.md`. There is no
> `6Star.md` file in the repository; this is a gap the maintainers have
> not yet filled — not a missing file in your clone.

### 4.4 The five build/lint scripts

`package.json` exposes five npm scripts. These are the **only** commands the
project supports; nothing else is invoked by CI or by the cook.aiursoft.com
build.

| Script | Command behind it | When you run it |
|---|---|---|
| `npm run build` | `node ./.github/readme-generate.js` | Regenerates the README's auto-generated index from `dishes/` |
| `npm run manuallint` | `node .github/manual_lint.js` | Runs the project-specific custom checks (template fields, image presence) |
| `npm run textlint` | `textlint . --fix` | Auto-fixes prose spacing and bracket-width issues |
| `npm run markdownlint` | `markdownlint ./dishes ./tips` | Structural Markdown checks against `dishes/` and `tips/` |
| `npm run lint` | All four above, in order | The full gate every pull request must pass |

> [!TIP]
> Always run `npm run lint` locally before pushing. The composite script
> echoes `Lint finished. All passed.` on success — that exact line is how
> the project signals a clean run.

### 4.5 Reading recipes programmatically

Because every recipe is plain Markdown with stable section headings, the
corpus is straightforward to consume from a script. Two common patterns:

```bash
# Count recipes per category
for dir in dishes/*/; do
    count=$(find "$dir" -name "*.md" | wc -l)
    echo "$dir: $count"
done
```

```python
# Walk the dishes/ tree and parse each recipe's H1 + 必要原料 section
import pathlib, re

for md in pathlib.Path("dishes").rglob("*.md"):
    text = md.read_text(encoding="utf-8")
    title_match = re.search(r"^#\s+(.+)", text, re.MULTILINE)
    materials_match = re.search(
        r"##\s*必要原料\s*\n(.+?)(?=\n##|\Z)", text, re.DOTALL
    )
    if title_match and materials_match:
        print(md, title_match.group(1).strip())
```

The Admin Guide's Integration Points section enumerates every consumer that
relies on this stable structure (the cook.aiursoft.com mirror, downstream
recipe apps mentioned in community issues, and the project's own
`readme-generate.js` script).

---

## 5. Common Tasks

This section is a cookbook of short workflows for the most common things you
will want to do with the repository, organised by goal.

### 5.1 Find a dish by category

**Goal:** find every fish dish in the corpus.

1. Open `dishes/aquatic/` either on GitHub or in your local clone.
2. Read the directory listing — each `.md` is one dish; each subdirectory is
   one dish with photos.
3. Click any entry to view the recipe.

### 5.2 Find a dish by ingredient

**Goal:** find every recipe that uses Sichuan peppercorn (`花椒`).

```bash
# In a local clone
grep -rln "花椒" dishes/ tips/
```

```text
dishes/meat_dish/水煮牛肉/水煮牛肉.md
dishes/meat_dish/麻婆豆腐/麻婆豆腐.md
dishes/meat_dish/宫保鸡丁/宫保鸡丁.md
... (and so on)
```

> [!TIP]
> On GitHub, use the repo's code search at
> `github.com/Anduin2017/HowToCook/search?q=花椒&type=code`. It's slower than
> grep but works in a browser.

### 5.3 Pick a dish for tonight by difficulty

**Goal:** you have 30 minutes and one pan; what should you make?

1. Open `starsystem/1Star.md` or `starsystem/2Star.md`.
2. Pick a dish from the listing.
3. Click through to the recipe and read the `计算` section to confirm
   portion sizes match what you have on hand.

### 5.4 Contribute a new recipe

**Goal:** add `蒜蓉茄子` (garlic-mashed eggplant) to `dishes/vegetable_dish/`.

1. **Fork** the repository on GitHub and clone your fork locally.
2. **Copy the template:**
   ```bash
   cp -r dishes/template/示例菜 dishes/vegetable_dish/蒜蓉茄子
   mv dishes/vegetable_dish/蒜蓉茄子/示例菜.md \
      dishes/vegetable_dish/蒜蓉茄子/蒜蓉茄子.md
   ```
3. **Fill in the template:** keep the same headings (`必要原料`, `计算`, `操作`,
   `附加内容`), replace the placeholder content, and add at least one finished-dish
   photograph next to the `.md` file.
4. **Run the linters:**
   ```bash
   npm install
   npm run lint
   ```
5. **Commit and push** to your fork, then open a pull request against the
   upstream `master` branch.

> [!IMPORTANT]
> The project's `manual_lint.js` script enforces structure that `markdownlint`
> cannot. It checks that the recipe contains the required headings, that
> images referenced in the Markdown actually exist on disk, and that the
> file lives in a category that exists. Skipping `npm run manuallint` means
> CI will reject the PR — always run `npm run lint` (which calls all four
> linters) before opening a PR.

### 5.5 Translate a recipe (or fix one)

**Goal:** clarify or correct a step in an existing recipe.

1. Find the recipe file under `dishes/`.
2. Edit the Markdown directly — preserve the canonical headings.
3. If you are adding clarifying notes, put them under `附加内容` so the
   primary steps under `操作` stay terse.
4. Run `npm run textlint` to auto-fix any half/full-width spacing the edit
   introduced.
5. Open a PR with a focused commit message in either Chinese or English.

> [!WARNING]
> Do **not** translate the entire recipe to English in-place. The project
> is intentionally Chinese-language; full translations belong in a separate
> downstream fork. Bug-fix style corrections to the Chinese source — fixing
> a typo, clarifying an ambiguous step — are always welcome.

### 5.6 Build the static site for offline reading

**Goal:** produce a self-contained HTML cookbook you can host on a NAS or
read on a flight.

```bash
git clone https://github.com/Anduin2017/HowToCook.git
cd HowToCook
pip install -r requirements.txt
mkdocs build
```

The output lands in `site/` — a static HTML tree you can serve from any
HTTP server or open directly with `file://` URLs. The Admin Guide's
Deployment section covers the Dockerfile-based build the public mirror uses.

### 5.7 Use the corpus as data for a recipe app

**Goal:** parse `dishes/` into structured records for downstream tooling.

The structure is regular enough that a 30-line parser produces a clean
dataset. Issue [#60](https://github.com/Anduin2017/HowToCook/issues/60)
discusses adopting YAML frontmatter to make this even cleaner; it is not
yet implemented. Until then, parse the H1 + the four section headings and
ignore everything else. The example Python parser in Section 4.5 is a
working starting point.

> [!NOTE]
> Issue [#1755](https://github.com/Anduin2017/HowToCook/issues/1755) tracks
> a community proposal for a NanoBananaPro-based image-rich preview and PDF
> exporter built on top of the corpus. Treat the source files as the stable
> API; rendered tools come and go.

---

## 6. Troubleshooting

The recipe corpus is plain Markdown so there is little that can go wrong at
read-time. Most issues are toolchain or rendering problems on the contributor
side. Each entry below uses the project's standard cause/solution format.

### Error: `npm run lint` fails on files I did not edit

**Cause:** Your local clone is decoding non-ASCII filenames or contents
incorrectly. Common causes are Windows `core.autocrlf=true`, a missing
`core.quotePath false`, or a terminal that is not UTF-8.

**Solution:**

1. Set git's path-quoting and line-ending defaults:
   ```bash
   git config --global core.quotePath false
   git config --global core.autocrlf false
   ```
2. Re-clone the repository so files are checked out cleanly with UTF-8 byte
   sequences intact.
3. Confirm your terminal uses UTF-8 (`chcp 65001` on Windows cmd; default
   on Linux/macOS).

**Prevention:** Set the two git options globally before cloning any
repository that contains non-ASCII paths.

### Error: `manual_lint.js` reports a missing image

**Cause:** Your recipe references an image filename that doesn't exist next
to the `.md`, or the case in the path doesn't match the case on disk.

**Solution:**

1. Confirm the image file actually exists:
   ```bash
   ls dishes/vegetable_dish/蒜蓉茄子/
   ```
2. Verify case. The repository runs CI on Linux, where `Foo.JPG` and
   `foo.jpg` are different files even if your Mac or Windows machine treats
   them as the same.
3. Update either the Markdown reference or the file on disk so they match
   exactly, then re-run `npm run manuallint`.

**Prevention:** Always reference images with the exact filename and
extension (`.jpg`, `.jpeg`, `.png`, `.webp`) that you committed.

### Error: `textlint` fails on bracket or spacing rules

**Cause:** Your edit introduced a Chinese character directly adjacent to a
Latin character without the required space, or used a half-width bracket
where the project expects full-width.

**Solution:** Run the auto-fixer; it handles 95% of cases:

```bash
npm run textlint
```

```text
All issues fixed.
```

Then re-run `npm run lint` to confirm the file now passes.

**Prevention:** Configure your editor to run `textlint --fix` on save for
files in this repository.

### Error: Images don't render on GitHub

**Cause:** Either the relative path is wrong, or the image file was committed
with `git lfs` while the consumer doesn't have LFS configured.

**Solution:**

1. Verify the path: GitHub renders images that live next to the `.md` file
   when referenced as `![](image.jpg)`.
2. Check `.gitattributes` for any LFS rules — this repository does not use
   LFS for recipe images, so any LFS pointer is a mistake.
3. If you accidentally committed a pointer file, run:
   ```bash
   git lfs uninstall
   git rm <pointer>
   git add <real-image>
   git commit
   ```

**Prevention:** Commit images directly. The repository's image footprint is
fine in plain git.

### Error: I can't find a dish I'm sure exists

**Cause:** You're searching by Pinyin or English in a tree where files are
named in Chinese characters.

**Solution:**

- On GitHub, use the file-finder (press `t`) and type any Chinese substring.
- Locally, use a Unicode-aware search:
  ```bash
  find dishes/ -name "*红烧肉*"
  ```
- Or rely on GitHub's code-search:
  `github.com/Anduin2017/HowToCook/search?q=红烧肉&type=code`.

**Prevention:** Bookmark the GitHub category pages (`dishes/meat_dish/`,
`dishes/vegetable_dish/`, etc.) for quick browsing instead of filename guessing.

### Error: A recipe contradicts a fundamentals tutorial

**Cause:** Recipes are contributed by many community members; occasionally a
step diverges from the canonical technique in `tips/learn/` or `tips/advanced/`.
Multiple open issues track this — see [#1757](https://github.com/Anduin2017/HowToCook/issues/1757)
(戚风蛋糕 issues) and [#1759](https://github.com/Anduin2017/HowToCook/issues/1759)
(southern-style 红烧肉 issues) for active examples.

**Solution:** Trust the fundamentals tutorial as the baseline. If a recipe's
step looks wrong relative to `tips/learn/`, it probably is — open an issue or
a PR with the correction.

**Prevention:** When in doubt, follow `tips/learn/` over a single recipe.

### Error: A recipe step skips an ingredient

**Cause:** Same as above — recipes occasionally have ingredients in the
materials list that never appear in the steps. Issue
[#1750](https://github.com/Anduin2017/HowToCook/issues/1750) documented one
such case in `酸辣土豆丝.md` (scallions in the ingredient list, not used in
steps); it is now closed but the pattern recurs in other dishes.

**Solution:** Cross-check `必要原料` against `操作`. If an ingredient is
listed but not used, file an issue or open a PR adding the missing step.

**Prevention:** This is a structural quality gap the project tracks via its
issue tracker; community contributions catching these gaps are welcome.

### Error: Print layout is unreadable on paper

**Cause:** GitHub-rendered Markdown isn't optimised for print, and Chinese
characters can fall below readable size when a long recipe is shrunk to fit
one page.

**Solution:**

1. Use the `cook.aiursoft.com` mirror, which has a print-friendly stylesheet.
2. Or build the static site locally with `mkdocs-with-pdf` (Section 2.4) and
   print from the generated PDF instead of from GitHub.

**Prevention:** Don't print from GitHub directly. Issue
[#1762](https://github.com/Anduin2017/HowToCook/issues/1762) tracks the same
complaint; the static-site mirror is the supported path.

> [!WARNING]
> When troubleshooting an open community issue, check the issue thread before
> assuming the bug is yours. Many of the surface-level recipe quirks are
> tracked at the project level — see issue
> [#1765](https://github.com/Anduin2017/HowToCook/issues/1765) for the
> overall recipe-quality discussion.

---

## 7. FAQ

**Q: Do I need to install anything to read recipes?**

No. The repository is plain Markdown rendered by GitHub. Open
[github.com/Anduin2017/HowToCook](https://github.com/Anduin2017/HowToCook),
click into `dishes/`, pick a category, click a recipe. That's the entire flow.

**Q: Is there an English version of the recipes?**

No. The corpus is intentionally Chinese-language; this is documented in the
project description (`程序员在家做饭方法指南` — "programmer's guide about
how to cook at home (Chinese)") and in `package.json`'s description field.
Community translation forks exist, but the upstream project does not host
translations.

**Q: Where is the published web version?**

[cook.aiursoft.com](https://cook.aiursoft.com), declared as the project
homepage in `package.json`. It is generated from the same source files.

**Q: What license is the recipe corpus released under?**

The Unlicense (declared in `package.json`'s `license` field and the
repository's `LICENSE` file). You can copy, modify, and redistribute the
content freely. Photographs may have been contributed by individual authors
under the same waiver.

**Q: How are recipes added?**

Fork the repo, copy `dishes/template/示例菜/` into the appropriate category
under `dishes/`, fill in the standard headings, run `npm run lint`, and open
a pull request. Section 5.4 has the full workflow.

**Q: Why are some category folders nearly empty at the top level?**

For example, `dishes/dessert/` shows almost no top-level `.md` files — most
of its dishes are in subdirectories. Recipes that include photographs live
in a same-named subfolder containing both the `.md` and the images. Recipes
without photographs sit as flat files at the category root. Both styles are
supported; the recipe is whichever `.md` exists.

**Q: What's the difference between `dishes/` and `tips/`?**

`dishes/` holds specific recipes — one dish per file. `tips/` holds
cross-cutting tutorials and reference material that many recipes depend on.
You should read `tips/learn/学习炒与煎.md` before tackling any stir-fry
recipe in `dishes/meat_dish/` or `dishes/vegetable_dish/`.

**Q: What's the `starsystem/` directory for?**

Curated, difficulty-graded menus. If you don't want to browse the whole
`dishes/` tree, pick a star file matching your skill level and pick from its
list. See Section 4.3.

**Q: Can I use these recipes in my own app or website?**

Yes — the Unlicense permits any reuse. Several community projects already
parse the corpus; see issue [#1755](https://github.com/Anduin2017/HowToCook/issues/1755)
for one such proposal. If you build something on top, consider crediting the
upstream project and contributing fixes back.

**Q: Is there a YAML/JSON version of the recipes?**

Not yet. Issue [#60](https://github.com/Anduin2017/HowToCook/issues/60)
tracks adopting YAML frontmatter for machine-readability; for now, parse
the Markdown directly. The headings are stable enough that a regex parser
works reliably (see Section 4.5).

**Q: How do I report a wrong recipe?**

Open an issue at
[github.com/Anduin2017/HowToCook/issues](https://github.com/Anduin2017/HowToCook/issues).
Tag your issue with `bug` and link the specific recipe file. Existing
examples of recipe-quality issues include
[#1757](https://github.com/Anduin2017/HowToCook/issues/1757) and
[#1759](https://github.com/Anduin2017/HowToCook/issues/1759).

**Q: Why does CI fail with a non-English error message?**

The lint stack is configured for Chinese-language content; some `textlint`
rules emit Chinese diagnostic text. The fix is the same regardless: run
`npm run textlint` (with `--fix`) and `npm run lint` to confirm the auto-fix
worked.

**Q: Are there any platform-specific cooking tools assumed?**

Several recipes assume an air fryer (`空气炸锅`), microwave (`微波炉`), or
pressure cooker (`高压力锅`). The fundamentals files in `tips/learn/`
explicitly cover each of these and are linked from the recipes that depend
on them. There is no assumption that you own restaurant equipment.

**Q: How do I keep my fork in sync with upstream?**

Standard git workflow:

```bash
git remote add upstream https://github.com/Anduin2017/HowToCook.git
git fetch upstream
git checkout master
git merge upstream/master
```

The repository uses a single `master` branch, so syncing is straightforward.

**Q: Where do I learn about contribution etiquette?**

Read `CONTRIBUTING.md` and `CODE_OF_CONDUCT.md` in the repository root before
opening a pull request. Both files set expectations on tone, scope, and
review cycle.

---

_Generated April 2026 from Anduin2017/HowToCook at 1857c9e. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
