Inspiration

Choosing dinner sounds easy until it is 8 p.m., you are tired, and a delivery app gives you hundreds of options. I kept opening menus, comparing dishes, closing the app, and starting again.

Most recommendation products respond to choice overload with another list. I wanted the opposite: one dish, with a clear explanation of why it survived.

What it does

OneDish uses your budget, dietary restrictions, current craving, recent meals, and optional daily context to make one decision.

It filters a versioned catalog of 90 demo dishes from ten fictional restaurants. Instead of hiding the process behind a loading animation, it shows the actual elimination record: what was removed, which constraints were applied, and why the final dish won.

Allergen exclusions are hard rules. They cannot be relaxed to improve a score. If the result feels wrong, "Pick another" records that correction and selects the next valid option.

The Taste Orbit turns meal history into an interactive preference map. The Privacy page shows where each type of data goes, what stays on the device, and what the user can delete.

How I built it

The frontend is a React and TypeScript PWA built with Vite. It stores preferences, meal history, and completed decisions locally in IndexedDB through Dexie. The default demo works without an API key and remains available offline after the first load.

The recommendation engine is deterministic. Given the same inputs and catalog version, it produces the same result and explanation.

OpenAI's Responses API has a deliberately narrow job. When enabled, it converts natural food language, such as "something warm, spicy, but not too heavy," into validated fields. It does not rank dishes, override allergy rules, or choose the winner.

The optional FastAPI backend uses Pydantic to validate requests. Foursquare can provide nearby place discovery in live mode, while OpenStreetMap supports the location experience. The public demo uses clearly labeled fictional restaurants and versioned menu data, so it does not pretend to know live inventory or delivery availability.

Challenges

The hardest decision was deciding what the AI should not control.

Letting a language model choose the final meal would have been easier, but the result would be difficult to reproduce and unsafe around strict dietary constraints. I separated interpretation from decision making: AI handles ambiguous language, while deterministic code owns exclusions, scoring, and the final selection.

The animations caused another round of work. The elimination sequence, Taste Orbit, and privacy map had to feel alive without turning into fake "AI thinking." The app now completes and stores the decision first. The animation only explains what already happened.

Mobile layout, bilingual content, smooth orbital motion, and readable privacy connections also took more iteration than I expected.

What I learned

A single recommendation requires more trust than a list. If an app gives users ten options, it can quietly include weak ones. If it gives one answer, every assumption becomes visible.

I also learned that AI is most useful here at the boundary between human language and structured software. It is good at understanding "comfort food, but lighter." Deterministic code is better at enforcing a peanut allergy every single time.

Finally, privacy explanations work better when they are part of the interface. Users should be able to see what leaves their device without reading a legal document.

What's next

I want to connect OneDish to live menu and ordering providers when reliable APIs are available. A mobile version could add optional health and sleep context, processed locally and enabled only with explicit permission.

The goal will stay the same: stop browsing and eat one good meal.

Built With

Share this project:

Updates