SRS - v1.2
| Field | Value |
|---|---|
| Version | 1.2 |
| Product | NepWalk |
| Company | Tech Everest |
| Author | Prakash (Product Team) |
| Last Updated | 2026-03-20 |
| Hard Deadline | 2026-04-24 (Internal Buffer: 2026-05-24) |
| Launch Date | 2026-04-29 |
Table of Contents
- Introduction
- System Architecture
- User Roles
- Core Data Structure
- Authentication & User Management
- Functional Requirements
- API Requirements
- Database Design
- Non-Functional Requirements
- Out of Scope (MVP)
- Milestones & Demo Plan
- Tools & Communication
1. Introduction
1.1 Purpose
This document defines the Software Requirements Specification (SRS) for the NepWalk MVP. It translates the Business Requirement Specification (BRS) into technical system requirements to guide software development.
Intended audience:
- Backend developers
- Frontend developers
- QA engineer
- Product manager
- Project manager
1.2 Product Overview
NepWalk is a Trip Operations System designed to help tour operators manage and share travel itineraries through a structured timeline.
Core problem solved: Nepal travel is dominated by unreliable middlemen, non-transparent pricing, and no single trustworthy platform. NepWalk replaces scattered communication — WhatsApp messages, Facebook posts, emails, spreadsheets, multiple itinerary versions — with a single source of truth for trip timelines.
The MVP focuses primarily on timeline-based itinerary management.
2. System Architecture
2.1 Technology Stack
| Layer | Technology |
|---|---|
| Frontend | Next.js + TypeScript + PWA |
| Backend | NestJS + Fastify Adapter |
| API Style | REST |
| Database | PostgreSQL |
| ORM | Prisma |
| Auth | OAuth 2.0 (Google) + JWT + Email/Password |
| Notifications | Web Push API (VAPID keys, no third-party) |
| Deployment | Docker + Cloud hosting (post-backend completion) |
| Docs | MkDocs (architecture + tech + product/requirement) |
| Product Docs | Google Docs / Obsidian (business + product) |
2.2 Architecture Diagram
Next.js (Frontend + PWA)
│
│ REST API
▼
NestJS Backend (Fastify Adapter)
│
│ Prisma ORM
▼
PostgreSQL Database
3. User Roles
Roles in NepWalk operate at two levels: system-level and trip-level. They are independent of each other.
3.1 System-Level Roles
There are exactly two system-level roles. These are stored on the users table.
3.1.1 Traveler (Default)
Every user who registers on NepWalk is a Traveler by default. This role cannot be manually assigned — it is the registration default.
| Permission | Details |
|---|---|
| Register and log in | Full |
| Create trips | Full |
| Manage their own trips | Full |
| Be invited to other trips as a member | Full |
| Create and manage personal packages | Full |
| Use global packages to create trips | Full |
| View their dashboard | Full |
| Receive push notifications | Full |
A Traveler who creates a trip is automatically the Trip Leader for that trip (trip-level role). A Traveler who is invited to someone else's trip is a Trip Visitor for that trip. These are not mutually exclusive — the same user can be Trip Leader on their own trips and a Trip Visitor on someone else's trip simultaneously.
3.1.2 Admin
Admin accounts are not created through the registration flow. They are seeded directly in the database by the development team when needed. Admins are internal operators who intervene only when necessary — they do not use the system on a daily basis.
| Permission | Details |
|---|---|
| View all trips (public and private) | Full |
| Modify any trip | Full |
| Manage any user account | Full |
| Promote or demote user system roles | Full |
| Seed and manage global packages | Full |
| Delete any content | Full |
| Monitor system usage | Full |
Admin does not appear in the registration flow. There is no "register as admin" feature. Admin access is a backend operation only.
3.2 Trip-Level Roles
Trip-level roles are stored on the trip_members table. They are scoped to a specific trip and have no effect outside of that trip.
3.2.1 Trip Leader
The user who creates a trip is automatically assigned the Trip Leader role for that trip. There is only one Trip Leader per trip. Trip Leadership cannot be transferred in MVP.
| Permission | Details |
|---|---|
| Edit trip details (title, description, dates, visibility) | Full |
| Add / edit / delete days | Full |
| Add / edit / delete itinerary items | Full |
| Reorder itinerary items | Full |
| Invite members by email | Full |
| Remove members | Full |
| Toggle trip visibility (private / public) | Full |
| Save trip as personal package | Full |
| Delete the trip | Full |
3.2.2 Trip Visitor
Any user who is invited to a trip is assigned the Trip Visitor role for that trip.
| Permission | Details |
|---|---|
| View the trip and its itinerary | Full |
| Receive push notifications for the trip | Full |
| Modify any trip content | ❌ Not allowed |
A Trip Visitor is still a Traveler at the system level. They can create and manage their own separate trips. They just cannot modify the specific trip they were invited to.
Future roles (not in MVP): Trip Visitor is the only non-leader trip role in MVP. Future versions may introduce Guide and Agent as additional trip-level roles with different permissions.
3.3 Public Visitor (Unauthenticated)
Not a stored role — this is any user accessing NepWalk without being logged in.
| Permission | Details |
|---|---|
| View the landing page (global packages) | Full |
| Browse global packages | Full |
| View a public trip via shareable link | Full |
| Edit anything | ❌ Not allowed |
| Access private trips | ❌ Not allowed |
4. Core Data Structure
The system revolves around Trips and Timeline Itineraries.
Trip
└── Day
└── Itinerary Items (Activities)
Example Timeline
3 Days in Kathmandu
Day 1
08:00 – 08:45 (45m) Breakfast at Hotel Yak & Yeti
08:45 – 09:15 (30m) Drive to Pashupati
09:15 – 11:30 (2h 15m) Visit Pashupati
11:30 – 12:30 (1h) Lunch at Roadhouse Café
12:30 – 14:00 (1h 30m) Free time / Rest
Decision: Open-ended ("onward") times are removed from MVP. All activities must have a defined start and end time. Time range per day is 05:00 – 23:00. No activity can cross into the next calendar day.
5. Authentication & User Management
5.1 Registration
Two registration methods are supported:
Method 1 — Email / Password
- User provides name, email, password
- Password is validated (minimum 8 characters)
- Password is hashed (bcrypt) before storage
- Email must be unique in the system
Method 2 — Google OAuth 2.0
- User clicks "Continue with Google"
- Google returns profile (name, email, avatar)
- System creates or links account automatically
- No password stored for OAuth users
Recommendation for Team: Let's use Google OAuth as the primary method. It is free, removes password management burden, reduces friction, and eliminates email verification complexity. Email/password is kept as a fallback.
5.2 Login
- Email/password login returns a JWT token
- Google OAuth login returns a JWT token
- JWT is stored in the frontend (httpOnly cookie recommended)
- Token expiry: 7 days
5.3 Forgot Password (Email/Password users only)
- User enters their registered email
- System sends a reset link (valid for 1 hour)
- User sets a new password via the link
- OAuth-only users see a message: "You signed in with Google. No password to reset."
5.4 Session Handling
- Protected pages redirect unauthenticated users to login
- Frontend stores JWT and attaches it to all API requests
- Logout clears the token from storage
5.5 Role Assignment
| Role | How Assigned |
|---|---|
| Traveler | Automatically on registration. Cannot be changed by the user. |
| Admin | Seeded directly in the database by the dev team. Never via UI. |
| Trip Leader (trip-level) | Automatically assigned to the user who creates the trip. |
| Trip Visitor (trip-level) | Assigned when a Traveler is invited to a trip via email. |
6. Functional Requirements
6.1 Trip Management
6.1.1 Create Trip
- Trip Leader fills in: trip title, description (optional), start date, number of people (optional)
- Slug is auto-generated at creation time:
{title-slug}-{YYYY}-{4-char-random} - Example:
everest-camp-2026-x4k2 - Slug is unique across the system
- Slug is not editable in MVP
- Default visibility: Private
- Trip is saved to DB and Trip Leader is set as owner
6.1.2 Edit Trip
- Trip Leader can edit: title, description, start date, number of people, visibility toggle
- Endpoint:
PUT /trips/:id
6.1.3 Delete Trip
- Trip Leader or Admin can delete a trip
- Requires confirmation dialog before deletion
- Cascades: deletes all days, itineraries, version logs for that trip
6.1.4 View Trip List
- Trip Leader sees all trips they created
- Trip Visitor sees all trips they have been invited to
- Both shown on their respective dashboards
6.1.5 Visibility Toggle
- Trip Leader can toggle trip between Private and Public
- Private: Only invited members can view the trip
- Public: Anyone with the shareable URL can view the trip
- Default on creation: Private
6.2 Trip Member Management
6.2.1 Invite Member
- Trip Leader enters the invitee's email address
- System checks if email is a registered user:
- If registered: Trip member record is created immediately. Member sees the trip in their dashboard.
- If not registered: Invitation is stored as pending. When the user registers with that email, they are automatically linked to the trip.
- Invitation email is sent in both cases (registered and pending)
6.2.2 Remove Member
- Trip Leader can remove any member from a trip
- Member loses access immediately
- Member's push notification subscription for that trip is cancelled
6.2.3 View Members
- Trip Leader can view the full member list for a trip
- Shows: name, email, role, invite status (active / pending)
6.2.4 Access Control Rules
| User | Private Trip | Public Trip |
|---|---|---|
| Trip Leader (owner) | Full access + edit | Full access + edit |
| Invited Trip Visitor | View only | View only |
| Public Visitor | ❌ No access | View only |
| Other Travelers | ❌ No access | View only |
6.3 Day Management
6.3.1 Day Model
Each trip contains one or more days. Days are ordered by day_number (ascending). No custom manual reorder in MVP — Day 1 is always first.
6.3.2 Add Day
- Trip Leader adds a day to a trip
- Day number is auto-incremented
- Optional: day title (e.g., "Arrival Day", "Acclimatisation")
6.3.3 Edit Day
- Trip Leader can edit day title
6.3.4 Delete Day
- Deleting a day deletes all its itinerary items
- Confirmation required before deletion
6.4 Timeline Builder (Itinerary Management)
This is the core feature of the NepWalk MVP.
6.4.1 Activity Fields
Each itinerary item must include:
| Field | Required | Notes |
|---|---|---|
start_time |
✅ Yes | Min 05:00, max 22:59 |
end_time |
✅ Yes | Must be after start_time. Max 23:00. |
title |
✅ Yes | Short label |
description |
❌ Optional | Longer detail |
location |
❌ Optional | Name of place |
map_link |
❌ Optional | Google Maps / Apple Maps URL or coordinates |
notes |
❌ Optional | Internal notes for the group |
order_index |
✅ System | For reordering within a day |
Example:
start_time: 08:00
end_time: 08:45
title: Breakfast
location: Hotel Yak & Yeti
notes: Buffet included. Meet in lobby at 07:55.
map_link: https://maps.google.com/?q=HotelYakYeti
6.4.2 Time Rules
- Time range per day: 05:00 to 23:00 (no activity may end after 23:00)
end_timemust be afterstart_time- No overlapping activities within the same day
- Backend validates and rejects overlapping time ranges
- Frontend shows a clear validation error
- Duration is auto-calculated:
end_time - start_time - Duration is displayed in the UI (e.g.,
45m,2h 15m) - Activities crossing midnight are not supported in MVP
6.4.3 Add Activity
- Trip Leader opens an add form / modal
- All required fields filled, optional fields skipped if not needed
- System validates time range and overlap before saving
- Activity is appended to the day (highest order_index + 1)
6.4.4 Edit Activity
- Trip Leader can edit all fields
- On save, overlap validation runs again
- If time is changed, a version log entry is created
6.4.5 Delete Activity
- Confirmation required
- A version log entry is created on deletion
6.4.6 Reorder Activities
Decision: Use explicit Up/Down buttons in MVP. No drag-and-drop.
Rationale: drag-and-drop adds frontend complexity, mobile UX issues, and requires careful state management. Up/Down arrows are reliable, fast to build, and sufficient.
- Trip Leader can move any activity up or down within its day
- Backend endpoint:
PATCH /itineraries/reorder— accepts an ordered array of itinerary IDs for a given day - On reorder, a version log entry is created
6.4.7 Timeline Display Format
08:00 – 08:45 (45m)
Breakfast at Hotel Yak & Yeti
- Activities sorted by
start_timeascending - Duration calculated and shown in parentheses
- Map link shown as a button/icon if present
6.5 Trip Sharing Page
6.5.1 Public URL
Each trip has a unique public URL:
nepwalk.com/trip/everest-camp-2026-x4k2
- Slug is generated at trip creation (see 6.1.1)
- Public URL is always accessible but only shows content if trip is Public
- If trip is Private, the public URL returns a "Trip not available" message
6.5.2 Public Page Content
The public sharing page shows:
- Trip title
- Trip description
- All days with their titles
- All itinerary items per day (start time, end time, duration, title, location, notes)
- Map link button (if present, opens in default map app)
- Latest version info (version number, last edited by, timestamp)
6.5.3 Read-Only Enforcement
- No edit controls are shown to public visitors
- Public API endpoint exposes only allowed fields — no member list, no private management data
6.5.4 Mobile-Friendly Layout
- Timeline is readable on small screens
- Map link buttons are touch-friendly
- Responsive design required
6.6 Version Log
6.6.1 What Triggers a New Version
A version log entry is created when:
| Event | Triggers version? |
|---|---|
| Activity added | ✅ Yes |
| Activity deleted | ✅ Yes |
| Activity time changed (start or end) | ✅ Yes |
| Activities reordered | ✅ Yes |
| Activity title / description / notes / location edited | ❌ No |
| Day added or deleted | ❌ No (MVP) |
Field edits (title, notes, description) do NOT create a version in MVP. Version log tracks schedule changes only.
6.6.2 Version Entry Structure
Each version log entry stores:
| Field | Example |
|---|---|
version_number |
3 |
trip_id |
(FK to trips) |
edited_by |
John (user display name) |
timestamp |
2026-04-01 10:30 |
change_description |
Optional short note from Trip Leader |
Example:
Version 3
Edited by: John
Time: 2026-04-01 10:30
Change: Lunch moved from 12:00 → 13:00
6.6.3 Version Display
- Version list accessible to Trip Leader and Trip Visitors
- Latest version shown at the top
- Public sharing page shows latest version info (version number + timestamp only)
- Trip Leader can optionally add a short change note when saving a version-triggering change
6.6.4 Version Granularity
- Trip-level versioning: One version entry per save action, not per individual field
- Single reorder action = one version entry (not N entries for N items moved)
6.7 Package System
The package system in NepWalk has two distinct scopes: personal packages (private, per-user) and global packages (public, platform-wide). Both use the same underlying data structure but differ in visibility and management.
6.7.1 Terminology
The word Package is used in the product UI instead of "Template." Internally in the codebase and database, the term template remains valid.
| Internal Term | UI Label |
|---|---|
| Template | Package |
| Clone Template | Use this Package / Plan this Trip |
| Personal Template | My Packages |
| Global Template | Explore / Popular Packages |
Note on clone label: The action of creating a trip from a package should not be called "Clone" in the UI. Suggested options: "Use this Package", "Plan this Trip", or "Start from here". Final label to be decided by the designer. The backend endpoint can remain
/templates/:id/use.
6.7.2 Personal Packages (Private)
These are packages created by a Traveler for their own reuse. They are not visible to any other user.
Save as Package:
- Any Trip Leader can save one of their own trips as a personal package
- Saved data: package name, all days, all itinerary items (title, start/end time, description, location, notes, map_link, order_index)
- Members are NOT copied — a package contains only the trip structure, not the people
- Dates are NOT stored — packages are date-agnostic blueprints
View and Manage Personal Packages:
- Traveler sees their own packages on the
/templates(My Packages) page - Can view, rename, and delete their packages
- Deleting a package does not affect any trips previously created from it
Use a Personal Package:
- Traveler selects one of their packages and initiates trip creation from it
- System opens the Create Trip flow (same modal/page as a normal new trip) but pre-populated with the package name as a starting point
- Traveler must fill in: Trip Name (editable), Start Date, and any other trip-level details
- On confirmation, system copies all days and itinerary items from the package into a new trip
- The new trip is independent — changes to it do not affect the original package, and vice versa
6.7.3 Global Packages (Public)
Global packages are platform-level blueprints curated and managed by Admin only. They are visible to all users — including unauthenticated visitors on the landing page.
Purpose:
- Showcase popular Nepal trip blueprints (e.g., "Everest Base Camp Trek — 15 Days", "Kathmandu Cultural Tour — 3 Days")
- Serve as the primary content on the NepWalk landing page for unauthenticated users
- Give new Travelers a starting point without building from scratch
MVP Seed:
- Admin seeds 4–5 carefully curated popular packages before launch
- These are not created through the normal "save trip as package" flow — they are seeded directly by Admin (via admin tools or directly in the DB for MVP)
- Admin can create, edit, and delete global packages at any time
Landing Page Behavior:
- Unauthenticated users see the global packages as the homepage
- Each global package shows: package name, cover image, number of days, brief description, and a "Plan this Trip" button
- "Plan this Trip" for unauthenticated users: redirects to the Register/Login page, then resumes the action after auth
Use a Global Package (authenticated Travelers):
- Traveler clicks "Plan this Trip" on a global package
- System opens the Create Trip flow pre-populated with the package name
- Traveler fills in: trip name (editable), start date, other trip details
- On confirmation, all days and itinerary items from the global package are copied into a new personal trip
- The Traveler becomes the Trip Leader of that new trip
- The global package is not modified
Global packages are read-only for all Travelers — they cannot save, edit, or delete global packages. Only Admin can manage them.
6.7.4 Create Trip Flow from a Package (Both Types)
When a user initiates trip creation from any package (personal or global), the flow is:
- User clicks "Use this Package" / "Plan this Trip"
- System opens the Create Trip modal/page with fields:
- Trip Name (pre-filled with package name, editable)
- Start Date (required — package has no dates)
- Description (optional, editable)
- Number of People (optional, informational for MVP — stored on trip but not enforced)
- Visibility (default: Private)
- User confirms → system creates the trip and copies all days and itinerary items from the package
- User lands on the new trip's Timeline Builder page as Trip Leader
- The original package remains unchanged
6.7.5 Package Management Summary
| Action | Personal Package | Global Package |
|---|---|---|
| Create / Save | Any Traveler (from their own trip) | Admin only (seeded) |
| View | Owner only | All users (including unauthenticated) |
| Use to create a trip | Owner only | Any authenticated Traveler |
| Edit / Delete | Owner only | Admin only |
| Visible on landing page | No | Yes |
| Members copied on use | Never | Never |
| Dates copied on use | Never (date-agnostic) | Never (date-agnostic) |
6.8 Push Notifications
6.8.1 Technology
- Native Web Push API with VAPID keys
- No third-party service dependency (no Firebase FCM)
- Service worker handles push events on the frontend
- VAPID keys generated once and stored in backend environment variables
6.8.2 Subscription Flow
- On first visit to a trip page (as a Trip Visitor), browser prompts for notification permission
- If granted, browser push subscription is saved to DB (linked to user + trip)
- If denied, notifications are silently skipped for that user
6.8.3 Who Receives Notifications
- All Trip Visitors of a trip are auto-subscribed on joining
- No notification preference UI in MVP — opt-out is only via browser-level permission denial
6.8.4 Trigger Events
Notifications are sent when:
- Activity is added
- Activity is deleted
- Activity time is changed
6.8.5 Notification Format
Trip Update — Everest Camp 2026
Lunch time changed
Old: 12:00 – 13:00
New: 13:00 – 14:00
6.8.6 Technical Note for Backend
Spike push notification setup in Milestone 2, not Milestone 5. VAPID key generation, subscription endpoint, and service worker registration should be prototyped early to avoid last-minute integration risk.
6.9 Map Links
- Each activity can optionally include a
map_link - Supported formats: Google Maps URL, Apple Maps URL, coordinates
- Map button is only shown in UI if
map_linkis present - On click, opens in the device's default map application
- Basic URL format validation before save (must start with
http)
6.10 PWA Support
| Feature | MVP? |
|---|---|
| Web app manifest (name, icon, theme color, start URL) | ✅ Yes |
| Service worker (cache static assets) | ✅ Yes |
| Installable on device | ✅ Yes |
| Offline viewing of previously loaded itinerary | ✅ Yes |
| Offline editing | ❌ No |
7. API Requirements
All endpoints are REST. JWT token required on all protected endpoints (via Authorization: Bearer header).
Authentication
POST /auth/register
POST /auth/login
POST /auth/forgot-password
POST /auth/reset-password
GET /auth/google ← OAuth redirect
GET /auth/google/callback ← OAuth callback
POST /auth/logout
Trips
POST /trips ← Create trip
GET /trips ← List trips for logged-in user
GET /trips/:id ← Trip detail (private, auth required)
PUT /trips/:id ← Edit trip
DELETE /trips/:id ← Delete trip
GET /trips/public/:slug ← Public trip page (no auth required)
Trip Members
POST /trips/:tripId/members ← Invite member by email
GET /trips/:tripId/members ← List members
DELETE /trips/:tripId/members/:userId ← Remove member
Days
POST /trips/:tripId/days ← Add day
GET /trips/:tripId/days ← List days for a trip
PUT /trips/:tripId/days/:id ← Edit day title
DELETE /trips/:tripId/days/:id ← Delete day
Itineraries
POST /itineraries ← Add activity to a day
PUT /itineraries/:id ← Edit activity
DELETE /itineraries/:id ← Delete activity
PATCH /itineraries/reorder ← Reorder activities (ordered array of IDs)
Version Log
GET /trips/:id/versions ← Fetch all versions for a trip
Packages (Templates)
POST /templates ← Save personal trip as package
GET /templates ← List caller's personal packages
GET /templates/:id ← Get single package detail
PUT /templates/:id ← Rename / update personal package
DELETE /templates/:id ← Delete personal package
POST /templates/:id/use ← Create a new trip from this package
GET /packages/global ← List all global packages (public, no auth)
GET /packages/global/:id ← Get single global package detail (public, no auth)
The
/packages/globalendpoints are unauthenticated public endpoints. They feed the landing page. Admin management of global packages is handled directly or via a simple admin-only endpoint (not in MVP UI).
Push Notifications
POST /notifications/subscribe ← Save browser push subscription
DELETE /notifications/subscribe ← Remove subscription
8. Database Design
Core Tables
users
id, name, email, password_hash (nullable for OAuth),
avatar_url, auth_provider (email | google),
system_role (traveler | admin),
created_at, updated_at
trips
id, title, slug (unique), description, start_date, number_of_people,
visibility (private | public),
created_by (FK: users),
created_at, updated_at
trip_members
id, trip_id (FK: trips), user_id (FK: users),
trip_role (leader | visitor),
status (active | pending),
invited_email (for pending invites),
created_at
days
id, trip_id (FK: trips), day_number, title,
created_at, updated_at
itineraries
id, day_id (FK: days),
start_time, end_time,
title, description, location, map_link, notes,
order_index,
created_at, updated_at
activity_versions
id, trip_id (FK: trips),
version_number, edited_by (FK: users),
change_type (added | deleted | time_changed | reordered),
change_description (nullable),
snapshot (JSONB — optional, stores trip state at that version),
created_at
templates
id, name,
scope (personal | global),
created_by (FK: users, nullable for global seeds),
created_at, updated_at
template_days
id, template_id (FK: templates), day_number, title
template_itineraries
id, template_day_id (FK: template_days),
start_time, end_time, title, description,
location, map_link, notes, order_index
push_subscriptions
id, user_id (FK: users), trip_id (FK: trips),
endpoint, p256dh, auth_key,
created_at
9. Non-Functional Requirements
Performance
- Timeline load time: < 2 seconds
- Support at least 100 concurrent users per trip
Security
- Role-based access control on all protected endpoints
- JWT authentication
- Private trips return 403 for unauthenticated and uninvited users
- Public API endpoint must not expose private data (member list, internal notes — decision: notes are visible on public page as they are part of the itinerary)
- All inputs validated and sanitised (Prisma + NestJS class-validator)
- HTTPS enforced in production
Note on notes visibility: Activity
notesare shown on the public sharing page. Trip Leaders should be informed of this. If a note is truly internal, the description field should not be used for sensitive information.
Compatibility
| Platform | Support |
|---|---|
| Desktop browsers | ✅ Chrome, Safari, Edge, Firefox |
| Mobile browsers | ✅ Android Chrome, iOS Safari |
| PWA installed | ✅ |
Offline Support
- Previously loaded itinerary pages are viewable offline (service worker cache)
- Offline editing is not required
10. Out of Scope (MVP)
The following will not be built in this MVP:
- AI itinerary editing
- Guide / driver login
- Vehicle tracking
- Vendor portals
- Hotel dashboards
- Restaurant ordering
- Payment system
- Booking engine
- Marketplace
- Shared package library (personal packages only)
- Email notifications (push only)
- Notification preference UI
- Custom slug editing
- Offline editing
- Multi-day activity spanning midnight
- Global package management UI for Admin (Admin seeds directly or via DB for MVP)
- Transfer of Trip Leadership
- Shared personal packages between users
- Guide and Agent as trip-level roles (future)
11. Milestones & Demo Plan
Note: Each milestone demo is backend only. Frontend completion deadline: April 27.
Milestone 1 — Core System
Deadline: March 20 Demo: Backend API only
Scope:
- Project setup (NestJS + Prisma + PostgreSQL)
- User registration (email/password + Google OAuth)
- JWT auth + session handling
- Forgot password flow
- User system roles (Traveler, Admin)
- Trip creation (with slug generation)
- Database schema — core tables
Demo scenarios:
- Register via email and Google OAuth
- Login and receive JWT
- Create a trip, verify slug generated
- Confirm DB tables and schema
QA tasks: Pull backend repo. Test auth APIs with Postman. Log bugs in ClickUp.
Milestone 2 — Timeline Builder
Deadline: April 3 Demo: Backend API only
Scope:
- Day CRUD (create, edit, delete)
- Itinerary CRUD (add, edit, delete, reorder)
- Time validation (05:00–23:00, no overlaps, end > start)
- Duration calculation
- Version log on: add, delete, time change, reorder
- Push notification spike (VAPID keys, subscription endpoint, service worker prototype)
Demo scenarios:
- Create a day, add multiple activities
- Attempt overlapping times (expect 400 error)
- Reorder activities, verify order persists
- Verify version log entry created on time change
- Show VAPID key setup working
QA tasks: Pull backend repo. Test timeline APIs. Test overlap validation edge cases. Log bugs in ClickUp.
Milestone 3 — Trip Sharing Page
Deadline: April 10 Demo: Backend API only (frontend team demos public page UI)
Scope:
- Public trip API (
GET /trips/public/:slug) - Visibility toggle (private / public)
- Public page exposes: title, description, days, itineraries, version info
- Public page hides: member list, pending invitations
- Trip member invite API (email-based, pending state support)
- Member access control enforcement
- Global packages API for landing page
Demo scenarios:
- Create trip, toggle public, access via slug
- Try to access private trip without auth (expect blocked)
- Invite a registered user and a non-registered email
- Confirm pending invite resolves on registration
- Fetch global packages without auth
QA tasks: Test public vs private access. Test invite flow. Cross-browser check on public page.
Milestone 4 — Version Log
Deadline: April 17 Demo: Backend API only
Scope:
- Full version log API (
GET /trips/:id/versions) - Version entries for all trigger events
- Optional change description input
- Version number auto-increment per trip
- Latest version shown first
Demo scenarios:
- Perform 5 timeline changes
- Fetch version log, verify entries and timestamps
- Add optional change description, confirm it's saved
QA tasks: Test all version trigger events. Test version ordering. Test optional description field.
Milestone 5 — Packages & Notifications
Deadline: April 24 Demo: Backend + Frontend integrated
Scope:
- Package save from trip (personal package)
- Package list and delete (personal)
- Use package to create new trip (personal + global)
- Global packages seed and display
- Push notifications: send on add/delete/time change
- Full notification flow: subscribe → trigger event → receive notification
Demo scenarios:
- Save a trip as personal package
- Use personal package to create new trip, verify days and activities copied, members not copied
- Fetch global packages on landing page (unauthenticated)
- Use global package to create new trip as authenticated Traveler
- Trigger an itinerary change, receive push notification on another device
QA tasks: Full regression test. Notification testing (permission prompt, receive message, open app from notification). Mobile PWA test.
Final Launch Preparation
Date: April 24–27
- QA regression testing
- Bug fixes
- UI polish
- Deployment setup (Docker, cloud, env vars, migrations)
- HTTPS confirmation
- Smoke test: login → create trip → add timeline → share → edit → see version → receive notification
MVP Launch
Date: April 29
Expected state:
- NepWalk MVP operational
- Travelers creating and managing trips
- Timelines actively used
- Itineraries publicly shareable
- Push notifications functioning
- Global packages visible on landing page
- First client on-boarded as beta users
12. Tools & Communication
| Tool | Purpose |
|---|---|
| Slack | Official team communication |
| Quick informal chat | |
| ClickUp | Tickets, task tracking, QA bug reports |
| MkDocs | Architecture and technical documentation |
| Google Docs | Business and product documentation |
| GitHub | Code repository (assumed) |
QA Process
- QA pulls frontend and backend repos after each milestone is declared complete
- QA runs the project locally
- QA tests against milestone scope and acceptance criteria
- QA creates bug tickets in ClickUp with steps to reproduce
- QA is involved from Milestone 1 onwards — not after launch
Appendix A — Slug Generation Rule
Slug format: {title-slug}-{YYYY}-{4-char-random}
Rules:
- Title converted to lowercase, spaces replaced with hyphens, special characters removed
- Year is the trip start year (or creation year if start date not set)
- 4-character random alphanumeric suffix for uniqueness
- Collision check on insert; regenerate suffix if collision (extremely rare)
- Slug is immutable after creation
Examples:
| Trip Title | Generated Slug |
|---|---|
| Everest Camp 2026 | everest-camp-2026-x4k2 |
| Kathmandu Cultural Tour | kathmandu-cultural-tour-2026-m9r1 |
| Nepal Mission Trip | nepal-mission-trip-2026-3kp7 |
Appendix B — Open Architecture Decisions (Resolved)
| Decision | Resolution |
|---|---|
| System role names | traveler (default) and admin (seeded only). Old leader system role removed. |
| Trip-level role names | leader (creator) and visitor (invited member). Old member renamed to visitor. |
| Admin creation | Never via UI. Seeded directly in DB by dev team. |
| Trip Leader terminology | Renamed to Trip Leader (trip-scoped). No longer a system-level role. |
| Template vs Package naming | Backend/DB uses template. UI uses Package. Both refer to the same entity. |
| Clone action label | Not "Clone" in UI. Options: "Use this Package" / "Plan this Trip". Final label: TBD by designer. |
| Personal vs Global packages | Both exist in MVP. scope field on templates table distinguishes them. |
| Global package management | Admin-only. Seeded before launch. Not manageable via Traveler UI. |
| Global packages on landing page | Yes — unauthenticated landing page shows global packages as primary content. |
| Number of global packages at launch | 4–5 curated popular Nepal packages seeded by Admin. |
| Unauthenticated "Plan this Trip" | Redirects to login/register, then resumes trip creation after auth. |
| Members copied on package use | Never. Neither personal nor global packages copy members. |
| Dates copied on package use | Never. Packages are date-agnostic. Traveler sets dates during trip creation. |
| Number of people field | Added to Create Trip flow. Stored on trip. Not enforced in MVP. |
| Invite mechanism | Email-based. Registered users linked immediately. Unregistered stored as pending. |
| Auth method | Google OAuth (primary) + Email/Password (fallback) |
| Password reset | Yes, included in MVP |
| Open-ended times | Removed. All activities require start and end time. |
| Time range | 05:00 – 23:00. No cross-midnight activities. |
| Overlap validation | Not allowed. Backend rejects overlapping times with 400 error. |
| Reorder UX | Up/Down buttons. No drag-and-drop in MVP. |
| Day ordering | By day_number ascending. No manual reorder. |
| Trip visibility default | Private |
| Version triggers | Add, delete, time change, reorder only. Field edits do not trigger. |
| Version granularity | Trip-level. One entry per save action. |
| Notification provider | Native Web Push API with VAPID keys. No FCM. |
| Notification subscription | Auto-subscribed on joining a trip. No preference UI. |
| Notes on public page | Visible. Trip Leaders informed to keep notes appropriate. |
End of Document — NepWalk MVP SRS v1.2