うまい — delicious.
A personal chef that runs on your own hardware. Ask for a dish, get a proper recipe, scale it to however many are eating, change it as many times as you like, and keep the version that you most like.
- Writes recipes from a dish name, a craving, or whatever is about to go off in the fridge.
- Scales everything as you change the number of people. Metric masses round
to something you can actually weigh; spoons and counts snap to real fractions
(
1 ⅔ tbsp, not1.667). Things that don't scale linearly — raising agents, frying oil, pasta water — are held fixed. - Takes changes. Spicier, lighter, quicker, or free text like "swap the cream for stock". Revisions carry the current recipe as context, so it rewrites rather than starting over.
- Remembers what you learned. Write a note after cooking ("too salty, half the pecorino") and it's fed back into the prompt on every future revision. Each save also logs a diff of what you changed, so an entry accumulates a written record of how it became your version of the dish.
- Keeps a pantry, either typed in or read from photos of your fridge. Recipes tick what you already have.
- Builds a shopping list of only the gaps, grouped by supermarket aisle, merging quantities across recipes.
- Estimates nutrition per serving, clearly labelled as an estimate.
- Cook mode — one step at a time, large type, per-step timers.
- Prints the cookbook as a properly typeset A4 PDF with a cover, contents and one recipe per page.
- Any modern browser
- Node.js 18+ — only to serve the folder
- Ollama for the offline mode (optional; there's an Anthropic API fallback)
git clone https://github.com/YOUR-USERNAME/umai.git
cd umai
npm startThen in a second terminal:
ollama pull qwen3:8b # the recipe writer, ~5 GB
ollama pull qwen2.5vl:7b # reads fridge photos, optional
ollama serve # skip on macOS/Windows, it already runsOpen http://localhost:8080, click the gear, and hit Test the connection.
| Model | RAM | Notes |
|---|---|---|
qwen3:8b |
8 GB | Default. Best structured-output reliability at this size. |
llama3.1:8b |
8 GB | Solid alternative. |
mistral-small3.1 |
16 GB+ | Noticeably better writing if you have the headroom. |
llama3.2:3b |
4 GB | Works, but wanders off the schema often. |
Vision is a separate model. qwen2.5vl:7b is the pick for 8 GB;
moondream is faster but much weaker.
Leave the field blank to turn photo recognition off and add pantry items by hand.
The UI is built around a 10–13" (I have an old ipad 10.3 inch) touch screen: 44 px touch targets, no hover-only affordances, 16 px form fields so iPadOS doesn't zoom on focus, safe-area padding around the home indicator, and a cook mode sized to be read from across a worktop.
Run the server on your computer with the LAN flag:
npm run lanIt prints an address e.g. http://192.168.1.42:8080.
Open that on the iPad, then Share → Add to Home Screen — it launches full-screen with no browser chrome.
If Ollama refuses the request, start it with:
OLLAMA_ORIGINS='*' ollama serveThere is no authentication in Umai. Keep it on a network you trust.
umai/
├── index.html markup only; every id here is wired in js/main.js
├── serve.js dependency-free static server (npm start)
│
├── css/
│ ├── tokens.css colour, type and spacing variables; both themes
│ ├── base.css element defaults, touch and iPad behaviour
│ ├── layout.css app shell and scroll regions
│ ├── components.css everything you can see
│ └── print.css this file *is* the PDF
│
└── js/
├── main.js entry point: wiring and boot
├── state.js the state object and shared constants
├── store.js persistence with three fallback tiers
├── bus.js tiny pub/sub, so views don't import each other
├── dom.js $, escaping, toast, icons
├── units.js quantity formatting and scaling
├── matching.js pantry ↔ ingredient matching
├── chef.js prompts, model transport, defensive JSON parsing
├── recipe-view.js the recipe card
├── pantry.js photo intake, vision, review-before-commit
├── cookbook.js saving, revision history, browsing
├── shopping.js the list and its exports
├── cook-mode.js step-by-step and timers
├── printout.js builds the printable cookbook
└── ui.js theme, panes, settings
With Ollama selected, every request goes to localhost and every byte of data
lives in your browser's localStorage.
Fridge photos are downscaled and encoded in the browser and sent only to your local model.
Switching to the Anthropic backend sends prompts — and photos — to Anthropic. The setting says so. so you can't go wrong :)
- Merge the shopping list across a whole week's meal plan
- Track what's actually running low rather than just what exists
- Import a recipe from a URL or a photo of a cookbook page
- Substitution suggestions driven by the pantry
MIT. See LICENSE.
