build note
A restaurant list gets better when its opinions have names
What changed when I stopped treating bobby.menu as a pile of saved places and started treating curation as a small, explicit data model.
The first useful version of bobby.menu could have been a spreadsheet. Name, address, cuisine, maybe a note. Put the rows on a map and the problem is solved.
Except the problem was not storing restaurants. It was preserving judgment.
When a friend asks where to eat, I do not mentally query an undifferentiated list. I remember that one place is an easy recommendation, another is a favorite I would send almost anyone to, and a third came from a source I trust but is still waiting for a visit. Those are different kinds of knowledge. Flattening them into “saved” throws away the part that makes a personal list useful.
So the small decision that shaped the whole product was to give those states names: Loved, Recommended, and On My Radar.
Definitions beat vibes
The names only help if they have boundaries.
Loved means I have eaten there multiple times and would send someone without hesitation. Recommended means I have been and think it deserves consideration. On My Radar means it has been pre-vetted through a trusted source, but I have not visited yet.
This prevents a green map pin from implying a review that never happened. It also gives the interface honest material to work with. A filter can show only places I have visited. A card can explain why a restaurant is present. A random-pick button can draw from the level of certainty appropriate to the question.
Once the model was explicit, other features became easier to reason about.
One restaurant, several useful views
The map answers “what is near this part of town?” A list answers “what names should I compare?” A named collection answers “what would you send a visitor?” An MCP client answers a conversational version: “Is there anything Korean on the list that is open now?”
Those could have become four separate products with four drifting datasets. Instead, they are views over the same curated records.
That choice is most visible in collections. A collection stores a title, a short explanation, an order, and references to restaurants. It does not copy restaurant details. If a phone number, note, or tier changes, the map, the shared collection, and the AI tool all see the same current record.
The MCP server follows the same rule. It exposes tools for searching, reading collection summaries, and picking from a filtered pool. The public tools are read-only. Curation actions require authentication. “Available to an AI” is not treated as a reason to erase the permission boundary that exists in the human interface.
Enrichment without surrender
Restaurant data invites automation. Google Places can provide hours, ratings, price levels, photos, and location details. That information is useful, especially when the alternative is retyping it.
It is also capable of matching the wrong branch, carrying a stale status, or presenting an aggregate rating as if it were my opinion.
The solution was not to reject outside data or to trust it completely. It was to give it a subordinate role. Third-party details enrich a restaurant record; curator-supplied names, notes, tiers, and branch choices remain authoritative. Adding a restaurant includes a confirmation step. Data audits look for identity mismatches rather than assuming a successful API response is a correct answer.
The same principle applies to visitor suggestions. A suggestion can point me toward a restaurant. Approval does not publish the visitor’s submission as my review; it creates a curator-owned entry.
The interface followed the model
As the list expanded beyond a single metro, the interface accumulated pressure. A fixed map was no longer enough. Search needed to understand branches. Filters needed visible counts. A full-screen list made browsing easier on phones, while a split map-and-list layout made sense on wide displays. Links needed to preserve the current restaurant, city, collection, and filters.
Most of that work was ordinary iteration: watch where the vocabulary bends, find the duplicated rule, and move the rule to a place every surface can share.
The visual system benefited from the same discipline. The three tier colors communicate meaning, so the brand accent cannot casually reuse one of them. The “Wine & Paper” palette gives the application warmth without confusing brand color with recommendation state.
What I would carry into another build
The lesson is not that every personal project needs a taxonomy. It is that a product becomes easier to extend when it can say what its opinions mean.
If the distinction matters in conversation, it probably deserves a name in the model. If several interfaces need it, it should not live as a sentence copied between components. If an automated source can disagree with a human judgment, the precedence should be explicit before the disagreement occurs.
bobby.menu works because it is not trying to know every restaurant. It is trying to preserve one person’s evolving reasons for keeping a restaurant in view—and to make those reasons useful in more than one place.
AI-use note: AI coding assistants contributed substantially to the project’s planning, implementation, tests, debugging, and documentation, and helped me outline this build note from the repository’s actual decisions. I remain responsible for the curation model, product choices, and published account.