Folder Structure

This document maps the real folder layout of Tours so you can quickly locate any piece of code. The trees below reflect the actual repository — a single Next.js 16 App Router application (there is no separate server project).

Repository Root

TEXT
tours-web/
├── src/                     # All application code (see below)
├── scripts/                 # DB init/seed scripts + add-on & OpenAPI tooling (tsx / node)
├── docs/                    # Buyer docs + add-on packages (docs/add-ons)
├── public/                  # Static assets (favicon, manifest, images)
├── migrations/              # Legacy SQL snapshots (schema is created by ensure*Schema functions)
├── prisma/                  # Prisma schema kept for tooling only (runtime uses raw SQL)
├── translations/            # Exported i18n catalogs
├── middleware wiring        # src/middleware.ts (see below)
├── next.config.ts           # Next.js config (image domains, etc.)
├── tailwind.config.ts       # Tailwind CSS config
├── tsconfig.json            # TypeScript config (@/* path alias → src/*)
├── vercel.json              # Vercel deployment config
├── package.json             # Scripts: dev/build, db:init, db:seed:*, addons:*, gen:openapi
└── .env / .env.production    # DATABASE_URL, JWT_SECRET, SECRET_KEY, R2_*, …

src/ Overview

TEXT
src/
├── app/          # Next.js App Router: pages + route handlers (the API)
├── core/         # Reusable framework: contracts + registries (channels/plugins/payments/adapters)
├── product/      # Add-ons (63) + GENERATED aggregation indexes + booking/master schema
├── lib/          # DB client, schema (*-schema.ts), auth, r2, secrets, queries, helpers
├── components/   # Shared React UI (admin, tour, booking, dashboard, form, ui, data-table, …)
├── views/        # Page-level view components for the public site
├── services/     # Client-side data/service helpers
├── hooks/        # Reusable React hooks
├── context/      # React context providers
├── config/       # App configuration constants
├── constants/    # Static constant data
├── data/         # Static/seed data sets
├── assets/       # Bundled assets imported by components
├── types/        # Shared TypeScript types
├── utils/        # Generic utilities (e.g. cn())
├── generated/    # Generated artifacts (Prisma client output — not hand-edited)
├── docs/         # In-app documentation (content/*.md — these files)
└── middleware.ts # Next.js middleware (edge request handling)

src/app — Route Groups

App Router folders wrapped in parentheses are route groups (they organise code without appearing in the URL). Dynamic segments use [param].

TEXT
src/app/
├── layout.tsx                  # Root layout (fonts, providers, global shell)
├── (site)/                     # PUBLIC site + storefront  →  /
│   ├── page.tsx                # Home
│   ├── [slug]/                 # CMS pages by slug
│   ├── tours/                  # Catalog + tour detail
│   ├── booking/                # Booking / checkout flow
│   ├── blogs/  gallery/  faq/  about/  contact/  how-it-works/  enquiry/  careers/  ai-tools/
│   ├── r/  x/                  # Referral + short-link redirects
│   └── privacy-policy/  terms-and-conditions/  cookie-policy/  refund-policy/  …
├── (auth)/                     # Traveler/operator account auth  →  /login, /register, …
│   ├── login/  register/  forgot-password/  reset-password/  verify-email/
├── admin/                      # ADMIN  →  /admin/*
│   ├── login/                  # Admin login (outside the panel group)
│   └── (panel)/                # Authenticated admin shell + pages
│       ├── dashboard/  tours/  bookings/  customers/  operators/  reviews/
│       ├── blogs/  pages/  gallery/  testimonials/  hero-slider/  faqs/  media/
│       ├── inclusions/  extras/  master-data/  coupons/  calendar/  calendars/  leads/
│       ├── marketing/  partners/  apps/  builder/  theme-builder/  why-choose-us/  settings/  …
├── customer/                   # TRAVELER (customer) portal  →  /customer/*
│   └── (app)/                  # Authenticated traveler shell + pages
│       ├── dashboard/  bookings/  wishlist/  reviews/  payments/
│       ├── messages/  notifications/  support/  settings/
├── operator/                   # OPERATOR (seller) portal  →  /operator/*
│   ├── (app)/                  # Authenticated operator shell + pages
│   │   ├── dashboard/  tours/  reservations/  calendar/  reviews/
│   │   ├── insights/  payouts/  billing/  inbox/  settings/
│   ├── [slug]/                 # Public operator profile
│   └── become/                 # Operator onboarding / sign-up
├── influencer/                 # INFLUENCER portal  →  /influencer/*
│   ├── (auth)/                 # login / forgot-password / reset-password / otp
│   └── (app)/                  # dashboard, tours, bookings, commission, payouts,
│                               #   referral-links, analytics, marketing-materials, ai-chat, …
├── install/                    # First-run setup wizard  →  /install
├── docs/                       # In-app buyer docs  →  /docs/[version]
├── api-docs/                   # OpenAPI (Scalar) viewer  →  /api-docs (admin-gated)
├── files/                      # File proxy  →  /files/[...key]
├── ref/                        # Influencer referral entry  →  /ref/[username]
└── api/                        # HTTP API (route handlers — the backend)
    ├── v1/                     # Versioned resource handlers (see below)
    ├── install/                # Installer endpoints
    ├── license/                # License activation / status
    └── openapi.json/           # OpenAPI document (admin-gated)

src/app/api — The API

Every route.ts is an endpoint; there are roughly 300 of them. The versioned surface lives under src/app/api/v1 with one folder per resource:

