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

TEXT
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

TEXT
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].

TEXT
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:

TEXT
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.

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(), 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.

TEXT
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 core CHANNELS),
  • emits ADDON_FEATURES (add-ons flagged feature: true → 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 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

TEXT
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.tsinit-vendor.tsinit-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