diff --git a/docs/api-reference.md b/docs/api-reference.md index 442a9b3..ec7ed36 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -15,6 +15,7 @@ the catalog. | Method | Path | Notes | |---|---|---| | `GET` | `/restaurants/{id}` | Restaurant profile | +| `GET` | `/restaurants/by-slug/{slug}` | Restaurant profile by URL slug — used by webapps that route on `/r/:slug` and need to resolve to an `id` before any other lookup. 404 when no match | | `GET` | `/restaurants/{id}/menu` | `{restaurant, tree, items}` — the canonical [[menu-tree|menu tree]] (hydrated children + items per node) plus a flat enriched items list with modifier groups + availability windows pre-joined | | `GET` | `/menu_items/{id}` | Single item | | `GET` | `/menu_nodes/{id}` | Single node row | diff --git a/docs/webapp-integration.md b/docs/webapp-integration.md index 4c0a925..e37c0c8 100644 --- a/docs/webapp-integration.md +++ b/docs/webapp-integration.md @@ -9,7 +9,17 @@ of restaurants, especially the multi-restaurant cart pattern. A webapp can either talk to one restaurant directly or aggregate many. There's no central directory inside this extension — grouping ("festival", "collective space", "food court") is **emergent** via -NIP-51 list events curated by whoever runs the venue: +NIP-51 list events curated by whoever runs the venue. + +For the **single-venue** case, a webapp that routes on a URL slug +(`/r/big-jays-bustaurant`) resolves the slug → restaurant via the +public `GET /restaurants/by-slug/{slug}` endpoint +([[api-reference]]) and proceeds with that one `id` for menu reads +and order placement. Slug is just a URL nicety — internally +everything continues to key on the restaurant `id`. + +For the **aggregator** case (multiple restaurants in one cart), the +webapp consumes a curated NIP-51 list event: ``` { diff --git a/views_api.py b/views_api.py index 74ca8e3..ad26520 100644 --- a/views_api.py +++ b/views_api.py @@ -59,6 +59,7 @@ from .crud import ( get_print_job, get_print_jobs, get_restaurant, + get_restaurant_by_slug, get_restaurants, get_settings, move_menu_node, @@ -248,6 +249,20 @@ async def api_list_restaurants( return await get_restaurants(wallet_ids) +@restaurant_api_router.get("/api/v1/restaurants/by-slug/{slug}") +async def api_get_restaurant_by_slug(slug: str) -> Restaurant: + """Public — used by the customer webapp to resolve a URL slug + (e.g. /r/big-jays-bustaurant) to a restaurant. Mirrors + api_get_restaurant; declared *before* the bare-id route so the + static prefix wins the path match in FastAPI's router.""" + restaurant = await get_restaurant_by_slug(slug) + if not restaurant: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail="Restaurant not found." + ) + return restaurant + + @restaurant_api_router.get("/api/v1/restaurants/{restaurant_id}") async def api_get_restaurant(restaurant_id: str) -> Restaurant: """Public — used by the webapp to fetch profile metadata."""