個人 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].