Full Development Plan

End-to-End Web Application — Adventures Overland

Angular · Node.js · MongoDB · Cloudflare · Microsoft Azure

Decoupled SPA + REST API 3 Repositories ~40 Endpoints 25+ Components 10 Collections

Product Overview

Adventures Overland (AO) is a premium adventure travel company offering self-drive road trips, expeditions, and curated overland experiences. This web application serves as their primary digital platform for:

  • Showcasing trips across categories (World Series, Road Trips in India, Supercar Drives, AO Experiences)
  • Enabling users to browse, filter, search, and compare trips
  • Collecting booking requests and enquiries
  • Processing payments and managing reservations
  • Publishing content (blogs, travel guides, news)
  • Building brand presence and trust (testimonials, media coverage, company story)

Target users: Adventure-seeking travelers (25–55), primarily India-based, browsing on mobile (60%) and desktop (40%).

System Architecture

architecture.diagram
                          ┌─────────── CLOUDFLARE ───────────┐
                          │  DNS · CDN · WAF · DDoS         │
                          └──────────────┬──────────────────┘
                                         │
              ┌──────────────────────────┼──────────────────────────┐
              ▼                          ▼                          ▼
   ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
   │  ANGULAR SPA     │  │  NODE.JS API     │  │  ADMIN PANEL     │
   │  (ao-web)        │  │  (ao-api)        │  │  (ao-admin)      │
   │  Azure Static    │  │  Azure App Svc   │  │  Azure Static    │
   │  Angular 19      │  │  Express.js      │  │  Angular 19      │
   │  Material + SCSS │  │  TypeScript      │  │  PrimeNG Tables  │
   │  NgRx Signals    │  │  Mongoose        │  │  Material        │
   └──────────────────┘  └────────┬─────────┘  └──────────────────┘
                                         │
                    ┌────────────────────┼────────────────────┐
                    ▼                    ▼                    ▼
         ┌──────────────┐  ┌──────────────┐  ┌──────────────────┐
         │  MongoDB     │  │  Azure Blob  │  │  Azure Comms     │
         │  Atlas /     │  │  Storage     │  │  Services        │
         │  Cosmos DB   │  │  (files)     │  │ (Email,SMS,WA)   │
         └──────────────┘  └──────────────┘  └──────────────────┘

Key Architectural Decisions

DecisionChoiceRationale
Frontend-Backend splitDecoupled SPA + REST APIIndependent scaling, separate deploy cycles
Two reposao-web + ao-apiClear ownership, independent CI/CD
SSR approachAngular UniversalSEO for public pages, hydration for interactivity
DatabaseMongoDB (document store)Flexible trip schemas, embedded itineraries, fast reads
API styleREST (not GraphQL)Simpler, well-understood, sufficient for this domain
Admin panelSeparate Angular appDifferent auth context, independent deploy

Information Architecture & Sitemap

