Skip to main content

12 — Consumer Meta Web Specification

Surface: Consumer Meta Web (Next.js 14+ App Router, PWA) BFF: bff-consumer-service Audience: Guests browsing across tenants, discovering and comparing properties before booking Runtime: Browser (Chrome, Firefox, Safari, Edge); PWA-installed on desktop + mobile


1. Overview

The Consumer Meta Web is the Ghasi Melmastoon discovery layer — a Trivago-style meta-search experience where guests find, compare, and shortlist properties across all tenants, then hand off into the chosen tenant's booking flow without leaving the platform.

What makes it unique:

  • The guest never leaves the platform to book — the booking transition is a runtime context switch, not a redirect.
  • Unified analytics across discovery and booking (same gms_id session).
  • RTL-first (Pashto / Dari default layouts).
  • Offline browse cache: last search results survive a 30-second outage (PWA).
  • Shortlist persists: cookie pre-auth, account post-auth, merged on login.

2. Tech stack

ConcernChoice
FrameworkNext.js 14+ App Router
RenderingRSC default; "use client" only for interactive islands
StylingTailwindCSS + @ghasi/ui-melmastoon design tokens
State — serverTanStack Query v5 (React Query)
State — URLnuqs (type-safe URL search params)
State — clientZustand (shortlist, map viewport, filter panel)
OfflinePWA — next-pwa with workbox. Browse cache strategy: StaleWhileRevalidate for search results (30 s TTL), CacheFirst for property photos (7 d TTL)
MapsLeaflet + OpenStreetMap (no Google Maps API key cost)
i18nnext-intl with ICU MessageFormat
Authgms_id cookie from BFF; no login required for discovery
BFFbff-consumer-service via /api/consumer/ Next.js route handlers

3. Information architecture

3.1 Route tree

/ (root)
├── / → redirect to /[locale]/
├── /[locale]/
│ ├── / ← Home (hero search, featured properties)
│ ├── /search ← Search results (list + map)
│ ├── /property/[propertyId] ← Property detail
│ ├── /shortlist ← Saved properties
│ ├── /account/ ← Guest account (login-gated)
│ │ ├── /login
│ │ ├── /register
│ │ ├── /bookings ← Past/upcoming bookings
│ │ └── /profile
│ └── /[tenantSlug]/ ← Tenant booking context (handoff from search)
│ └── /book/[propertyId] ← Booking funnel (rendered in tenant theme)

[locale] segment: ps, fa, ar, en (language only; region resolved by tenant or property).

3.2 URL state (search page)

/ps/search?dest=Kabul&from=2026-05-01&to=2026-05-03&adults=2&children=0&rooms=1
&stars=3,4,5&amenities=halal_kitchen,prayer_room&cancel=free
&sort=distance&view=list&page=1
&bbox=69.1,34.5,69.3,34.6 (map mode only)

All params type-safe via nuqs. Shareable and deep-linkable.


4. Key screens

4.1 Home

Purpose: Entry point for first-time and returning guests. Inspire discovery; enable quick search.

Sections:

  1. Hero search bar — destination autocomplete + date range + guests. On submit → /search.
  2. "Popular destinations" — curated city tiles (static content, editable in control plane).
  3. "Featured properties" — promoted by super-admin; GET /consumer/v1/featured.
  4. "Near me" — requires geolocation permission; shows 5 nearest available properties.
  5. "Your shortlist" — shown if shortlist is non-empty; last 3 saved properties.

RSC: Hero search is a client component (interactive). Other sections are RSC + streaming.

4.2 Search results

Layout:

  • Desktop: split panel — filters sidebar (left 280 px) + results list/map (right).
  • Mobile: full-width, with filter bottom sheet and toggle between list/map.
  • Map: Leaflet full-viewport with results overlay list (scrollable drawer on mobile).

Data flow:

URL params → useSearchResults() → React Query → GET /consumer/v1/search → search-aggregation-service → results

Pagination: Infinite scroll (IntersectionObserver); 20 results per page; max 200.

Empty state: C3 E-01 (zero results), C3 E-03 (offline), C3 L-01 (loading).

4.3 Property detail

URL: /[locale]/property/[propertyId]

