Folder Structure

This document maps the real folder layout of Tutor so you can quickly locate any piece of code. The tree below reflects the actual repository — a single Next.js 16 App Router application (there is no separate server project) that powers a tutoring & education booking marketplace: a public storefront plus four signed-in portals (customer, host, admin, influencer) and a REST API.

Repository Root

TEXT
tutor-web/
├── src/                     # All application code (see below)
├── scripts/                 # DB init/seed scripts + tooling (tsx / node)
├── docs/                    # Buyer docs + add-on packages
├── public/                  # Static assets (favicon, manifest, images)
├── next.config.ts           # Next.js config (image domains, etc.)
├── tailwind.config.ts       # Tailwind CSS config (ink-*/brand-* tokens)
├── 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_* (fallback), …

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 + booking/master/verticals domain modules + GENERATED indexes
├── lib/          # DB client, ensure*Schema, auth (4 sessions), r2, secrets, booking, i18n, …
├── components/   # Shared React UI (admin, booking, listing, form, ui, data-table, …)
├── views/        # Page-level view components for the public site (home, blogs, faq, …)
├── 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
├── generated/    # Generated artefacts
├── types/        # Shared TypeScript types
├── utils/        # Generic utilities (cn, formatting, …)
├── middleware.ts # Edge middleware (routing/i18n)
└── docs/         # In-app documentation (content/*.md — these files)

src/app — Route Groups & Portals

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 storefront  →  /
│   ├── layout.tsx  page.tsx    # Home
│   ├── listings/               # Lesson catalogue/search + lesson detail
│   ├── booking/                # Booking & checkout flow
│   ├── blogs/  gallery/  faq/  about/  contact/  enquiry/  how-it-works/  careers/
│   ├── ai-tools/               # Public AI helpers
│   ├── [slug]/                 # CMS pages (builder/pages)
│   ├── r/  x/                  # Referral capture + short links
│   └── privacy-policy/  terms-and-conditions/  cookie-policy/  refund-policy/
├── (auth)/                     # Customer/host account auth  →  /login, /register, …
│   └── login/  register/  forgot-password/  reset-password/  verify-email/
├── (bare)/                     # Chrome-less layouts
├── admin/                      # ADMIN  →  /admin/*
│   ├── login/  page.tsx        # Admin login (outside the panel group)
│   └── (panel)/                # Authenticated admin shell + pages
│       ├── dashboard/  listings/  bookings/  hosts/  customers/  refunds/  reviews/
│       ├── amenities/  amenity-groups?  extras/  coupons/  master-data/  calendar/
│       ├── blogs/  faqs/  pages/  gallery/  hero-slider/  menus/  partners/  testimonials/
│       ├── about/  why-choose-us/  builder/  theme-builder/  marketing/  leads/  issues/
│       └── apps/  media/  settings/  license/
├── customer/                   # CUSTOMER (student) portal  →  /customer/*
│   └── (app)/                  # dashboard, bookings, payments, messages, notifications,
│                               #   reviews, wishlist, support, settings (+ Chrome/Sidebar)
├── host/                       # HOST (tutor) portal  →  /host/*
│   ├── become/  [slug]/        # Become-a-host + public tutor profile
│   └── (app)/                  # dashboard, listings, calendar, reservations, inbox,
│                               #   insights, payouts, billing, reviews, settings
├── influencer/                 # INFLUENCER / affiliate portal  →  /influencer/*
│   ├── (auth)/                 # Influencer sign-in
│   └── (app)/                  # dashboard, referral-links, bookings, commission, payouts,
│                               #   analytics, marketing-materials, ai-chat, notifications, settings
├── install/                    # First-run setup wizard  →  /install
├── docs/                       # In-app buyer docs  →  /docs/[version]
├── envato/  ref/               # Marketing / referral landing helpers
├── files/                      # File proxy
└── api/                        # HTTP API (route handlers — the backend)
    ├── v1/                     # Versioned resource handlers (see below)
    ├── docs/v1/                # Scalar API reference (admin-gated)
    ├── openapi.json/           # Auto-generated OpenAPI spec (admin-gated)
    ├── install/                # Installer endpoints
    └── license/                # License activation / status

There are no course/lesson-management-system folders — Tutor is a booking marketplace for one-to-one and small-group lessons, not an LMS.

src/app/api/v1 — The API

Every route.ts is an endpoint; the repository contains ~290 of them. The versioned surface lives under src/app/api/v1 with one folder per resource:

TEXT
api/v1/
├── portal/          # Customer/host auth: register, login, verify-otp, forgot, reset, social, me, …
├── customer/        # Customer app: bookings, payments, wishlist, reviews, notifications, support, …
├── host/            # Host app: listings, lesson times, calendar, reservations, earnings, payouts, …
├── influencer/      # Influencer app: referral-links, bookings, commissions, payouts, analytics, …
├── admin/           # Admin-only resource handlers (listings, bookings, hosts, refunds, settings, …)
├── listings/        # Lesson search/detail + [slug], availability, quote, report, [slug]/reviews
├── bookings/        # Create, checkout, pay, verify, payment-methods, paypal
├── amenities/  extras/  coupons/  reviews/                     # What's-included, add-ons, reviews
├── blogs/  pages/  faqs/  gallery/  hero-sliders/  testimonials/  brand/  destinations/   # CMS/content
├── countries/  currencies/  languages/  locations/  i18n/      # Reference + translations
├── forms/  booking-settings/  app-version/                     # Forms + config
├── calendar-config/  captcha/  chat/  chatbot/  livechat/  video/  analytics/  track/   # Channels
└── plugins/  cron/  ext/                                       # Add-on dispatch + automation