sitemap
/                                   → Home
├── /trips                          → All Trips (Listing + Search + Filter)
│   ├── /trips/fixed-departures     → Fixed Departures
│   ├── /trips/road-trips-india     → Road Trips in India
│   ├── /trips/supercar-drives      → Supercar Drives
│   ├── /trips/ao-experiences       → AO Experiences
│   └── /trips/:slug               → Trip Detail (#overview #itinerary #faq #enquire)
├── /about                          → About Us
│   ├── /about/our-story            → Our Story
│   ├── /about/our-team             → Team
│   ├── /about/testimonials         → Testimonials
│   └── /about/careers              → Careers
├── /resources
│   ├── /resources/blog             → Blog listing
│   ├── /resources/blog/:slug       → Blog post
│   ├── /resources/in-the-news      → Press / Media
│   ├── /resources/travel-guides    → Travel Guides
│   └── /resources/faq              → Global FAQ
├── /book/:tripSlug                 → Booking Flow (multi-step)
├── /account                        → User Account (auth guard)
│   ├── /account/bookings           → My Bookings
│   ├── /account/wishlist           → Saved Trips
│   └── /account/profile            → Profile Settings
├── /auth                           → Login / Register / Password Reset
├── /legal                          → Privacy · Terms · Cancellation

│   ADMIN (admin.adventuresoverland.com)
└── /admin                          → Dashboard · Trips · Bookings · Enquiries · ...

Responsive Design Strategy

The Figma only contains mobile (390px) screens. The responsive strategy defines how each layout adapts across 5 breakpoints.

Breakpoints

TokenWidthTarget Devices
xs0–599pxPhones (portrait)
sm600pxPhones (landscape), small tablets
md960pxTablets (portrait)
lg1280pxTablets (landscape), laptops
xl1920pxDesktops, large monitors

Layout Rules

ElementMobile (xs–sm)Tablet (md)Desktop (lg+)
HeaderLogo + hamburgerLogo + condensed navFull nav + CTA button
NavigationFull-screen sidenavFull-screen sidenavHorizontal bar + dropdowns
Trip CardsSingle column2-column grid3-column grid (4 on xl)
Hero CarouselFull-width, 60vhFull-width, 50vhFull-width, 70vh + overlay
Trip DetailSingle columnSingle column, wider2-col: content + sticky sidebar
FilterBottom sheetSide panel (slide right)Persistent sidebar
ItineraryAccordion, full widthAccordion + side mapTimeline left + map right
TestimonialsSwipe carousel2-card carousel3-card row with arrows

Desktop-Specific Additions

  • Mega menu dropdown for Trips (category previews + featured trip)
  • Breadcrumbs on interior pages
  • Sticky sidebar on Trip Detail (price, CTAs, upcoming dates)
  • Trip comparison (side-by-side, desktop only)
  • Search in header with autocomplete
  • Hover states on cards (lift shadow + quick-view overlay)
  • Lightbox gallery for trip highlights
  • Sticky sub-nav on Trip Detail (Overview / Itinerary / FAQ / Enquire)

Screen-by-Screen Scope

Home Page

SectionMobileDesktop
HeroFull-screen video/image + CTAFull-viewport video + headline overlay
Trip CategoriesHorizontal scroll cards4-column grid with hover effects
Featured TripsVertical card stack3-column card grid
Why AOStacked value props3-column icon+text row
TestimonialsSwipe carousel3-card row
NewsletterStacked formInline form centered

Trip Listing Page

SectionMobileDesktop
Search + FilterSearch input + filter iconInline search + filter dropdowns
Category TabsHorizontal scroll pillsFull row of tabs
Trip Grid1 column3 columns with sidebar filters
Pagination"Load More" buttonNumbered pagination

Trip Detail Page

SectionMobileDesktop
Hero CarouselFull-width, dotsFull-width with thumbnail strip
Sticky Sub-navNone (scroll to section)Sticky tabs: Overview / Itinerary / FAQ / Enquire
OverviewTitle + CTAs stackedContent left + sticky price card right
ItineraryAccordion per dayTimeline view left + map right
Highlights2×2 image gridMasonry gallery or lightbox
Enquiry FormFull-width stacked2-column form in card
FAQAccordionAccordion, max-width 800px centered

Booking Flow & Account

Step / SectionMobileDesktop
Select Date + TravelersFull page formMulti-step stepper, left panel
Traveler DetailsFull page formSame, wider layout
Review & PaymentStacked summarySummary left + payment right
My BookingsCard list with status badgesTable view with filters
WishlistSaved trip cards3-column grid

User Flows

Trip Discovery → Enquiry

Home Browse Categories Trip Listing Apply Filters Trip Detail Enquiry Form Confirmation

Trip Discovery → Booking

Home Trip Listing Trip Detail "Book Now" Date + Travelers Details Add-ons Review + Pay Confirmation

Wishlist / Favorites

Trip Card ♥ Login Prompt Saved to Wishlist /account/wishlist

Brochure Download

Trip Detail "Download Brochure" Lead Capture Dialog PDF Download Lead → CRM

Tech Stack

Frontend (Angular SPA)

LayerChoiceRationale
FrameworkAngular 19Enterprise-grade, strong typing, built-in DI/routing
SSRAngular UniversalServer-side rendering for SEO on public pages
UI ComponentsAngular Material 19Sidenav, dialog, tabs, chips, slider, expansion panel, bottom sheet
StylingSCSS + Material themingCustom theme with AO brand tokens, responsive mixins
CarouselSwiper.js (Angular wrapper)Touch-optimized, SSR-compatible
FormsReactive Forms + validatorsType-safe with FormGroup/FormArray
StateNgRx SignalStoreSignal-based state for filters, wishlist, cart, auth
HTTPHttpClient + interceptorsJWT interceptor, error interceptor
MapsAzure Maps / MapboxRoute polylines, interactive itinerary map
IconsMaterial Icons + custom SVGsConsistent iconography matching Figma

Backend (Node.js API)

LayerChoiceRationale
RuntimeNode.js 20 LTSStable, Azure-native support
FrameworkExpress.js + TypeScriptLightweight, flexible, massive ecosystem
DatabaseMongoDB 7Document model fits trip/itinerary data
ODMMongoose 8Schema validation, middleware, TypeScript
AuthPassport.js + JWTGoogle OAuth + local strategy
ValidationZodSchema validation on all API inputs
File StorageAzure Blob StorageTrip images, brochures, user uploads
Image CDNCloudinaryOn-the-fly transforms, WebP/AVIF
EmailAzure Communication ServicesTransactional emails, Azure-native
SMSAzure Communication ServicesOTP verification, booking confirmations, alerts
WhatsAppWhatsApp Business API (Meta)Booking updates, trip reminders, rich media
SearchMongoDB Atlas SearchFull-text with fuzzy matching, facets
PaymentRazorpayIndia-focused — UPI, cards, wallets, EMI
CAPTCHACloudflare TurnstilePrivacy-friendly, invisible
JobsAgenda.js (MongoDB-backed)Reminders (email/SMS/WA), slot updates, reports

Frontend Architecture

Repository: ao-web

ao-web/src/app/
core/
  auth/           auth.service · auth.guard · auth.interceptor
  api/            trip.service · booking.service · enquiry.service · content.service
  error.interceptor · seo.service · breakpoint.service

shared/
  components/     header · footer · mobile-nav · image-carousel · trip-card
                    category-tabs · date-chips · cta-section · testimonial-card
                    breadcrumbs · search-autocomplete · gallery-lightbox
                    icon-info-row · accordion-group · lead-capture-dialog
                    sticky-price-bar · loading-skeleton · brand-value-card
  pipes/          currency · truncate · date-range
  directives/     lazy-image · scroll-spy · click-outside

store/            auth.store · trip-filter.store · wishlist.store · booking.store · ui.store

features/         (all lazy-loaded)
  home/           Home page
  trips/          trip-listing · category-landing · trip-detail · filter-panel
  booking/        booking-wizard · step-date · step-travelers · step-addons · step-review
  account/        my-bookings · wishlist · profile
  auth/           login · register · forgot-password
  about/          About Us pages
  resources/      blog-listing · blog-detail
  contact/        Contact page
  legal/          Privacy · Terms · Cancellation

Component Library (25+ reusable components)

ComponentMaterial BaseVariants
HeaderComponentMatToolbar, MatButtontransparent / solid, mobile / desktop
MobileNavComponentMatSidenavSlide-out with links + social icons
ImageCarouselComponentSwiper.jsdots / arrows / thumbs, autoplay
TripCardComponentMatCardvertical / horizontal, compact / full
FilterPanelComponentMatBottomSheet / MatSidenavbottom-sheet (mobile) / sidebar (desktop)
ItineraryTimelineComponentMatStepper / customvertical (mobile) / split with map (desktop)
EnquiryFormComponentReactive Forms + MatFormFieldstandalone / embedded, with CAPTCHA
BookingWizardComponentMatSteppermulti-step horizontal/vertical
StickyPriceBarComponentmobile bottom bar / desktop sidebar card
GalleryLightboxComponentCDK Overlaygrid + fullscreen overlay with zoom

Backend Architecture

Repository: ao-api

ao-api/src/
config/         db · cloudinary · azure-blob · passport · razorpay · env (Zod)

models/         user · trip · booking · enquiry · testimonial · blog-post · faq · newsletter · team · coupon

routes/         trip · booking · payment · enquiry · auth · user · wishlist · search · content · upload · newsletter
  admin/        admin-trip · admin-booking · admin-enquiry · admin-content · admin-user · admin-analytics

controllers/    Route handlers (mirrors routes structure)

services/       trip · booking · payment · pricing · email · sms · whatsapp · search · upload · analytics

middleware/     auth · admin · validate (Zod) · rate-limit · error

validators/     Zod schemas: trip · booking · enquiry · auth · common

jobs/           trip-reminder (7-day) · slot-status (auto-update) · report (weekly summary)

utils/          jwt · password (bcrypt) · slug · pagination · booking-number (AO-2026-00001)

types/          trip.types · booking.types · user.types · api.types

Database Schema (MongoDB)

10 collections using embedded subdocuments for denormalized, fast reads.

Trips Collection

trips
{
  slug: String,               // unique, indexed — "ladakh-expedition"
  name: String,               // "Ladakh Expedition"
  category: "world_series" | "road_trips_india" | "supercar_drives" | "ao_experiences",
  badge: String,              // "Trending", "Limited seats"
  heroImages: [String],       // Cloudinary URLs
  duration: { nights: Number, days: Number },
  cost: { amount: Number, currency: "INR", emiAvailable: Boolean },
  tripType: "adventure" | "leisure" | "short_trip",
  experienceLevel: "beginner" | "intermediate" | "experienced",
  driveType: "self_drive" | "assisted",

  // Embedded subdocuments
  dates: [{ startDate, endDate, slotsTotal, slotsBooked, status: "open" | "filling_fast" | "sold_out" }],
  itinerary: [{ dayNumber, title, description, images, activities, distance }],
  faqs: [{ question, answer, sortOrder }],
  seo: { metaTitle, metaDesc, ogImage }
}

Bookings Collection

bookings
{
  bookingNumber: "AO-2026-00001",
  userId: ObjectId,  tripId: ObjectId,  tripDateId: ObjectId,
  tripSnapshot: { name, slug, startDate, endDate, heroImage },
  travelers: [{ name, age, idType: "passport" | "aadhar", idNumber }],
  addOns: [{ name, price }],
  pricing: { basePerPerson, travelerCount, addOnsTotal, subtotal, gst, tcs, couponDiscount, total },
  status: "pending" | "confirmed" | "cancelled" | "completed",
  payment: { razorpayOrderId, razorpayPaymentId, method, paidAt }
}

Other Collections

users

Email/Google auth, roles, embedded wishlist array

enquiries

General / custom / brochure leads, assignment, status

testimonials

Reviews linked to trips, rating, featured toggles

blog_posts

Rich-text, tags, SEO, publish/draft, cover image

global_faqs

Categorized Q&A, sort order, published

newsletter

Email, source (footer/popup/brochure), dates

team_members

Name, role, bio, photo, sort order

coupons

% or fixed, validity, limits, trip restrictions

API Design (REST)

Base URL: https://api.adventuresoverland.com/v1

endpoints
── PUBLIC (no auth) ──────────────────────────────────────────
GET    /v1/trips                     → List trips (filter, sort, paginate, search)
GET    /v1/trips/categories          → Categories with counts
GET    /v1/trips/:slug               → Trip detail (full + itinerary + FAQs)
GET    /v1/trips/:slug/dates         → Available dates with slot availability
GET    /v1/trips/:slug/related       → Related trips
GET    /v1/search?q=ladakh           → Full-text search (trips, blog)
GET    /v1/content/testimonials      → Testimonials (paginated)
GET    /v1/content/blog              → Blog posts (by tag)
GET    /v1/content/blog/:slug        → Single blog post
POST   /v1/enquiries                 → Submit enquiry
POST   /v1/leads/brochure            → Brochure lead capture
POST   /v1/newsletter                → Newsletter signup

── AUTH ──────────────────────────────────────────────────────
POST   /v1/auth/register             → Create account
POST   /v1/auth/login                → Login (returns JWT)
POST   /v1/auth/google               → Google OAuth
POST   /v1/auth/forgot-password      → Send reset email
POST   /v1/auth/refresh              → Refresh JWT

── PROTECTED (JWT required) ─────────────────────────────────
GET    /v1/users/profile             → Get / update profile
POST   /v1/wishlist/:tripId          → Add / remove wishlist
POST   /v1/bookings                  → Create booking
GET    /v1/bookings                  → User's bookings
POST   /v1/payments/verify           → Verify Razorpay signature

── ADMIN (JWT + role=ADMIN) ─────────────────────────────────
GET    /v1/admin/dashboard           → Stats + charts
CRUD   /v1/admin/trips               → Trip management
CRUD   /v1/admin/bookings            → Booking management + CSV export
CRUD   /v1/admin/enquiries           → Enquiry management
CRUD   /v1/admin/testimonials|blog|faq|team|users

Standard Response Envelope

success
{ "success": true,
  "data": { ... },
  "meta": { "page": 1, "total": 47 }
}
error
{ "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid email"
  }
}