Sections:

  1. Photo gallery — hero carousel + thumbnail strip. AVIF/WebP, LQIP. Tap to expand lightbox.
  2. Property header — name, star rating, location, review score (if any).
  3. Map thumbnail — Leaflet mini-map centered on property.
  4. Amenities grid — icon + label per amenity. Grouped: essentials, room, safety, services.
  5. Rate & availability panel — (requires dates in URL; falls back to "Enter dates to see prices") — shows room types, rate plans, lowest price per night. Book CTA → handoff (J-02).
  6. Room type cards — photo, name, capacity, amenities, rate. "Select" triggers hold + funnel.
  7. About / description — multi-locale. Collapsible after 3 lines.
  8. Policies — check-in time, cancellation, pets, smoking, payment.
  9. Location section — area description, nearby landmarks, transport.
  10. Reviews section — (Phase 2, once review service exists).

4.4 Shortlist

URL: /[locale]/shortlist

State: Zustand + React Query backed by GET /consumer/v1/shortlist (BFF-side cookie / account).

Contents:

  • Property cards in shortlist order.
  • Side-by-side comparison toggle (compare up to 3).
  • Remove from shortlist.
  • "Book" CTA on each card → handoff.

4.5 Booking handoff

URL transition: /[locale]/[tenantSlug]/book/[propertyId]?rate=...&from=...&to=...&adults=...

This URL segment switches the runtime theme from the meta theme to the tenant's theme (via GET /tenant-booking/v1/bootstrap). The user sees the tenant's brand colors and logo without a page reload — same Next.js App Router; just the <ThemeProvider> context changes.


5. PWA / offline behavior

ScenarioBehavior
First visit with networkAll critical paths cached by service worker
Repeat visit, network presentStaleWhileRevalidate — instant render from cache, background refresh
Network lost during browsingServe cached search results; show offline banner (C3 ER-07); new searches blocked (not cached)
Network lost mid-searchCache last successful result page; toast "Offline — showing last results"
PWA installed on deviceApp icon, splash screen, standalone mode (no browser chrome)

Cached assets: App shell, fonts, last 5 search pages, last viewed property detail pages (3).

Not cached: Payment flows, tenant bootstrap (requires fresh token), auth flows.


6. Performance budget

See ../common/09-non-functional-requirements.md §1.1 for canonical web targets. Home and search result pages are the primary targets.

Additional meta-web-specific targets:

  • Search query response (BFF → results rendered): < 800 ms p95
  • Property detail hydration: < 300 ms p95
  • Map tile load (LTE): < 2 s for all visible tiles

7. SEO

  • All property detail pages are SSR (Next.js App Router Server Components) with generateMetadata().
  • Metadata: og:title, og:description, og:image (hero photo), og:type: "place".
  • Structured data: schema.org/Hotel JSON-LD on property detail pages.
  • Canonical URLs include [locale] prefix but have <link rel="alternate" hreflang> for all supported locales.
  • Search results page: noindex (paginated, query-driven).
  • Sitemap: auto-generated nightly for all published properties.

8. Accessibility

  • WCAG 2.2 AA minimum.
  • Map: keyboard-navigable pins; list view always available as alternative.
  • Date picker: ARIA grid pattern; keyboard date entry supported.
  • Filter chips: role="checkbox" group.
  • Photo gallery lightbox: focus trap, ESC to close, aria-label on navigation arrows.
  • Search bar: role="combobox" for destination autocomplete.

9. State management conventions

State typeToolStorage
Search resultsTanStack QueryIn-memory + IndexedDB (PWA cache)
Active filters / sortnuqs (URL)URL
Map viewport (bounds, zoom)nuqs (URL)URL
ShortlistZustand + TanStack QueryCookie (pre-auth) → server (post-auth)
Autocomplete suggestionsTanStack QueryIn-memory, short TTL
Guest sessionBFF cookie (gms_id)HttpOnly cookie

10. Open Questions

  • Home "Near me" section: request geolocation permission proactively or only when tapped? (Preference: only when tapped.)
  • Property reviews: Phase 2. Placeholder design needed for property detail — should it show "Reviews coming soon" or hide the section entirely in R1?
  • Sitemap: should it include all published properties across all tenants, or only properties with at least one published rate plan?
  • PWA install prompt: when to show the add-to-home-screen prompt? After 2 visits (Google's heuristic) or on shortlist save?

References