SRS - v1.1
| Field | Value |
|---|---|
| Version | 1.1 |
| Product | NepWalk |
| Company | Tech Everest |
| Author | Prakash (Product Team) |
| Last Updated | 2026-03-15 |
| 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
3.1 System Admin
| Permission | Details |
|---|---|
| Manage user access | Full |
| View all trips | Full |
| Modify any trip | Full |
| Monitor system usage | Full |
3.2 Tour Leader
| Permission | Details |
|---|---|
| Create trips | Full |
| Edit trip timeline | Full |
| Add / edit / delete itineraries | Full |
| Invite trip members (by email) | Full |
| Remove trip members | Full |
| Toggle trip visibility (private/public) | Full |
| Save trip as template | Full |
| Clone template into new trip | Full |
3.3 Trip Member
| Permission | Details |
|---|---|
| View invited trips (dashboard) | Full |
| View itinerary | Full |
| Receive push notifications | Full |
| Modify timeline | ❌ Not allowed |
3.4 Public Visitor (Not logged in)
| Permission | Details |
|---|---|
| View public trip via shareable link | Full |
| Edit anything | ❌ Not allowed |
| Access private trip data | ❌ 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 | Assigned by |
|---|---|
| System Admin | Manual / seeded in DB |
| Tour Leader | Default role on registration |
| Trip Member | Assigned when invited to a trip |
Every registered user is a Tour Leader by default. A user becomes a Trip Member when invited to a specific trip. These are not mutually exclusive — a user can be a Tour Leader for their own trips and a Trip Member on someone else's.
6. Functional Requirements
6.1 Trip Management
6.1.1 Create Trip
- Tour Leader fills in: trip title, description (optional), start date
- 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 Tour Leader is set as owner
6.1.2 Edit Trip
- Tour Leader can edit: title, description, start date, visibility toggle
- Endpoint:
PUT /trips/:id
6.1.3 Delete Trip
- Tour 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
- Tour Leader sees all trips they created
- Trip Member sees all trips they have been invited to
- Both shown on their respective dashboards
6.1.5 Visibility Toggle
- Tour 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
- Tour 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
- Tour 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
- Tour 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 |
|---|---|---|
| Tour Leader (owner) | Full access + edit | Full access + edit |
| Invited Trip Member | View only | View only |
| Public Visitor | ❌ No access | View only |
| Other Tour Leaders | ❌ 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
- Tour 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
- Tour 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
- Tour 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
- Tour 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.
- Tour 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 Tour 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 Tour Leader and Trip Members
- Latest version shown at the top
- Public sharing page shows latest version info (version number + timestamp only)
- Tour 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 Template System
6.7.1 Save as Template
- Tour Leader can save any of their trips as a template
- Template stores: template name, all days, all itinerary items (title, times, description, location, notes, map_link)
- Templates are per-user — not visible to other users on the platform
6.7.2 Clone Template
- Tour Leader selects a saved template
- System creates a new trip with all days and itinerary items copied
- Members are NOT copied — the new trip starts with no members
- Dates are NOT auto-set — Tour Leader sets dates on the new trip manually
- Changes to the cloned trip do not affect the original template
6.7.3 Template Management
- Tour Leader can view their template list
- Tour Leader can delete a template (does not affect trips already created from it)
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 Member), 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 Members 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 (Tour Leader)
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
Templates
POST /templates ← Save trip as template
GET /templates ← List user's templates
DELETE /templates/:id ← Delete template
POST /templates/:id/clone ← Clone template into new trip
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),
role (admin | leader),
created_at, updated_at
trips
id, title, slug (unique), description, start_date,
visibility (private | public),
created_by (FK: users),
created_at, updated_at
trip_members
id, trip_id (FK: trips), user_id (FK: users),
role (leader | member),
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, created_by (FK: users),
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. Tour 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 template library (templates are per-user only)
- Email notifications (push only)
- Notification preference UI
- Custom slug editing
- Offline editing
- Multi-day activity spanning midnight
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 roles (Admin, Tour Leader)
- 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
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
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 — Templates & Notifications
Deadline: April 24 Demo: Backend + Frontend integrated
Scope:
- Template save from trip
- Template list and delete
- Clone template into new trip (no members copied)
- Push notifications: send on add/delete/time change
- Full notification flow: subscribe → trigger event → receive notification
Demo scenarios:
- Save a trip as template
- Clone template, verify days and activities copied, members not copied
- 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
- Tour Leaders creating and managing trips
- Timelines actively used
- Itineraries publicly shareable
- Push notifications functioning
- Manna group (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 |
|---|---|
| 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. |
| Slug generation | Auto at creation, immutable, format: title-year-random4 |
| 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. |
| Templates scope | Per-user only. No shared library. |
| Template clone | Copies days + activities only. Members and dates not copied. |
| 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. Tour Leaders informed to keep notes appropriate. |
End of Document — NepWalk MVP SRS v1.1