Feature: festival / venue aggregator view (NIP-51 list) #8

Open
opened 2026-05-11 06:57:15 +00:00 by padreug · 0 comments
Owner

Background

A "festival", "food court", "collective space", or "neighborhood"
is any context where a customer wants to browse and order across
multiple restaurants in one cart. The design rationale (see
docs/webapp-integration.md) commits us to emergent grouping:
whoever runs the venue publishes a NIP-51 list event of restaurant
pubkeys; the webapp consumes that list and fans out per restaurant.
No central database, no central wallet, no server-side "festival"
entity inside the extension.

The current customer webapp module ships single-venue only
/r/:slug resolves one restaurant. The cart store already keys by
restaurant_id so the data model is ready; this issue is only the
discovery + presentation layer.

Goals

  • A new route /festival/:naddr (or /group/:naddr) that resolves
    a NIP-51 addressable list event and renders a unified browse over
    its restaurants.
  • Customers can put items from multiple restaurants in one cart.
    Checkout opens N invoices in sequence, settling each via
    WalletService.payInvoice (one bolt11 per restaurant).
  • Pre-flight balance check sums /quote responses across all
    restaurants in the cart before opening any invoice.
  • Per-restaurant order tracking after settlement (each restaurant's
    KDS / print pipeline runs independently).
  • A simple curator tool (UI or CLI) for publishing / updating a
    NIP-51 list event. Probably out of scope of this issue — list
    authoring can live elsewhere; this issue is consumer-only.

Open design questions

  • Which NIP-51 kind? kind 30000 (follow set) is generic;
    kind 30002 (relay set) and kind 30003 (bookmark set) all
    parameterized-replaceable; we may want a custom kind in the
    30000–39999 range so curators can distinguish "festival lists"
    from regular follow sets. Reference: NIPs at
    ~/dev/refs/repos/nostr-protocol/nips/51.md.
  • URL shape: /festival/:naddr (NIP-19 addressable identifier)
    vs /festival/:hexId vs operator-defined slug — naddr1... is
    most protocol-pure but ugly. May want both: addressable id under
    the hood, optional human-readable slug indexed by a separate
    registry event.
  • Partial-payment failure mode: a restaurant going offline
    mid-cart. Best-effort sequential payment is fine; HODL invoices
    are the harder atomic alternative (its own issue when we want
    it).
  • Cross-instance discovery: if restaurants are on multiple
    LNbits instances, the webapp talks to N different apiBaseUrls.
    Restaurant profile would need to carry its api_base somewhere
    — either added to the kind-0 metadata event or resolved per
    restaurant from its nostr_pubkey via an LNbits well-known
    endpoint.

Acceptance criteria

  • /festival/:naddr route resolves a NIP-51 list and renders
    a header (curator name, list title) plus a per-restaurant
    accordion or tabbed view.
  • Unified search filter spans all restaurants.
  • Cart visibly groups by restaurant; checkout pays each bolt11
    sequentially with per-restaurant progress feedback.
  • Per-restaurant orders land in the existing /orders/:id
    tracker.
  • If one bolt11 fails after others have settled, the customer
    is informed clearly which restaurants completed and which
    didn't, with retry / refund affordances.
  • docs/webapp-integration.md updated; new note
    docs/festival-aggregator.md added under the Obsidian vault
    and indexed from docs/index.md.

Out of scope

  • Festival list authoring UI.
  • HODL-invoice atomicity (separate issue when we want it).
  • Per-restaurant payment failure rollback (refunds).
  • Multi-instance discovery automation (assume api_base per
    restaurant is configurable for now).

Files / surfaces (rough)

  • ~/dev/webapp/src/modules/restaurant/views/FestivalPage.vue (new)
  • ~/dev/webapp/src/modules/restaurant/composables/useFestival.ts (new)
  • ~/dev/webapp/src/modules/restaurant/services/RestaurantNostrSync.ts
    (extend to subscribe to multiple authors)
  • ~/dev/webapp/src/modules/restaurant/stores/cart.ts (multi-
    restaurant code paths already wired in v1; just exercise them)
  • ~/dev/shared/extensions/restaurant/docs/webapp-integration.md

See also

  • #2 — tiered operator modes (per-tier visibility decisions)
  • (NIP-17 transport issue, sibling to this) — different transport
    layer concern but related Nostr-native trajectory

