For the team at KangaCook

Cook Mode for KangaCook: your 151 recipes, made cookable in English and 中文

A working concept built on KangaCook's public recipe data for the Software Engineer role. It adds the four things the job description lists and the site does not have yet: a parser for free-text Chinese quantities, a serving scaler with a metric/US toggle, a step-by-step cook mode with timers and screen wake lock, and a shopping list that merges several recipes. Served at /en and /zh with hreflang and full Recipe JSON-LD, on Next.js with the parser also shipped as a tested Python service. Not affiliated with KangaCook or Roulettech.

One-minute demo on a phone: scale a recipe, switch units, cook it step by step with a timer, and merge two recipes into one shopping list.
Open any recipe, change the servings, switch Metric/US, start cook mode, add two recipes to the shopping list. Phone first. Concept by Mayank Goel, not affiliated with KangaCook or Roulettech; recipes and photos belong to their authors on kangacook.com.
Open Cook Mode for KangaCook full screen

Free-text quantities are why there is no scaler yet

What I noticed

Ingredients are stored as one string per line: 150 公克 雞腿肉, 適量 鹽, 一個瓶蓋 米酒, and, because the create form forces a number, lines like 1 鹽少許 and 1 味醂(1/2 大匙). Some lines are simplified Chinese, some are English.

Why it matters

A scaler, a unit toggle and a shopping list all need a number, a unit and a name. Until the text is parsed, every one of those features is blocked, and the About page's one-click shopping list stays a promise.

The fix

A parser with one grammar for all of it: Arabic, Chinese and fractional numbers, ranges, placeholder 1s, parenthetical quantities, 30 unit aliases, and to-taste words that are never scaled. On the 1,041 real lines it reads 888 with a quantity, a known unit and an item, 148 as counts or to-taste, and leaves 5 verbatim and unscaled. The same rules exist in TypeScript for the app and in a FastAPI service with 1,124 tests, because KangaCook runs Django.

Nothing is dropped; unsure lines stay verbatim

parse("一個瓶蓋 米酒")  → { qty: 1, unit: "bottle-cap", item: "米酒", confidence: "high" }
parse("1 鹽少許")      → { kind: "to-taste", item: "鹽" }           // placeholder 1 dropped
parse("4-5 瓣 蒜頭")   → { qty: [4, 5], unit: "clove", item: "蒜頭" }
parse("義式香料")      → { kind: "unparsed", item: "義式香料", confidence: "low" }  // shown as written

Cooking happens on a phone with wet hands

What I noticed

Recipe pages show the steps as a list under the ingredients. There is no per-step view, the screen goes dark mid-step, and 煮 10 分鐘 is text, not a timer.

Why it matters

The step-by-step cook mode is the first feature in the job description, and it is the one a founder can judge in ten seconds on a phone.

The fix

One step per screen with its photo, swipe or arrow keys to move, the Screen Wake Lock API to keep the display on, and timers detected from the step text (10 分鐘, 5-8 分鐘, 20 minutes) that count down with a beep and vibration. The ingredient drawer shows amounts at the chosen scale.

English should be a URL, not a toggle

What I noticed

kangacook.com serves lang=zh-Hant on every page; the 中/EN switch is client-side, with no /en routes and no hreflang, so search engines never see the English. The recipe schema is good but misses inLanguage, ItemList and a working SearchAction, and the LCP image is a ~1 MB PNG straight from S3 with no cache header.

Why it matters

The posting describes an English relaunch for a Chinese-language site. Routing, hreflang, schema and image delivery are the plumbing that relaunch stands on.

The fix

Real /en and /zh routes, server-rendered, with hreflang and x-default; Recipe JSON-LD with inLanguage, mainEntityOfPage and step URLs, an ItemList on the listing, a SearchAction that resolves; covers and step photos converted once at build time to AVIF/WebP at three widths with srcset and immutable caching. English recipe text is machine-translated and labelled as such on every page. The audit page lists each fix found and a Lighthouse before/after on one recipe, measured, not quoted.