Admin Panel

Separate Angular application (ao-admin) deployed at admin.adventuresoverland.com. Same Angular 19 stack + PrimeNG DataTable for complex grids.

ModuleFeatures
DashboardBooking count (today/week/month), revenue chart, new enquiries, upcoming trips, slot fill rate
TripsCRUD, Quill rich text, Cloudinary upload, itinerary builder (drag-reorder), date slot manager, FAQ editor
BookingsDataTable with sort/filter, status update, traveler details, payment info, CSV/Excel export
EnquiriesDataTable, filter by type/status, assign to team, status flow (new → contacted → closed), inline notes
TestimonialsCRUD, approve/reject workflow, link to trip, toggle featured, avatar upload
BlogCRUD, Quill editor, cover image, tag management, publish/draft, SEO fields
TeamCRUD, photo upload, drag-reorder
CouponsCRUD, date range, usage tracking, trip restriction
NewsletterSubscriber list, search, export CSV, bulk unsubscribe
UsersList, role management (user/admin), view bookings per user

Authentication & User Accounts

auth flow
Angular SPA ──(credentials)──→ Node.js API ──(verify)──→ MongoDB
                                      │
                                      ├── Issue JWT (access + refresh)
                                      │
Angular SPA ←──(JWT in response)──←──┘
     │
     ├── Store access token in memory (AuthStore)
     ├── Store refresh token in httpOnly cookie (Set-Cookie by API)
     └── Attach access token via HttpInterceptor on every API call
