NepWalk MVP — Scope (v2)
Authoritative product scope for the MVP (build 17–30 Sep 2026). Created 17 Sep 2026.
- Why these choices:
decisions.md. If this file anddecisions.mddisagree,decisions.mdwins; then fix this file. - Day-by-day build plan:
tasks.md. - Change scope only by adding a decision first.
1. What the MVP is
One itinerary, two faces. A tool that makes a real group-trip workflow easier for the operator, and gives travellers a simple day-by-day view.
The manual workflow it replaces
- A group leader sends context: group size, dates, cities, nights, flights, rooms, vehicle needs. Often only the arrival date is fixed at first, and people are still enrolling.
- The operator works through dates and times, spots gaps (e.g. a missing night) and asks the leader questions.
- The operator sends each vendor (hotel, airline/ticketing, van) the details by WhatsApp or phone.
- The vendor books and confirms; the operator records the confirmation.
- The operator sends the group what has been booked.
Software takes over steps 2, 3 and 5. Step 4 (calls) stays human for now. The advantage is operator knowledge written as tested rules (§4), not the forms.
| Face | Who | Goal | Feel |
|---|---|---|---|
| Operator | NepWalk operator now; agencies in 2027 | Build a 13-day trip in 10 minutes | Fast, clear, calm |
| Traveller | Group leader + travellers | Know today's plan in 3 seconds | Visual, fun, Visitacity-simple |
Users:
- Operator: the only login.
- Group leader and travellers: no login. They get a WhatsApp summary and a secret link.
- Vendor: no login. A record managed by the operator.
2. Reference case — the acceptance test
Example request, the typical shape of a church-group request, used as the rules test case. It isn't a confirmed real trip.
Request: 7 pax · 28 Dec → 10 Jan · 5 nights KTM (28 Dec–2 Jan) · rest in PKR · flight KTM→PKR 2 Jan ~09:00 · flight PKR→KTM 9 Jan ~10:00 · rooms: 1 couple + 5 singles · van for Kathmandu valley. Headcount may change, and the tool must re-run when it does.
The tool must output:
NIGHT COVERAGE (13 nights)
✅ KTM 28 Dec→2 Jan (5) ✅ PKR 2 Jan→9 Jan (7) ❌ GAP 9 Jan→10 Jan (1) → KTM hotel
ROOMS: 1 double + 5 single = 6 rooms · 78 room-nights
SERVICES (7): KTM hotel ×5n · PKR hotel ×7n · KTM hotel ×1n · flight 2 Jan ×7 ·
flight 9 Jan ×7 · KTM van (pickup 28 Dec, valley days, drop 2 Jan, pickup 9 Jan, drop 10 Jan) ·
PKR airport↔hotel transfers 2 Jan + 9 Jan
QUESTIONS: arrival time 28 Dec? departure time 10 Jan? passport names? couple double/twin?
PKR vehicle/guide? which valley days need the van? dietary/medical?
FLAGS: 7 pax + luggage → Hiace · PKR arrival ~10:00 → early check-in request ·
PKR winter morning fog → keep 2 Jan morning free · 9 Jan domestic flight 1 day before
international departure → plan B road transfer · 28 Dec–2 Jan peak → book now
Services count: 7 services cover 6 transfer legs, grouped into the KTM van and the PKR transfers.
3. Features
| # | Feature | Must include | Reuse / new |
|---|---|---|---|
| F0 | Foundations | FE Bearer auth fix; auth guards on all read endpoints; isPublic check; template ownership; reorder validation; JWT_SECRET required at startup; Organization + orgId scoping on every trip query (seed one org "NepWalk Ops"); prod deploy (Docker + domain + HTTPS + nightly DB backup) |
nepwalk-be/src/modules/auth, docker-compose.prod.yml |
| F1 | Itinerary builder (operator) | Trip basics: pax (enrolled / expected max / lock date), leader contact, room mix. Nights strip: whole trip on one line, city blocks, empty nights in red. Moves between blocks: one tap ✈ flight / 🚐 road + time. Day list with typed items: STAY, FLIGHT, TRANSFER, VEHICLE, PLACE, MEAL, FREE, CUSTOM |
Existing Trip, Day, Itinerary + days/, itineraries/ modules; existing FE components |
| F2 | Rules engine | Rules R1–R10 (§4) read the itinerary → generated service checklist + rule questions + risk flags. Re-runs on every edit. Pure functions; TDD with the reference case | New planning module |
| F3 | Questions panel | Each question: text · why · source (Rule / AI) · category (hotel/flight/vehicle/traveller) · blocks booking? · status open → asked → answered / dismissed. Flow: tick questions → "Compose message" → one WhatsApp message to the client → type answers back → itinerary updates → rules re-run | New Question model |
| F4 | Vendor directory | NepWalk-wide (no orgId). Type (hotel/airline-ticketing/transport/guide/activity), WhatsApp number, city, verification (license no., vehicle reg/green plate, checked by/date), commission %, status unverified/verified/blocked |
New Vendor model |
| F5 | Place list | NepWalk-wide. Name, city, photo + credit, typical duration, location, one-line description, tip. Only ~15 core places (Kathmandu valley + Pokhara). Place picker replaces the 7-field Add Activity form; "custom item" as fallback | New Place model |
| F6 | Services + booking tracker | One Service per generated booking; one service may cover several itinerary items (e.g. van legs). Fields: type, dates, qty, details, vendor. Status: to request → on hold (range + release-by date) → requested → confirmed / declined → cancelled / completed. Evidence: confirmation ref + who/when + note |
New Service model (= booking) |
| F7 | WhatsApp drafts | Per service: vendor sheet as a monospace block + wa.me link.• Hotel: rooms by type, check-in/out, nights, requests • Vehicle: one line per leg with date, time, from → to, pax, luggage, vehicle type • Flight: date, route, time, pax, passport names, nationality Per trip: "booked for you" summary (confirmed items; pending ones marked) |
Text templates in BE; no WhatsApp API |
| F8 | Commission ledger | Per service: vendor price, currency, commission %/amount, status expected/invoiced/collected + date; paymentFlow enum; trip money summary; global receivables list |
Fields on Service |
| F9 | Traveller day view | Revocable ShareToken; mobile; built to the design brief (§5); Nepal emergency numbers; print CSS; no prices, commissions or emails | FE /trips/[id] read view as base |
| F10 | AI assist (OpenRouter) | "Paste client message → prefill itinerary" + "suggest extra questions" (labelled AI). Optional; everything works with AI off (§6). Default: October unless the build is ahead | New ai module |
| F11 | Inquiry intake | No code: Tally/Google Form on the landing page | Static home page |
Not in the MVP
- Builder extras: manual day/item reorder UI, duplicate, templates UI.
- Agency/tenant screens: only the
orgIdcolumn for now. - Workflow: change approval, version history, notifications/push.
- Vendors and money: vendor login, payments, WhatsApp API.
- Discovery: AI itinerary generation, reviews, marketplace search.
- Platform: PWA offline, i18n, live alerts.
- Design: Stitch/Figma redesign.
Cut-line checkpoint — Wed 23 Sep evening
If behind, these move to October:
- F10 AI assist.
- F9 polish (map, weather, countdown, fun extras). Keep a plain share view or rely on the WhatsApp summary.
- F5 photos (use text-only places).
- The commission "invoiced" state and the receivables screen (use CSV).
Never cut: F0 security + orgId, F1 nights strip, F2 rules, F3 rule questions, F6 tracker, F7 drafts.
4. Rules v1 (each rule has tests)
Rules read itinerary items: "stays" = STAY items; "moves" = FLIGHT / TRANSFER items.
| Rule | Check | Output |
|---|---|---|
| R1 Night coverage | Every night from trip start to end has exactly one stay | Gap/overlap flag + "add hotel" service |
| R2 City continuity | A city change between stays has a move on that date; the move's destination = next stay's city | Missing-move flag |
| R3 Transfers | Every flight arrival/departure → airport transfer leg (pickup at arrival time; drop at intl −3h / domestic −1.5h). Legs are grouped per city into one vehicle service | Transfer legs with times |
| R4 Check-in timing | Arrival before 14:00 → early check-in request; departure after 12:00 → late checkout request | Request note on hotel service |
| R5 Rooms & vehicle | Room mix → rooms and room-nights; pax + luggage → vehicle class (1–3 car · 4–10 Hiace · 11+ coaster; configurable) | Quantities + vehicle flag |
| R6 Connection risk | Domestic flight within 36h of international departure (or departure time unknown) | Risk flag + plan B (road transfer) |
| R7 Weather risk | Pokhara/Lukla/mountain flight before 11:00 in Dec–Feb | Fog-delay flag; keep morning free |
| R8 Missing info | No intl arrival/departure time; no passport names before domestic flights; couple bed type; vehicle days unspecified; dietary/medical | Rule questions (F3) |
| R9 Peak dates | Stay overlaps 24 Dec–2 Jan or Dashain/Tihar dates (config table) | "Book early" flag |
| R10 Headcount not final | Pax has enrolled / expected max / lock date. Until locked: holds only, sized to expected max; lock date must be before the earliest vendor release-by date; re-run rooms + vehicle class when pax changes | "Hold, don't book" flag · release-by countdown (≤7 days) · vehicle class change flag · question: enrolment close date? |
- Time rules (05:00–23:00, no overlaps) apply to
PLACE/MEAL/CUSTOMitems only.STAYspans nights;FLIGHT/TRANSFERmay start early. - Every real miss becomes a new rule + test, logged in
decisions.md.
5. Design brief — copy the pattern, not the pixels
- No Stitch/Figma redesign before real users. Build straight in code with existing components (
nepwalk-fe/design-system.md). - Polish goes to the traveller day view. Clients see it, so it doubles as marketing.
Take from Visitacity:
- Day buttons across the top (
Day 1Day 2Day 3) - Photo card: time label on the photo · title · duration on the right · one-line description
- Connector between cards: "🚐 25 min by van" · "✈ 25 min flight" · "🚶 5 min walk"
Add for groups and logistics: 4. "🌙 Tonight: Hotel X · 📍 map" at the end of each day 5. Call / WhatsApp buttons for driver or guide on the card 6. "⏳ Pending" badge on anything not yet confirmed 7. Light fun: countdown before the trip ("12 days to Nepal 🏔"), "Day 3 of 13", Nepali word of the day, route line KTM → PKR on the map. Map and weather can slip to October.
Traveller day view:
Today · Day 3 of 13 ☀ 18° Kathmandu
09:00 🚐 Pickup at hotel — Ram (driver) 📞
⏱ 25 min drive
09:30 [photo] Pashupatinath Temple · 2h
💡 Cover shoulders & knees
12:00 [photo] Lunch · Thamel
🌙 Tonight: Hotel X · 📍 map
[Day 1][Day 2][Day 3●][Day 4] … Itinerary · Map · Help
Operator builder:
1. BASICS 7 pax (max 10, lock 10 Nov) · 28 Dec → 10 Jan · 1 double + 5 single
2. NIGHTS [KTM ■■■■■][PKR ■■■■■■■][ ? ] ← red empty night = 9 Jan gap
3. MOVES KTM → PKR 2 Jan: ✈ flight 09:00 | 🚐 road (one tap)
4. DAYS tap a day → add places from list (Pashupati, Boudha, Bhaktapur…)
SIDE PANEL ❓ Questions (4) · ✅ Bookings 3/7 confirmed · ⚠ Flags
Delete:
- The 7-field Add Activity form. Use the place picker + time, with "custom item" as fallback.
- Office-software wording ("ACTIVE PLAN", "Trip ID", "Publish").
- The duplicate time display (08:00 / 08:45 AM).
Keep: the trips dashboard (photo cards) · green brand colour. Token unification waits until October.
Place photos: own photos or Wikimedia Commons; store the credit with each photo.
6. Architecture
Principle: AI reads · code calculates · operator approves.
Client's WhatsApp text
→ [ai.extract] draft itinerary (pax, rooms, stays, moves) + "unclear" list (optional)
→ [Operator] nights strip + day list, prefilled; corrects → saved Trip/Day/Itinerary items
→ [planning] rules R1–R10 → services + flags + rule questions (+ ai.suggest questions)
→ [Operator] ticks questions → compose message → client answers → itinerary updated → re-run
→ [messages] vendor sheets + wa.me drafts → operator sends → status requested → confirmed + ref
→ [messages] "booked for you" summary → group leader
→ [share] traveller day view (no money, no emails)
Backend modules (nepwalk-be/src/modules/):
- Existing:
auth,trips,days,itineraries,templates. - New:
organizations,planning(pure functions, no DB),questions,vendors,places,services,messages(templates),share,ai.
Data model changes (Prisma):
Organization(seed "NepWalk Ops").orgIdgoes on Trip, Service, Question, ShareToken and AiRun, and every query is scoped by it.Itinerary(existing item) gets atypeenum plus optionalplaceIdandvendorId.STAYhas check-in/check-out dates.FLIGHT/TRANSFERhave from, to, time and mode.Tripgets pax enrolled / expected max / lock date, room mix and leader contact.- New models:
PlaceandVendor(both NepWalk-wide, noorgId)Service(linked to the itinerary items it covers)QuestionShareTokenAiRun
AI layer (OpenRouter free models; no Claude API):
- Client:
llm.client.tsis an OpenAI-compatible client pointed at OpenRouter. - The key stays server-side; the frontend never calls OpenRouter.
- Env:
OPENROUTER_API_KEY,AI_ENABLED,AI_MODEL_PRIMARY,AI_MODEL_FALLBACKS. ai.extract: message → JSON → schema validation → retry once → otherwise "AI unavailable, use the form".ai.suggest: trip summary → extra questions, labelled AI.- Redact before sending: names, phones, emails and passport numbers become placeholders.
AiRunlog: original message, model, AI output, operator corrections. These become the accuracy score and test cases.- Works with AI off. With
AI_ENABLED=falsethe form does everything.
Portals:
| Portal | Now | Later |
|---|---|---|
| Operator | NepWalk operator | Agencies, same screens (2027) |
| NepWalk admin | NepWalk operator | Vendor verification, commissions across orgs |
| Vendor | Record managed by operator | Oct: confirmation link · 2027: login |
| Traveller | Share link + WhatsApp summary | Same |
7. Acceptance — MVP is "done" when all pass on prod (Wed 30 Sep)
- Reference case (§2) entered through the builder produces:
- 13 nights, with the 9 Jan gap shown red on the nights strip
- 6 rooms / 78 room-nights
- 7 services
- Hiace flag, early check-in request, fog and connection risk flags
- the full rule question list
Rules unit tests cover it.
2. The example request runs end-to-end with no dev tools or DB edits: itinerary → questions composed and answered → services → vendor assigned → WhatsApp draft sent → status confirmed with ref → "booked for you" summary sent.
3. The tool catches everything an experienced operator would catch manually for the example. Every miss becomes a new rule.
4. A group leader opens the share link on a phone and finds the next flight/pickup time and driver contact unaided. If F9 slipped, the WhatsApp summary counts.
5. Access control holds. A private trip returns 401/404 without login or a valid token. A revoked token fails. Changing IDs fails. A second test org can't read the first org's trips.
6. No private data leaks. The share view and group summary contain no prices, commissions or member emails (check the network tab).
7. AI is optional and safe. With AI_ENABLED=false the whole flow works. With AI on, prompts sent to OpenRouter contain no names, phones or passport numbers.
8. Commission maths checks out. The receivables total matches a hand-calculated sheet.
9. Backups restore. A DB backup restores into a fresh container.
10. Backend tests pass. npm test in nepwalk-be passes, including the auth, rules and money tests.