The mobile/public API is the non-admin surface here; admin, install, license, cron, ext, plugins, and the chat/analytics areas are excluded from the generated API reference (see the API Documentation).

src/core — Reusable Framework

Stable contracts and registries the app reads at runtime. Integration providers plug in here.

TEXT
src/core/
├── channels/        Channel/provider registry (email, payments, storage, sms, analytics, …)
├── plugins/         Feature-plugin contract + lifecycle hooks
├── payments/        Payment-driver registry + built-in drivers (e.g. paypal, bank)
├── adapters/        clientAdapters()/serverAdapters() — resolve a provider by kind + provider
├── email/  video/  calendar/  captcha/  social/  chatbot/  messaging/  realtime/
├── analytics/  script-channel/                  # adapter contracts per channel kind
├── install/         setup wizard + DB provisioning helpers
├── admin/  dashboard/                            # shared admin/portal building blocks

src/product — Add-ons & Domain Modules

Integration/feature add-ons plus the booking/master domain modules and generated indexes.

TEXT
src/product/
├── addons/                     # Integration & feature add-ons, one folder each
│   ├── payments-stripe/  payments-mollie/  payments-paystack/  payments-flutterwave/ …
│   ├── email-sendgrid/  email-ses/  email-postmark/                 # Email providers
│   ├── analytics-gtm/  analytics-meta_pixel/  analytics-posthog/ …  # Analytics/pixels
│   ├── chatbot-openai/  chatbot-anthropic/  captcha-recaptcha_v3/ … # AI / captcha
│   ├── livechat-crisp/  calendar-google_calendar/  chat-pusher/ …   # Live chat / calendar / realtime
│   ├── announcements/  audit-logs/  digest/  api/  maps/            # Feature add-ons
│   └── index.ts                # [GENERATED] ADDON_CHANNELS
├── booking/                    # Booking domain module — schema.ts + availability-schema.ts
├── master/                     # Master-data module (one `master_items` table, many kinds)
├── verticals/                  # VERTICAL PACKS — one engine, one shipped pack
│   ├── types.ts                #   the VerticalPack contract
│   ├── shared.ts                #   master tables/fields/facets every pack gets
│   ├── index.ts                #   the registry + kind merging
│   ├── active.ts                #   which pack is active (settings) + booking profile
│   ├── apply.ts                #   dry run → snapshot → delete → import → persist
│   ├── terms.ts                #   client-safe vocabulary defaults
│   ├── demo/                   #   people.ts (shared) + seed.ts (one seeder for all packs)
│   └── tutor/                  #   the shipped pack (pack.ts) — Tutoring & Education, add more beside it
├── document/                   # Document module
├── admin-nav.ts  admin-routes.ts  experience-types.ts  product.ts  install.ts
├── 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)

Vertical Packs

verticals/<key>/pack.ts is data only — it never imports from @/lib or @/app, and there is no if (pack === "x") anywhere in the engine. A pack declares its vocabulary, master tables, categories, listing fields, browse facets, booking profile (seat sittings vs slot appointments) and demo catalogue; the engine does the rest. The pack shipped today is Tutoring & Education (verticals/tutor/pack.ts), running in slot mode — tutors publish weekly availability and a lesson length, and students book a lesson time. Adding another vertical is one new folder plus one line in verticals/index.ts.

The active pack lives in the database (settings.section = 'vertical'), so server code reads it through getActivePack() and client components receive it from VerticalProvider — see useTerms().

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), ADDON_FEATURES (add-ons flagged feature: true), and the client/server adapter maps grouped by kind (payment, email, sms, chatbot, captcha, analytics, calendar, video, livechat, …). A companion scripts/gen-addon-catalog.mjs regenerates the add-on catalog. Re-run them via npm run addons:bundle and npm run addons:catalog.

src/lib — Core Library

TEXT
src/lib/
├── db.ts                # Neon client + sql tagged template + rawSql()
├── booking/             # Booking spine: listings, seats (atomic claim/release), quote,
│                        #   create, checkout, pay, refund, cancellation-policy, extras, coupons, invoice
├── auth.ts              # Admin JWT (jose, HS256) + admin_token cookie + getSession()
├── customer-auth.ts     # Customer/host JWT + member_session cookie + OTP + getCustomerId()
├── hosts.ts             # getHostId() — a signed-in customer who is an active host
├── influencer-auth.ts   # Influencer JWT + influencer_session cookie + getInfluencerId()
├── secrets.ts           # AES-256-GCM encrypt/decrypt of stored integration credentials
├── r2.ts                # Cloudflare R2 / S3 upload, presign, delete, public URL
├── payments.ts          # Payment-gateway helpers (via integration_connections)
├── i18n*.ts             # UI catalog (R2 JSON) + dynamic content translation + routing
├── translations.ts      # Machine-translation + translations-table cache
├── api-helpers.ts       # ok()/err()/serverErr() response shapes
├── public-id.ts  slug.ts  rate-limit.ts  require-permission.ts  route-permissions.ts
├── mailer.ts  notify.ts  image-process.ts  locations.ts  license/  ai/  seeds/  …

scripts — Provisioning & Tooling

Script npm command Purpose
init-db.ts db:init Provision base/CMS tables via ensure*Schema()
init-core.ts db:init Provision core channels/settings
seed-*.ts db:seed:* Demo data (lessons, hosts, reviews, media, …)
gen-openapi.ts gen:openapi Regenerate the OpenAPI spec from route handlers
bundle-addons.mjs addons:bundle Regenerate the four product index files
gen-addon-catalog.mjs addons:catalog Regenerate the add-on catalog
reset-template.ts db:reset Reset the template database

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


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