MethodImplementation
Email + PasswordPassport local strategy, bcrypt hashing (12 rounds)
Google OAuthPassport Google strategy → JWT exchange
Phone OTPAzure Communication Services SMS → verify code → JWT
Access TokenShort-lived JWT (15min), stored in memory (SignalStore)
Refresh TokenLong-lived JWT (7d), httpOnly secure cookie
Password ResetCrypto token in MongoDB, email link, 1hr expiry

Guest browsing: All trip pages are fully accessible without login. Login is required for wishlist, booking, and profile pages. Login prompt is triggered via MatDialog when needed.

Booking & Payment

Booking Flow (MatStepper)

① Select Date + Travelers ② Traveler Details ③ Add-ons ④ Review + Coupon ⑤ Razorpay Payment ⑥ Confirmation

Payment Integration (Razorpay)

payment sequence
Angular SPA                    Node.js API                  Razorpay
    │                                │                              │
    │──POST /v1/bookings──────────→  │──Create booking (pending)──→ │
    │                                │──Create Razorpay order─────→ │
    │  ←──orderId + amount────────── │  ←──order_id──────────────── │
    │                                │                              │
    │──Open Razorpay checkout────────────────────────────────────→  │
    │  ←──paymentId + signature──────────────────────────────────── │
    │                                │                              │
    │──POST /v1/payments/verify───→  │──Verify HMAC signature──→   │
    │                                │──Update booking → confirmed  │
    │  ←──Booking confirmed──────    │──Send confirmation (email+WA+SMS) │

