An open-source Learning Management System built with Next.js and FastAPI
Demo · Features · Quick Start · Docker · Contributing
Learnora is a full-featured, multi-tenant LMS you can self-host or deploy to any cloud provider. Each organisation gets its own isolated workspace, login URL, and role-based access control. Built for real educational workflows — not demos.
Seed a local instance in under a minute:
cd src/backend && python seed.pyThen open http://localhost:3000/stu and log in with:
| Role | Password | |
|---|---|---|
| Admin | admin@stu.edu |
Admin@123 |
| Faculty | faculty1@stu.edu |
Faculty@123 |
| Student | student1@stu.edu |
Student@123 |
The seed creates Sehas Technical University (
/stu) with 1 admin, 5 faculty, 20 students, 5 courses, and sample assignments.
- Each organisation has an isolated workspace accessed via its own slug (
/stu,/acme, etc.) - Admin-controlled member invitations with email-domain restriction
- Per-organisation plan and user limits
| Role | Capabilities |
|---|---|
| Admin | Manage members, verify org, view all courses |
| Faculty | Create/publish courses, modules, assignments; grade submissions |
| Student | Enrol, submit work, discuss, view grades |
- Drag-order modules and lessons (text + video)
- File uploads with MIME-type tracking
- Publish/draft toggles per module and course
- 6 submission types: text, code (with syntax highlight), file upload, URL, quiz (MCQ + short answer), and mixed
- Configurable due dates and point values
- Plagiarism flag field on submissions
- AI Tutor: context-aware chat powered by Groq (
llama-3.3-70b-versatile) - AI Grading: one-click grade + feedback suggestions for faculty reviewers
- KaTeX for inline and block math expressions
- Mermaid for flowcharts and sequence diagrams
- Recharts for function plots and data visualisations
- GitHub Flavored Markdown throughout
- Per-course gradebook with grade matrix
- Submission history and feedback trail
- Quiz auto-scoring with manual override
- Threaded course discussions with reply support
- Pin important announcements
- Invitation and verification emails via SMTP
- Falls back to console output when SMTP is not configured (great for local dev)
| Layer | Technology | Version |
|---|---|---|
| Frontend | Next.js (App Router), TypeScript | 15 / 5 |
| Styling | Tailwind CSS | 4 |
| Backend | FastAPI, Pydantic v2 | 0.115 / 2.9 |
| ORM | SQLAlchemy | 2.0 |
| Database | PostgreSQL (Supabase recommended) | 16 |
| Auth | JWT (python-jose) + bcrypt | — |
| AI | Groq API — llama-3.3-70b-versatile |
— |
| File uploads | Local filesystem (configurable path) | — |
| Containerisation | Docker + Docker Compose | — |
- Node.js 20+
- Python 3.11+
- PostgreSQL database — Supabase free tier works perfectly
- Groq API key — free at console.groq.com
git clone https://github.com/Sehastrajit/Learnora.git
cd Learnoracd src/backend
# Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate # macOS / Linux
.venv\Scripts\activate # Windows PowerShell
pip install -r requirements.txt
# Configure environment
cp .env.example .env
# Edit .env — fill in DATABASE_URL and SECRET_KEY at minimumStart the backend:
uvicorn main:app --reload --port 8000Interactive API docs are available at http://localhost:8000/docs.
cd src/frontend
npm install
cp .env.example .env.local
# NEXT_PUBLIC_API_URL=http://localhost:8000 (already the default)Start the frontend:
npm run devThe app is running at http://localhost:3000.
cd src/backend
python seed.pyLogin at http://localhost:3000/stu.
The fastest way to run Learnora locally with no setup:
# 1. Copy and fill in environment files
cp src/backend/.env.example src/backend/.env
cp src/frontend/.env.example src/frontend/.env.local
# Edit both files — DATABASE_URL and SECRET_KEY are required
# 2. Build and start all services
docker compose up --build
# 3. (optional) seed demo data in another terminal
docker compose exec backend python seed.py| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Backend API | http://localhost:8000 |
| API Docs | http://localhost:8000/docs |
See SUPABASE_DOCKER_SETUP.md for Supabase-specific configuration (Transaction Pooler URL, IPv6 notes).
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string. Use the Transaction Pooler URL from Supabase (port 6543) to avoid IPv6 issues. |
SECRET_KEY |
Yes | JWT signing secret — minimum 32 random characters. Generate: python -c "import secrets; print(secrets.token_hex(32))" |
ACCESS_TOKEN_EXPIRE_MINUTES |
No | Token lifetime in minutes. Default: 10080 (7 days). |
GROQ_API_KEY |
No | Groq API key — required only if you want AI Tutor and AI Grading features. |
UPLOAD_DIR |
No | Directory for user file uploads. Default: uploads. |
APP_URL |
No | Frontend base URL used in email verification links. Default: http://localhost:3000. |
SMTP_HOST |
No | SMTP host. Leave blank to print email links to the console instead. |
SMTP_PORT |
No | SMTP port. Default: 587. |
SMTP_USER |
No | SMTP username. |
SMTP_PASS |
No | SMTP password. |
FROM_EMAIL |
No | Sender address for outgoing emails. |
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_API_URL |
Yes | Backend URL. Default: http://localhost:8000. |
NEXT_PUBLIC_SUPABASE_URL |
No | Only needed if using the Supabase JS client directly. |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
No | Only needed if using the Supabase JS client directly. |
Learnora/
├── src/
│ ├── backend/
│ │ ├── main.py # FastAPI app, CORS, router registration
│ │ ├── models.py # SQLAlchemy ORM models
│ │ ├── schemas.py # Pydantic v2 request/response schemas
│ │ ├── auth.py # JWT creation/validation, bcrypt helpers
│ │ ├── database.py # Engine, session factory
│ │ ├── dependencies.py # get_current_user, require_faculty, require_admin
│ │ ├── email_service.py # SMTP sender with console fallback
│ │ ├── seed.py # Demo data generator
│ │ ├── requirements.txt
│ │ ├── .env.example
│ │ ├── Dockerfile
│ │ └── routers/
│ │ ├── ai.py # AI chat + grading (Groq)
│ │ ├── assignments.py # Assignment CRUD, submissions, grading
│ │ ├── auth.py # Register, login, /me
│ │ ├── courses.py # Course CRUD, enrolment, gradebook
│ │ ├── discussions.py # Threads and replies
│ │ ├── files.py # Upload, list, download, delete
│ │ ├── modules.py # Module + lesson CRUD
│ │ ├── organizations.py # Org registration, verification, invitations
│ │ └── users.py # User management
│ └── frontend/
│ ├── app/ # Next.js App Router pages
│ │ ├── page.tsx # Landing page
│ │ ├── dashboard/ # User dashboard
│ │ ├── courses/ # Course listing and detail
│ │ ├── ai/ # AI Tutor interface
│ │ ├── calendar/ # Schedule view
│ │ ├── admin/ # Admin panel
│ │ └── [org]/ # Dynamic org login page
│ ├── components/
│ │ ├── layout/ # AppLayout, Sidebar
│ │ └── ui/ # CourseCard, Modal, Badge, MdMessage, …
│ ├── contexts/
│ │ └── AuthContext.tsx # Auth state, token, role helpers
│ ├── lib/
│ │ ├── api.ts # Typed HTTP client
│ │ └── types.ts # Shared TypeScript interfaces
│ ├── .env.example
│ └── Dockerfile
├── docker-compose.yml
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── SECURITY.md
└── LICENSE
The backend exposes a fully documented REST API. Once the backend is running, open:
- Interactive docs (Swagger UI): http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
| Prefix | Description |
|---|---|
/api/auth |
Register, login, current user |
/api/organizations |
Org lifecycle, members, invitations |
/api/users |
User management |
/api/courses |
Course CRUD, enrolment, gradebook |
/api/modules |
Modules and lessons |
/api/assignments |
Assignments, submissions, grading |
/api/discussions |
Threads and replies |
/api/files |
File upload and management |
/api/ai |
AI chat and AI grading |
The items below are planned but not yet implemented. Contributions are especially welcome here.
- Real-time notifications (WebSocket)
- Video hosting integration (Bunny.net / Cloudflare Stream)
- S3-compatible file storage backend
- SCORM / xAPI content import
- LTI 1.3 tool consumer support
- Mobile-responsive redesign
- Dark mode
- Public course catalogue (unauthenticated browsing)
- Stripe integration for paid courses
- Alembic migration workflow documentation
- End-to-end test suite (Playwright)
- CI/CD pipeline (GitHub Actions)
Have an idea not listed? Open a feature request.
Contributions of all kinds are welcome — bug fixes, new features, documentation improvements, or translations.
Please read CONTRIBUTING.md before opening a pull request. It covers:
- Development environment setup
- Branch naming conventions
- Commit style
- How to run the project locally for development
- PR review process
For major changes, open an issue first to discuss the approach.
If you discover a security vulnerability, please follow the responsible disclosure process described in SECURITY.md. Do not open a public issue.
MIT © 2025 Sehastrajit