Folder Structure
This document maps the real folder layout of EduNest LMS 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).
Repository Root
edunest-lms-web/
├── src/ # All application code (see below)
├── scripts/ # DB init/seed scripts + add-on 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* functions)
├── next.config.ts # Next.js config (image domains, etc.)
├── tailwind.config.ts # Tailwind CSS 3 config
├── tsconfig.json # TypeScript config (@/* path alias → src/*)
├── vercel.json # Vercel deployment config
├── package.json # Scripts: dev/build, db:init*, db:seed*, addons:*
└── .env / .env.local # DATABASE_URL, JWT_SECRET, SECRET_KEY, R2_*, …
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 (93) + GENERATED aggregation indexes
├── lib/ # DB client, schema (*-schema.ts), auth, r2, secrets, queries, helpers
├── components/ # Shared React UI (admin, learn, 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
├── docs/ # In-app documentation (content/*.md — these files)
└── proxy.ts # (inactive) proxy helper
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].
src/app/
├── layout.tsx # Root layout (fonts, providers, global shell)
├── (site)/ # PUBLIC website + storefront → /
│ ├── layout.tsx
│ ├── page.tsx # Home
│ ├── courses/ # Catalog + course detail
│ ├── bundles/ # Bundle pages
│ ├── instructors/ # Instructor directory
│ ├── blogs/ gallery/ faq/ about/ contact/
│ ├── cart/ checkout/ membership/
│ └── privacy-policy/ terms-and-conditions/ cookie-policy/ …
├── (auth)/ # Learner/instructor 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/ courses/ customers/ orders/ revenue/
│ ├── blogs/ pages/ gallery/ testimonials/ hero-slider/ faqs/
│ ├── learning/ quizzes/ surveys/ tasks/ reviews/ media/
│ ├── subscriptions/ plan-changes/ marketing/ leads/ apps/ settings/ …
├── learner/ # LEARNER portal → /learner/*
│ ├── dashboard/ my-courses/ my-bundles/ progress/ grades/ analytics/
│ ├── messages/ my-mentor/ calendar/ orders/ subscriptions/
│ ├── wishlist/ addresses/ notifications/ account/ profile-summary/
├── instructor/ # INSTRUCTOR portal → /instructor/*
│ ├── organization/ enrollments/ tasks/ messages/ settings/
├── learn/ # Course player → /learn/[slug]
│ └── [slug]/page.tsx
├── install/ # First-run setup wizard → /install
├── docs/ # In-app buyer docs → /docs/[version]
├── api-docs/ # OpenAPI viewer
├── files/ # File proxy
└── api/ # HTTP API (route handlers — the backend)
├── v1/ # Versioned resource handlers (see below)
├── install/ # Installer endpoints
├── license/ # License activation / status
└── openapi.json/ # OpenAPI document
src/app/api — The API
Every route.ts is an endpoint; there are 256 of them. The versioned surface lives
under src/app/api/v1 with one folder per resource:
api/v1/
├── admin/ # Admin-only resource handlers (courses, customers, orders, settings, …)
├── portal/ # Learner/instructor portal endpoints
├── instructor/ # Instructor-specific endpoints
├── courses/ course-categories/ coupons/ gift-cards/ checkout/ # Catalog + commerce
├── blogs/ pages/ faqs/ gallery/ hero-slides/ testimonials/ # CMS
├── learn/ exams/ analytics/ # Learning + assessment
├── chat/ chatbot/ livechat/ calendar-config/ captcha/ video/ # Integration channels
├── countries/ languages/ locations/ tax-config/ brand/ i18n/ # Reference data
├── forms/ app-version/ plugins/ cron/ ext/ # Misc + automation
src/core — Reusable Framework
Stable contracts and registries that the app reads at runtime. Add-ons plug into these.
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(), client-builtins.ts
├── 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
The 93 built-in add-ons plus the generated aggregation indexes.
src/product/
├── addons/ # 93 add-on packages, one folder each
│ ├── certificates/ # Feature add-on: addon.json, index.ts, schema.ts, api.ts, *.tsx
│ ├── gamification/ # Feature add-on (points, badges, rules)
│ ├── exams/ assignments/ forums/ organizations/ affiliate/ wallet/ …
│ ├── payments-stripe/ # Provider add-on: channel + payment driver
│ ├── payments-razorpay/ email-sendgrid/ analytics-clarity/ video-mux/ …
│ └── 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 coreCHANNELS), - emits
ADDON_FEATURES(add-ons flaggedfeature: true→ exposed asFEATURES), - emits
ADDON_SERVER_ADAPTERSandADDON_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
human/machine-readable add-on catalog under docs/add-ons. 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()
├── vendor-schema.ts # Commerce/store/users/settings ensure* functions
├── lms-schema.ts # Courses/lessons/enrollments/instructors/commerce ensure*
├── auth-schema.ts leads-schema.ts groups-schema.ts calendar-schema.ts
├── auth.ts # Admin JWT (jose, HS256) + admin_token cookie
├── customer-auth.ts # Learner/instructor 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 cuid-like public ids
├── license/ # index.ts, licenseClient.ts, addons.ts (RS256 offline verify)
├── seeds/ # faqs.ts, pages.ts, settings.ts, message-templates.ts
├── queries.ts lms-queries.ts permissions-catalog.ts coupons.ts giftcards.ts
├── image.ts mailer.ts video.ts drip.ts i18n.ts locations.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-vendor.ts |
db:init:vendor |
Run ensureAllVendorTables() (commerce/store/settings) |
init-lms.ts |
db:init:lms |
Run ensureLmsSchema() + seed starter course categories |
seed-*.ts |
db:seed:core, … |
Demo/test data (courses, instructors, learners, surveys…) |
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 |
reset-template.ts |
db:reset |
Reset the template database |
npm run db:init chains init-db.ts → init-vendor.ts → init-lms.ts, fully
provisioning a fresh database by calling the same ensure*() functions the API routes
use at request time.
© CreativeCape Solutions · creative-cape.com · support@creative-cape.com