Pricing Logic

pricing
Base Price     trip.cost.amount (per person, in paise)
× Travelers    count
+ Add-ons      sum of selected add-on prices
= Subtotal
+ GST          5% of subtotal
+ TCS          5% (domestic) or 20% (international, above ₹7L)
= Gross Total
− Coupon       percentage or fixed discount (capped at maxDiscount)
= Payable

Email, WhatsApp & SMS Notifications

Multi-channel notification system — Email, WhatsApp, and SMS — ensuring users receive timely updates on their preferred channel.

Channels

📧 Email

Azure Communication Services / SendGrid. Rich HTML templates built with MJML + Handlebars. Booking confirmations, invoices, newsletters.

💬 WhatsApp

WhatsApp Business API (Meta Cloud API). Template messages, rich media (images, PDFs, locations), interactive buttons. Booking updates, trip reminders.

📱 SMS

Azure Communication Services. OTP verification, booking confirmations, critical alerts. Fallback channel when WhatsApp delivery fails.

Notification Matrix

TriggerRecipientEmailWhatsAppSMS
Booking confirmedUser✅ Details + PDF✅ Confirmation + itinerary✅ Booking number
Payment receiptUser✅ Invoice✅ Payment confirmation
Booking cancelledUser✅ Refund info✅ Cancellation + refund✅ Alert
Enquiry receivedUser + Admin✅ Ack + details✅ Alert
Brochure downloadUser✅ PDF attachment
Newsletter welcomeUser✅ Featured trips
Password resetUser✅ Reset link✅ OTP code
Trip reminder (7d)User✅ Departure info✅ Packing list + details✅ Reminder
Payment due / EMIUser✅ Reminder✅ Payment link✅ Due date

