Inlander Restaurant Week Picker
A web app for browsing, marking favorites, and randomly selecting a restaurant during Inlander Restaurant Week.
Overview
The app presents all participating IRW restaurants in a two-panel layout — a scrollable list on the left and a detail view on the right — making it easy to browse full multi-course menus before deciding where to eat.
Each couple gets their own set of interest checkboxes ("His Picks" / "Her Picks") that persist in localStorage across sessions. Once both people have marked their favorites, the built-in randomizer picks a winner from the mutually-agreed pool.
Features
- Browse & search — filter restaurants by name, price tier ($25 / $35 / $45), neighborhood/area, and cuisine type
- Full menu detail — click any restaurant to view its complete multi-course IRW menu with descriptions
- Dual interest tracking — independently mark restaurants as interesting for two people; selections are saved automatically in the browser
- Interest filter — narrow the list to His Picks, Her Picks, Both Picked, or Either Picked
- Random picker — "Pick for Us!" draws a random winner from the currently filtered pool, with an option to re-roll
- Course browse — dedicated First Course, Second Course, and Third Course buttons open a modal listing every dish for that course across all restaurants; click any dish to jump straight to that restaurant's detail view
- Clear Filters — one-click button to reset all search and filter fields back to their defaults
- Reset Selected — clears all saved picks (with a confirmation prompt) so you can start fresh
- Mobile-friendly — responsive single-panel layout on small screens; the list and detail views swap in place, with a Back button to return to the list
- No dependencies — pure HTML, CSS, and vanilla JavaScript; requires a local web server (see Usage)
Usage
- Serve the folder from a web server and open
restaurant-picker.htmlin a browser. (The app fetches2026-restaurants.jsonat runtime, so it cannot be opened directly as a localfile://URL — a server is required. A simple option is the VS Code Live Server extension, ornpx serve .in the project folder.) - Browse the restaurant list or use the toolbar filters to narrow choices.
- Use the First Course, Second Course, or Third Course buttons to browse all dishes for a given course and jump to any restaurant that interests you.
- Check the You and Wife boxes on any restaurant you're each interested in.
- Click Pick for Us! to randomly select from the restaurants you both want.
- Re-roll as needed, or click View Details to jump to the winner's menu.
- Use Clear Filters to reset the toolbar, or Reset Selected to clear all picks and start over.
Tech Stack
| Layer | Details |
|---|---|
| Structure | HTML5 |
| Styling | Inline CSS (dark red/gold IRW theme) |
| Logic | Vanilla JavaScript |
| Persistence | Browser localStorage |
| Dependencies | None |
File Structure
restaurant-picker.html # App shell — HTML, CSS, and JS logic
2026-restaurants.json # Restaurant data for the 2026 event (loaded at runtime via fetch)
LICENSE
README.md
Each year, create a new YYYY-restaurants.json and update the filename in the fetch() call near the bottom of restaurant-picker.html.
Data Entry Guide
Each year's restaurant data is stored as a JSON file (YYYY-restaurants.json) loaded by restaurant-picker.html at runtime. The source data comes from the IRW restaurant listing pages. This section covers the data schema and common pitfalls to avoid when entering or updating restaurant records.
Restaurant Object Schema
{
"name": "Restaurant Name",
"slug": "restaurantname",
"price": 35,
"areas": ["Downtown"],
"cuisine": "Italian",
"url": "https://inlanderrestaurantweek.com/project/restaurantname/",
"menu": {
"hours": "Menu served Tue-Sat, 5 pm-close",
"phone": "(509) 555-1234",
"courses": {
"First Course": [
{ "name": "Dish Name", "desc": "Ingredients and description GF" }
],
"Second Course": [
{ "name": "Dish Name", "desc": "Ingredients and description" }
],
"Third Course": [
{ "name": "Dish Name", "desc": "Ingredients and description V+" }
]
}
}
}
Field notes:
slug— lowercase, no spaces or special characters; used as an internal identifierprice— must be25,35, or45(the three IRW price tiers)areas— array; a restaurant can belong to more than one area (e.g.["Downtown", "Coeur d'Alene"])phone— use empty string""if not listed- Each course is an array — restaurants sometimes offer a choice of two or more dishes per course; add one object per option
Valid Area Values
Airway Heights Athol Coeur d'Alene Downtown
Hayden Liberty Lake North Spokane Post Falls
South Spokane Spokane Valley West Spokane Worley
ID (Coeur d'Alene-area catch-all)
Valid Cuisine Values
American Asian Barbecue Bistro Eclectic European French
Fusion Gastropub German Indian Irish Italian Latin
Mediterranean Mexican Middle Eastern Northwest Pizza
Seafood Southern Steakhouse Thai
New cuisine types can be added, but check existing values first to keep filters consistent.
Dietary Tags
Dietary tags go at the end of the desc field, separated by a space. Multiple tags are space-separated.
| Tag | Meaning |
|---|---|
GF |
Gluten Free |
GFA |
Gluten Free Available (on request or with substitution) |
V |
Vegetarian |
V+ |
Vegan |
DF |
Dairy Free |
Examples:
"desc": "Mixed greens, candied walnuts, goat cheese, balsamic vinaigrette GF V"
"desc": "House pasta with roasted vegetables – sub GF pasta available GFA V"
"desc": "Coconut curry with tofu and seasonal vegetables V+ GF DF"
Tags that are inline notes within a description (e.g. – sub GF crust for additional charge) are fine to leave mid-sentence; only the primary applicable tags belong at the end.
Common Data Entry Pitfall: Dietary Tag as Dish Name
The IRW website displays a dietary icon before the dish name. When copying menu data, it is easy to accidentally paste the dietary tag as the name field and run the dish name directly into the start of desc with no separator.
Wrong (broken):
{ "name": "GFA", "desc": "Margherita PizzaSan Marzano Tomato Sauce. Fresh Mozzarella." }
Correct:
{ "name": "Margherita Pizza", "desc": "San Marzano Tomato Sauce. Fresh Mozzarella. GFA" }
Signs that an entry has this problem:
- The
namefield is just a dietary tag ("GF","GFA","V+", etc.) - The
descfield starts with what looks like a dish name run together with the description (no space or punctuation between them, e.g."Chocolate TorteA rich slice of flourless paradise")
Special Characters
The data lives in a JSON file, so be careful with quotation marks inside descriptions. Use a curly/smart right double-quote (", U+201D) for inch marks (e.g. 7" pizza) rather than a straight ASCII ", which would break the JSON string. Em dashes (–) and curly apostrophes (') from the source website copy fine as-is.
Critical: JSON structural quotes must be straight ASCII double quotes. Some editors and AI tools auto-correct straight " to curly " / " (U+201C / U+201D). If curly quotes end up wrapping property names or values (e.g. "name" instead of "name"), the JSON file will fail to parse and no restaurants will appear in the app. Always verify that the structural quotes in the data use the straight ASCII " character (U+0022).