TEXT
api/v1/
├── admin/            # Admin-only resource handlers (tours, bookings, customers, settings, …)
├── portal/           # Traveler auth + account endpoints
├── customer/         # Traveler portal data (bookings, wishlist, reviews, …)
├── operator/         # Operator portal endpoints (tours, departures, reservations, payouts, …)
├── influencer/       # Influencer portal endpoints
├── tours/  destinations/  inclusions/  extras/  coupons/            # Catalog + commerce
├── bookings/  booking-settings/                                     # Booking + checkout
├── blogs/  pages/  faqs/  gallery/  hero-sliders/  testimonials/    # CMS
├── reviews/  analytics/  track/                                     # Reviews + metrics
├── chat/  chatbot/  livechat/  calendar-config/  captcha/  video/   # Integration channels
├── countries/  currencies/  languages/  locations/  brand/  i18n/   # Reference data
├── forms/  app-version/  plugins/  cron/  ical/  ext/               # Misc + automation

src/core — Reusable Framework

Stable contracts and registries the app reads at runtime. Add-ons plug into these.

TEXT
src/core/
├── channels/        registry.ts → CHANNELS, types.ts (ChannelDef/ProviderDef)
├── plugins/         registry.ts → FEATURES, types.ts → FeaturePlugin, hooks.ts (events)
├── payments/        registry.ts → PAYMENT_DRIVERS, types.ts, drivers/{cod,bank,paypal}.ts
├── adapters/        client.ts / server.ts → clientAdapters()/serverAdapters()
├── email/  video/  calendar/  captcha/  social/  chatbot/  messaging/  realtime/
├── analytics/  script-channel/                  # adapter contracts per channel kind
├── install/         setup wizard + DB provisioning helpers
├── admin/  dashboard/  wishlist/                # shared admin/portal building blocks

src/product — Add-ons & Domain Schema

The 63 built-in add-ons, the domain schema for tours/bookings, plus the generated aggregation indexes.

TEXT
src/product/
├── booking/schema.ts          # ensureBookingSchema(): listings (tours), units (departures),
│                              #   bookings, booking_payments/extras/notes/emails, coupons,
│                              #   listing_reviews, seasons, unit_rates, extras, ical_feeds
├── master/schema.ts           # master_items, listing_master_items, listing_nearby_places
├── addons/                    # add-on packages, one folder each
│   ├── announcements/         # Feature add-on: addon.json, index.ts, schema.ts, *.tsx
│   ├── audit-logs/  webhooks/  digest/  maps/  api/  …
│   ├── payments-mollie/       # Provider add-on: channel + payment driver
│   ├── payments-paystack/  email-sendgrid/  analytics-clarity/  chatbot-anthropic/ …
│   └── index.ts               # [GENERATED] ADDON_CHANNELS
├── features/index.ts          # [GENERATED] ADDON_FEATURES
├── adapters-server/index.ts   # [GENERATED] ADDON_SERVER_ADAPTERS (by kind)
└── adapters-client/index.ts   # [GENERATED] ADDON_CLIENT_ADAPTERS (by kind)

Generated Add-on Indexes

The four index.ts files above are produced by scripts/bundle-addons.mjs and must not be edited by hand. The script scans every addons/<id>/addon.json, then:

  • emits ADDON_CHANNELS (channel/provider add-ons → merged into core CHANNELS),
  • emits ADDON_FEATURES (add-ons flagged as features → exposed as FEATURES),
  • emits ADDON_SERVER_ADAPTERS and ADDON_CLIENT_ADAPTERS, grouped by kind (payment, email, sms, chatbot, captcha, analytics, calendar, video, livechat, …).

A companion scripts/gen-addon-catalog.mjs reads the same manifests to produce the add-on catalog under docs/add-ons. Re-run them via npm run addons:bundle and npm run addons:catalog.

src/lib — Core Library

TEXT
src/lib/
├── db.ts                # Neon/postgres.js client + sql tagged template + rawSql()
├── vendor-schema.ts     # Commerce/store/users/settings ensure*Schema() functions
├── auth-schema.ts  leads-schema.ts       # Admin auth + leads schema (booking/master
│                                          # schema lives in src/product/*/schema.ts)
├── operators.ts         # hosts table + getOperatorId() / commission + earnings/payouts
├── influencers.ts       # Influencer accounts + referral/commission helpers
├── auth.ts              # Admin JWT (jose, HS256) + admin_token cookie
├── customer-auth.ts     # Traveler/operator JWT + member_session cookie + OTP
├── secrets.ts           # AES-256-GCM encrypt/decrypt of stored credentials
├── r2.ts                # Cloudflare R2 / S3 upload, presign, delete, public URL
├── public-id.ts         # ensurePublicId() — non-sequential public ids
├── api-helpers.ts       # ok() / err() / serverErr() JSON responses
├── require-permission.ts  route-permissions.ts  permissions-catalog.ts   # RBAC
├── license/             # index.ts, license client, addons (RS256 offline verify)
├── booking/  document/  builder/  hero/  menu/  blocks/  ai/  seeds/       # subdomains
├── image.ts  r2.ts  mailer.ts  i18n.ts  locations.ts  payments.ts  …

scripts — Provisioning & Tooling

Script npm command Purpose
init-db.ts (part of db:init) Create base/CMS tables + seed admin user + default pages
init-core.ts (part of db:init) Provision core/auth/vendor + Tours business schema (ensure*)
seed-*.ts db:seed:core, … Demo/test data (tours, operators, travelers, reviews, hero…)
bundle-addons.mjs addons:bundle Regenerate the four product index files
gen-addon-catalog.mjs addons:catalog Regenerate the add-on catalog under docs/add-ons
gen-openapi.ts gen:openapi Regenerate the OpenAPI spec from the route handlers
reset-template.ts db:reset Reset the template database

npm run db:init chains init-db.tsinit-core.ts, fully provisioning a fresh database by calling the same ensure*Schema() functions the API routes use at request time.


© CreativeCape Solutions · creative-cape.com · support@creative-cape.com