WhatsApp Business API

  • Pre-approved template messages for transactional notifications
  • Rich media support — images, PDFs (brochures, itineraries), location pins
  • Interactive buttons — "View Booking", "Download Itinerary", "Contact Support"
  • Opt-in management — users opt-in during booking or via account settings
  • Webhook receiver — incoming messages routed to support team / auto-replies

SEO Strategy (Angular Universal)

SSR vs Client-Only Pages

Page TypeRenderingRationale
Home, Trip ListingSSRSEO-critical, high organic traffic
Trip DetailSSRSEO-critical, structured data
Blog postsSSRContent marketing, Google indexing
About, Contact, LegalSSRIndexable static content
Booking flowClient-onlyBehind auth, no SEO value
Account pagesClient-onlyBehind auth, no SEO value
Admin panelClient-onlySeparate app, no SEO value

Structured Data (JSON-LD)

  • TouristTrip on trip detail pages
  • FAQPage on FAQ sections
  • Organization on about page
  • BlogPosting on blog posts
  • BreadcrumbList on all interior pages
  • Review / AggregateRating from testimonials

On-Page SEO

  • Clean URL slugs (/trips/ladakh-expedition)
  • Admin-editable meta title + description per trip and blog post
  • Alt text on all images (stored in CMS)
  • Dynamic sitemap via GET /v1/sitemap.xml
  • Canonical URLs, Open Graph + Twitter Card meta
  • Core Web Vitals targets: LCP < 2.5s, CLS < 0.1, INP < 200ms

Performance & Caching

LayerStrategy
SSR PagesCloudflare edge cache (s-maxage=60, stale-while-revalidate=300)
API ResponsesCloudflare cache on GET endpoints (60s TTL, purge on write)
Static AssetsAzure CDN + Cloudflare (immutable, 1yr cache)
ImagesCloudinary CDN with auto-format (WebP/AVIF), blur placeholder
MongoDBCompound indexes, Atlas Search dedicated indexes with facets
Angular BundlesLazy-loaded feature modules, tree-shaking, production AOT
Heavy ComponentsDynamic imports for Map, Swiper, Quill (loaded on demand)
FontsSelf-hosted, font-display: swap, subset to Latin + Devanagari
Transfer StatePrevents duplicate API calls after SSR hydration

Testing Strategy

Frontend (Angular)

TypeToolCoverage Target
Unit TestsJasmine + KarmaServices, pipes, guards, validators
Component TestsJasmine + TestBedAll shared + feature components
E2E TestsPlaywrightBooking, enquiry, search, filter flows
Visual RegressionPlaywright screenshotsKey pages at mobile + desktop breakpoints
Accessibilityaxe-core + LighthouseWCAG 2.1 AA compliance

Backend (Node.js)

TypeToolCoverage Target
Unit TestsJestServices, validators, utilities
Integration TestsJest + SupertestAPI endpoints with test MongoDB
Load Testingk6API endpoints under traffic spikes (500 users)
PerformanceLighthouse CICore Web Vitals in CI pipeline
Securitynpm audit + SnykDependency vulnerabilities

Security

ConcernMitigation
XSSAngular's built-in sanitization + CSP headers (Cloudflare)
CSRFJWT in Authorization header (not cookies for API calls)
NoSQL InjectionMongoose schema validation + Zod input parsing
Authbcrypt (12 rounds), JWT with short expiry, refresh rotation
CORSStrict origin allowlist (only ao-web and ao-admin domains)
Rate Limitingexpress-rate-limit per endpoint + Cloudflare WAF rules
Input ValidationZod schemas on all API inputs (server-side, never trust client)
File UploadType + size validation (allowlist: jpg, png, webp, pdf)
PaymentRazorpay server-side HMAC signature verification
SecretsAzure Key Vault for production, .env for local dev
HTTPSCloudflare Full (Strict) SSL, Azure origin cert
DDoSCloudflare DDoS protection + rate limiting
Admin AccessSeparate domain, role middleware, optional IP allowlist

