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)         │
         └──────────────┘  └──────────────┘  └──────────────────┘

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
SearchMongoDB Atlas SearchFull-text with fuzzy matching, facets
PaymentRazorpayIndia-focused — UPI, cards, wallets, EMI
CAPTCHACloudflare TurnstilePrivacy-friendly, invisible
JobsAgenda.js (MongoDB-backed)Email reminders, 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 · 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     │

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 & Notifications

Transactional emails via Azure Communication Services. Templates built with MJML → compiled to HTML, stored as Handlebars templates.

TriggerRecipientTemplate
Booking confirmedUserBooking details, itinerary summary, PDF attachment
Payment receiptUserAmount, payment ID, invoice
Booking cancelledUserRefund info, cancellation policy
Enquiry receivedUser + AdminAcknowledgement + full details with CTA link
Brochure downloadUserPDF attachment + related trips
Newsletter welcomeUserWelcome message + featured trips
Password resetUserReset link (expires in 1hr)
Trip reminderUser7 days before departure (Agenda.js job)

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           (transactional email)
└── 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?
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
Third-party integrations needed? (WhatsApp Business, chatbot, travel insurance)
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).