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
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
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].
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:
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.
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.
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
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.ts → init-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