DevOps & Infrastructure

Environments

EnvFrontend URLAPI URLBranch
Developmentlocalhost:4200localhost:3000develop
Stagingstaging.adventuresoverland.comapi-staging.adventuresoverland.comstaging
Productionwww.adventuresoverland.comapi.adventuresoverland.commain

Azure Resources

rg-adventures-overland-prod
Resource Group: rg-adventures-overland-prod
├── Static Web App:     ao-web-prod           (Angular SPA + Universal SSR)
├── Static Web App:     ao-admin-prod         (Admin Angular SPA)
├── App Service:        ao-api-prod           (Node.js API, Linux, B2)
├── App Service Plan:   asp-ao-prod           (B2 tier, auto-scale 1–4)
├── Blob Storage:       aofilesprod           (brochures, uploads)
├── Key Vault:          kv-ao-prod            (JWT_SECRET, DB_URI, RAZORPAY_KEY)
├── Communication Svc:  acs-ao-prod           (email + SMS)
├── WhatsApp API:       Meta Cloud API        (WhatsApp Business messaging)
└── App Insights:      ai-ao-prod            (APM, logging, metrics)

External Services:
├── MongoDB Atlas      ao-production cluster  (M10+, Azure East US)
├── Cloudinary         ao-prod account       (image CDN)
├── Cloudflare         adventuresoverland.com (DNS, CDN, WAF, SSL)
├── Razorpay           production account    (payments)
└── Sentry             ao-prod project       (error tracking)

CI/CD Pipelines (GitHub Actions)

ao-web (Frontend)

# On Pull Request
 Lint (ng lint)
 Type check (tsc --noEmit)
 Unit tests (ng test)
 Build (staging config)
 Deploy preview → staging slot

# On Merge to main
 All of above (prod config)
 E2E tests (Playwright)
 Lighthouse CI
 Deploy → production
 Purge Cloudflare cache

ao-api (Backend)

# On Pull Request
 Lint (ESLint)
 Type check (tsc --noEmit)
 Unit tests (Jest)
 Integration tests (Supertest)
 Deploy → staging slot

# On Merge to main
 All of above
 Deploy → production
 Smoke tests
 Notify Slack

Monitoring & Alerting

ToolPurpose
Azure App InsightsAPI performance, request tracing, dependency tracking, custom metrics
SentryFrontend + backend error tracking, source maps, release tracking
Cloudflare AnalyticsCDN hit rate, WAF events, DDoS attempts, edge latency
Microsoft ClaritySession replays, heatmaps, user behavior analysis
Azure AlertsCPU > 80%, memory > 80%, 5xx rate > 1%, response time > 2s
Better UptimePings API + frontend every 60s

Open Questions

1
Are desktop/tablet Figma designs planned, or should we infer layouts from mobile?
High
2
What does the hamburger menu expand to? (No drawer screen in Figma)
High
3
Is there an existing booking/payment system, or are we building from scratch?
Critical
4
Razorpay confirmed as payment gateway?
Critical
5
MongoDB Atlas (dedicated cluster) or Azure Cosmos DB (MongoDB API)?
High
6
Should user accounts be mandatory for booking, or allow guest checkout?
Medium
7
Is there an existing CRM (HubSpot, Zoho, Salesforce) for lead/enquiry integration?
Medium
8
Azure Communication Services or SendGrid for transactional email/SMS?
Medium
9
Are there existing brand assets (logo SVGs, fonts, color palette) beyond the Figma?
Medium
10
What is the expected trip catalog size? (10s vs 100s — impacts search index design)
Medium
11
Is blog content migrating from an existing platform (WordPress, etc.)?
Low
12
Is there an existing WhatsApp Business account, or do we need to set up a new one?
Medium
13
What is the target launch date?
Critical
14
Expected peak concurrent users? (impacts Azure tier + auto-scaling)
Medium
15
Should the site support multiple currencies or languages (i18n)?
Medium

Project Summary

Decoupled SPA + REST API across 3 repositories (ao-web, ao-api, ao-admin). Angular 19 + Angular Material + SCSS on the frontend, Express.js + TypeScript + Mongoose on the backend, MongoDB Atlas for data, Azure for hosting, Cloudflare for edge. ~40 API endpoints, 25+ reusable components, 10 database collections. Recommended 5-person team (2 Angular devs, 1 Node.js dev, 1 designer, 1 QA).