个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证"What Should I Cook?" Randomizer with a Twist! Not a recipe app, a constraint-based one. The user inputs what's in their fridge and picks a vibe (e.g. "lazy," "impress someone," "5 minutes"), and the app narrows down suggestions.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Tell it what's in your fridge, pick a vibe, and let it spin up a meal you can actually make tonight.
Type the ingredients you have, separated by commas, set the vibe dial (Lazy, Simple, Comfort, Hearty, Healthy, Fun, Classic, Fancy, Elegant, Impressive) and hit Spin. The reel runs through real recipes from TheMealDB that use your ingredients and lands on the one that best fits both your pantry and your mood. Open it and you get everything you need to cook from your phone: ingredients you can tick off as they go in the pan, numbered steps in large type, a rough cook-time estimate, and Save, Print and Close within reach of your thumb. It won't show you the same recipe twice until you clear your history, and "Surprise me" skips the typing altogether. Saved recipes and your recent picks stay on your device; there is no account.
Ryan wrote the design brief and the spec, built the v1 app by hand, and ran a code review of it. He then directed AI agents (Claude Code) through a phased rebuild in TypeScript, with tests written at every phase and four rounds of manual QA on a real phone between passes. The process is all in the repo: the brief, the three design directions he chose between and the resulting design system in design/, the decision log and manual test rounds in docs/, every v1 bug and the commit that fixed it in BUGS_RESOLVED.md, and the commit history itself. The core logic modules are being rewritten by hand as ongoing ownership work, with the test suite as the contract.
strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes)src/
main.ts wires storage, API and UI together; the spin and surprise flows
types.ts Recipe, ScoredRecipe, VibeKey, VibeProfile, MealDB shapes
api/mealdb.ts fetch client (15s timeout), interleave, dedup, cap
api/loadRecipes.ts candidates → recipes via the session cache
api/surprise.ts one random recipe, re-rolled past ones you've seen
core/normalize.ts MealDB meal → Recipe
core/vibes.ts the ten vibe profiles and the vibe score
core/scoring.ts ingredient overlap, blend, seen exclusion, tiebreak, pick
core/identity.ts recipe identity by id, with a name fallback for old saves
core/cookTime.ts instruction text → under 30 / 30–60 / over 60 min estimate
core/measurements.ts measure string → quantity and unit (groundwork for servings)
storage/ localStorage and sessionStorage wrappers; every read guarded and validated
ui/ dial, reel, result card, recipe sheet, saved, recent, print
styles/tokens.css every colour, size, radius and motion value
styles/*.css one file per component
tests/ one file per module
Everything under core/ and the merge logic in api/ is pure: no DOM, no storage, no network. Nothing in src/ uses innerHTML. The design system behind styles/ is documented in design/SYSTEM.md.
Storage keys are unchanged from v1, so existing favourites carry over:
| Key | Holds | Cap |
|---|---|---|
pantryRouletteFavorites | saved recipes | 50 |
pantryRouletteSeenRecipes | ids of recipes already shown | 20 |
pantryRouletteRecentlyViewed | the last picks, newest first | 5 |
pantryRouletteLookup:<id> (session) | one cached recipe per TheMealDB id | cleared with the tab |
npm install
npm run dev # http://localhost:5173
npm test # vitest run
npm run typecheck # tsc --noEmit
npm run build # typecheck, then vite build → dist/
npm run preview # serve dist/ on http://localhost:4173
The manual test rounds, with expected results, are in docs/MANUAL_TEST.md. What changed in each release is in CHANGELOG.md and what comes next is in ROADMAP.md.
Source is public for reference and portfolio purposes. All rights reserved; see LICENSE.
Built by Ryan Christian. Questions and feedback: [email protected].