References

  • NIP-51 at ~/dev/refs/repos/nostr-protocol/nips/51.md
  • ~/dev/shared/extensions/restaurant/docs/webapp-integration.md
    (multi-restaurant cart flow rationale)
## Background A "festival", "food court", "collective space", or "neighborhood" is any context where a customer wants to browse and order across multiple restaurants in one cart. The design rationale (see `docs/webapp-integration.md`) commits us to **emergent** grouping: whoever runs the venue publishes a NIP-51 list event of restaurant pubkeys; the webapp consumes that list and fans out per restaurant. No central database, no central wallet, no server-side "festival" entity inside the extension. The current customer webapp module ships **single-venue only** — `/r/:slug` resolves one restaurant. The cart store already keys by `restaurant_id` so the data model is ready; this issue is only the discovery + presentation layer. ## Goals - A new route `/festival/:naddr` (or `/group/:naddr`) that resolves a NIP-51 addressable list event and renders a unified browse over its restaurants. - Customers can put items from multiple restaurants in one cart. Checkout opens N invoices in sequence, settling each via `WalletService.payInvoice` (one bolt11 per restaurant). - Pre-flight balance check sums `/quote` responses across all restaurants in the cart before opening any invoice. - Per-restaurant order tracking after settlement (each restaurant's KDS / print pipeline runs independently). - A simple curator tool (UI or CLI) for publishing / updating a NIP-51 list event. Probably *out of scope* of this issue — list authoring can live elsewhere; this issue is consumer-only. ## Open design questions - **Which NIP-51 kind?** `kind 30000` (follow set) is generic; `kind 30002` (relay set) and `kind 30003` (bookmark set) all parameterized-replaceable; we may want a custom kind in the `30000–39999` range so curators can distinguish "festival lists" from regular follow sets. Reference: NIPs at `~/dev/refs/repos/nostr-protocol/nips/51.md`. - **URL shape:** `/festival/:naddr` (NIP-19 addressable identifier) vs `/festival/:hexId` vs operator-defined slug — `naddr1...` is most protocol-pure but ugly. May want both: addressable id under the hood, optional human-readable slug indexed by a separate registry event. - **Partial-payment failure mode:** a restaurant going offline mid-cart. Best-effort sequential payment is fine; HODL invoices are the harder atomic alternative (its own issue when we want it). - **Cross-instance discovery:** if restaurants are on multiple LNbits instances, the webapp talks to N different `apiBaseUrl`s. Restaurant profile would need to carry its `api_base` somewhere — either added to the kind-0 metadata event or resolved per restaurant from its `nostr_pubkey` via an LNbits well-known endpoint. ## Acceptance criteria - [ ] `/festival/:naddr` route resolves a NIP-51 list and renders a header (curator name, list title) plus a per-restaurant accordion or tabbed view. - [ ] Unified search filter spans all restaurants. - [ ] Cart visibly groups by restaurant; checkout pays each bolt11 sequentially with per-restaurant progress feedback. - [ ] Per-restaurant orders land in the existing `/orders/:id` tracker. - [ ] If one bolt11 fails after others have settled, the customer is informed clearly which restaurants completed and which didn't, with retry / refund affordances. - [ ] `docs/webapp-integration.md` updated; new note `docs/festival-aggregator.md` added under the Obsidian vault and indexed from `docs/index.md`. ## Out of scope - Festival list authoring UI. - HODL-invoice atomicity (separate issue when we want it). - Per-restaurant payment failure rollback (refunds). - Multi-instance discovery automation (assume `api_base` per restaurant is configurable for now). ## Files / surfaces (rough) - `~/dev/webapp/src/modules/restaurant/views/FestivalPage.vue` (new) - `~/dev/webapp/src/modules/restaurant/composables/useFestival.ts` (new) - `~/dev/webapp/src/modules/restaurant/services/RestaurantNostrSync.ts` (extend to subscribe to multiple authors) - `~/dev/webapp/src/modules/restaurant/stores/cart.ts` (multi- restaurant code paths already wired in v1; just exercise them) - `~/dev/shared/extensions/restaurant/docs/webapp-integration.md` ## See also - #2 — tiered operator modes (per-tier visibility decisions) - (NIP-17 transport issue, sibling to this) — different transport layer concern but related Nostr-native trajectory ## References - NIP-51 at `~/dev/refs/repos/nostr-protocol/nips/51.md` - `~/dev/shared/extensions/restaurant/docs/webapp-integration.md` (multi-restaurant cart flow rationale)
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/restaurant#8
No description provided.