MedGryd
Planner, question bank, patient simulator, board plan, OMM protocols and grades — one account, built by medical students.
翻译准备中
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Self-hosted, multi-tenant learning management system (LMS) for training institutes and teams: course builder, trainer and student portals, progress tracking. Django + React. Apache-2.0.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗
Screenshots · Quickstart · Editions · Architecture · API · Contributing
TutorLoom is a free, self-hosted learning platform for institutes and training teams. Build structured courses, enrol learners in batches, grade their work and follow their progress, on the web and on Android and iOS.
This repository is the Community edition: free, open source and self-hosted. An Enterprise edition adds advanced modules on top.
| Capability | 🆓 Community | 💎 Enterprise |
|---|---|---|
| Email & password login, invites, password reset | ✅ | ✅ |
| Multi-role accounts with role switching | ✅ | ✅ |
| Institute Admin portal: trainers, students, batches | ✅ | ✅ |
| Bulk upload of trainers & students (CSV / Excel) | ✅ | ✅ |
| Course builder: levels, chapters, resources, tasks, quizzes | ✅ | ✅ |
| Prerequisites & sequential unlocking | ✅ | ✅ |
| Trainer portal: dashboard, grading, learner progress | ✅ | ✅ |
| Student portal & mobile app: dashboard, roadmap, progress | ✅ | ✅ |
| Points & levels | ✅ | ✅ |
| Course completion certificates (PDF) | ✅ | ✅ |
| Branded email notifications | ✅ | ✅ |
| Google & Microsoft sign-in | — | ✅ |
| Coding questions with AI test cases & starter code | — | ✅ |
| Course import/export, quiz bulk upload, drip release | — | ✅ |
| Assessments (MCQ, task, coding) | — | ✅ |
| No-login coding interviews for candidates | — | ✅ |
| Super Admin console, audit logs, organisation branding | — | ✅ |
| Leaderboard, badges, in-app notifications, calendars | — | ✅ |
| Component | Location | Stack |
|---|---|---|
| Backend REST API | repository root | Python 3.13, Django 6, Django REST Framework, Celery |
| Web frontend | frontend/ | React 19, TypeScript, Vite, Tailwind CSS 4 |
| Student mobile app | student_mobile_app/ | Flutter (Android & iOS), learner-only: courses, lessons, tasks, quizzes and progress against the same API |
| Role | What they do | Role in code | Edition |
|---|---|---|---|
| Institute Admin | Runs one organisation: people, batches, courses, progress | org_admin | 🆓 |
| Trainer | Delivers assigned courses, grades work, tracks learners | teacher | 🆓 |
| Student | Follows course roadmaps, submits work, tracks progress | student | 🆓 |
| Super Admin | Platform-wide console for every organisation and user | Django superuser | 💎 |
| External Candidate | Takes a coding interview through a private link, no account needed | — | 💎 |
One account can hold several roles (for example a Trainer who is also an Institute Admin) and switch between portals without signing out.
The fastest way to run everything (Postgres, Redis, the Django API, a Celery worker and the web app) is Docker. Nothing else to install.
git clone https://github.com/pacewisdomhq/TutorLoom.git
cd TutorLoom
docker compose up --build
| Service | URL |
|---|---|
| Frontend | http://localhost:5173 |
| API docs (Swagger) | http://localhost:8010/api/docs/ |
| ReDoc | http://localhost:8010/api/redoc/ |
| Django admin | http://localhost:8010/admin/ |
Source is bind-mounted, so edits on your machine reload in the containers — no rebuild unless dependencies change. Database migrations run automatically on every backend start.
Create the initial organization, default batch, and Org Admin (with superuser/admin panel access) in a single command:
docker compose exec backend python manage.py create_initial_organization \
--name "Acme Academy" --slug "acme-academy" \
--admin-email "[email protected]" --password "SecurePassword123" \
--batch-name "Batch 1"
(This automatically creates the user as an Org Admin and grants superuser/staff privileges so they can access both the LMS and /admin/).
The backend is published on 8010 because 8000 is often taken by another local service. Postgres and Redis are deliberately not published, so they never clash with ones you already run. Override host ports in a .env file next to docker-compose.yml, or inline:
BACKEND_PORT=9000 FRONTEND_PORT=3000 docker compose up
VITE_API_BASE_URL follows BACKEND_PORT automatically.
docker compose logs -f backend # tail a service's logs
docker compose exec backend bash # shell into the API container
docker compose exec backend python manage.py migrate
docker compose down # stop; add -v to also wipe the database
Prerequisites: Python 3.13, Poetry 2.x, PostgreSQL, Redis, Node.js and npm.
1. Install
git clone https://github.com/pacewisdomhq/TutorLoom.git
cd TutorLoom
poetry env use python3.13
poetry install
Prefer pip? python3.13 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
2. Configure
cp .env.example .env
At minimum set SECRET_KEY, the DB_* variables (or DATABASE_URL), REDIS_URL and CELERY_BROKER_URL. See environment variables for the full list.
3. Create the database and first organisation
poetry run python manage.py migrate
poetry run python manage.py create_initial_organization \
--name "Acme Academy" --slug "acme-academy" \
--admin-email "[email protected]" --password "AdminPassword123" \
--batch-name "Batch 1"
This creates the organisation, its first batch and the Institute Admin, who also gets Django admin (/admin/) access. Pass --no-superuser to skip that.
4. Run the backend
redis-server # or: docker run -d -p 6379:6379 redis
poetry run python manage.py runserver
poetry run celery -A lms_core worker -l info # background tasks
5. Run the web app
cd frontend
npm install
cp .env.example .env # set VITE_API_BASE_URL, e.g. http://localhost:8000/api
npm run dev # http://localhost:5173
The full frontend guide lives in frontend/README.md. The mobile app guide, covering Flutter setup, its one environment variable, architecture, and building and releasing, lives in student_mobile_app/README.md.
All settings are read from environment variables (or a .env file). Copy .env.example to get started.
| Variable | Description | Example |
|---|---|---|
SECRET_KEY | Django secret key | change-this-to-a-secure-secret-key |
DEBUG | Debug mode (default False) | True |
ALLOWED_HOSTS | Comma-separated allowed hosts (default *) | localhost,127.0.0.1 |
DATABASE_URL | Full DB URL; overrides the DB_* vars | postgres://postgres:postgres@localhost:5432/lms_db |
DB_NAME | Postgres database name | lms_db |
DB_USER | Postgres user | postgres |
DB_PASSWORD | Postgres password | postgres |
DB_HOST | Postgres host (required unless DATABASE_URL is set) | localhost |
DB_PORT | Postgres port | 5432 |
REDIS_URL | Redis URL for the cache (required) | redis://127.0.0.1:6379/1 |
CELERY_BROKER_URL | Celery broker (required) | redis://127.0.0.1:6379/0 |
CELERY_RESULT_BACKEND | Celery result backend | django-db |
CELERY_TASK_ALWAYS_EAGER | Run tasks inline, with no worker | False |
FRONTEND_URL | Web app URL, used in emails, CORS and CSRF | http://localhost:5173 |
BACKEND_PUBLIC_URL | Public URL of this API | http://localhost:8000 |
CSRF_TRUSTED_ORIGINS | Comma-separated trusted origins | https://app.example.com |
| URL | What |
|---|---|
/api/docs/ | Swagger UI: interactive API reference |
/api/redoc/ | ReDoc |
/api/schema/ | OpenAPI 3 schema |
/admin/ | Django admin |
To try authenticated endpoints in Swagger, call POST /api/auth/login/, click Authorize and paste the access token.
All endpoints require Authorization: Bearer <token> except login, invite and password reset. Lists are paginated at 20 items per page.
| Area | Endpoints |
|---|---|
| Auth | POST /api/auth/login/ · refresh/ · logout/ · forgot-password/ · reset-password/ · accept-invite/ · GET verify-invite/ |
| Profile | GET/PATCH /api/users/me/ · POST /api/users/<id>/reinvite/ |
| Roles | /api/roles/ · /api/user-roles/ · update-role/ · delete-role/ |
| Organisation | /api/organizations/<org>/ · members/ · staff/ · batches/ · batches/<b>/students/ · students/ · …/bulk-upload-file/ · …/download-template/ |
| Dashboards | …/<org>/analytics/overview/ · …/batches/<b>/analytics/ · …/students/me/dashboard/ · …/teacher-dashboard/<teacher>/ · …/batches-overview/ |
| Course builder | /api/organizations/<org>/courses/ → modules/ → nodes/ · nodes/<n>/content/ |
| Learning | …/courses/<c>/roadmap/ · …/my-courses/ · …/my-progress/ · POST /api/nodes/<n>/complete/ |
| Submissions | /api/nodes/<n>/submit/ · task/submit/ · task/result/ · task/all-submissions/ · /api/quizzes/<q>/submit/ |
| Grading & progress | …/pending-evaluations/ · …/submissions/tasks/<s>/review/ · …/learner-progress/ · …/learner-progress/export/ · …/node-submission-details/ |
For architecture details, multi-tenancy flowcharts and the full endpoint reference, see PROJECT_OVERVIEW.md.
| Area | Technology |
|---|---|
| Backend | Python 3.13, Django 6, Django REST Framework 3.16 |
| Auth | JWT via djangorestframework-simplejwt (rotating refresh tokens with blacklist) |
| Database | PostgreSQL |
| Cache & jobs | Redis, Celery, django-celery-results |
| Storage | Local filesystem or Amazon S3 (django-storages) |
| Amazon SES, with a fallback to any Django mail backend | |
| Spreadsheets | pandas, openpyxl, xlrd (bulk uploads and Excel exports) |
| API docs | OpenAPI 3 via drf-spectacular (Swagger UI and ReDoc) |
| Web frontend | React 19, TypeScript, Vite, React Router, Tailwind CSS 4 |
| Mobile | Flutter (Dart 3.13), MVVM + Provider, go_router, Dio, Hive |
| Tests | pytest, pytest-django, pytest-cov (backend) · Vitest (frontend) · flutter test (mobile) |
.
├── lms_core/ # Settings, root URLs, Celery app, email & storage utilities, soft-delete base model
├── accounts/ # Users (email login), JWT auth, invites, password reset, profile
├── rbac/ # Roles, role assignments, permission classes
├── organizations/ # Organisations, staff, batches, students, bulk upload, bootstrap command
├── curriculum/ # Courses, levels, chapters, steps, resources, tasks, quizzes, submissions, progress
├── analytics/ # Admin / trainer / student dashboards and daily metrics
├── gamification/ # Points & levels
├── settings/ # Shared Amazon SES client
├── frontend/ # React 19 + TypeScript + Vite web app (docs: frontend/README.md)
├── student_mobile_app/ # Flutter learner app for Android and iOS (docs: student_mobile_app/README.md)
├── Dockerfile # Backend API image
├── docker-compose.yml # Full local stack: Postgres, Redis, API, Celery worker, frontend
├── pyproject.toml # Poetry dependencies + pytest / coverage config
└── requirements.txt # pip dependencies (used by the Dockerfile)
Each backend app has its own README.md with deeper notes. The frontend is documented in frontend/README.md and the mobile app in student_mobile_app/README.md.
Backend tests need a running PostgreSQL; Redis, S3 and Celery are stubbed automatically.
poetry run pytest -p no:cacheprovider --no-cov -q # fast run
poetry run pytest # with coverage (terminal + coverage.xml)
poetry run pytest curriculum/ --no-cov -q # a single app
Frontend tests and lint:
cd frontend
npm test # Vitest
npm run lint # ESLint
docker build -t tutorloom-backend .
docker run -d -p 8000:8000 --env-file .env tutorloom-backend
[!IMPORTANT] The image starts Django's development server. In production, run
gunicorn lms_core.wsgi:application --bind 0.0.0.0:8000(already installed) behind a TLS-terminating proxy.
DEBUG=False, a strong SECRET_KEY, and explicit ALLOWED_HOSTS, FRONTEND_URL and CSRF_TRUSTED_ORIGINS.USE_S3=True for uploads and SES credentials for email.analytics.tasks.calculate_daily_analytics yourself; no beat schedule ships with the project.npm run build in frontend/) that you deploy separately.Planned (Enterprise)
Proposed (edition not yet decided)
| Area | Ideas |
|---|---|
| AI | AI feedback drafts for trainers · chapter-scoped AI tutor chat · code plagiarism / similarity check |
| Learning content | SCORM / xAPI import · native video hosting with watch progress · discussion threads per chapter |
| Assessment depth | Advanced proctoring · question bank with tags & random pools · rubric grading · skill-wise score breakdown |
| Reporting & compliance | Mandatory training compliance tracking · data export, account deletion & retention (GDPR / DPDP) |
| Platform | Custom subdomains & white-label email · subscription plans & usage limits · public API keys & webhooks · SAML SSO / SCIM · PWA with offline reading |
| Learner experience | Course catalogue with self-enrolment · learning paths across courses · notes & bookmarks · multi-language UI |
Contributions are welcome, especially for the 🚧 Community items and the roadmap. Please read CONTRIBUTING.md and our Code of Conduct first.
makemigrations --check runs in the test suite).<app>/tests/ (or next to the component in frontend/) and make sure poetry run pytest and npm test pass.Need help? See SUPPORT.md. Found a security issue? Please report it privately as described in SECURITY.md.
Licensed under the Apache License, Version 2.0. See NOTICE for attribution details.
TutorLoom is built and maintained by Pace Wisdom Solutions
Copyright © 2026 Pace Wisdom Solutions Pvt. Ltd.
If this project helps you, consider giving it a ⭐ on GitHub.
CORS_ALLOWED_ORIGINS | Extra comma-separated CORS origins | https://app.example.com |
CORS_ALLOW_ALL_ORIGINS | Allow any origin | False |
DEFAULT_FROM_EMAIL | Sender address | [email protected] |
AWS_SES_ACCESS_KEY_ID | SES key. If empty, email goes through EMAIL_BACKEND | (empty) |
AWS_SES_SECRET_ACCESS_KEY | SES secret | (empty) |
AWS_SES_REGION | SES region | ap-south-1 |
EMAIL_BACKEND | Fallback mail backend (default: console) | django.core.mail.backends.console.EmailBackend |
EMAIL_HOST / EMAIL_PORT / EMAIL_USE_TLS | SMTP server settings | smtp.gmail.com / 587 / True |
EMAIL_HOST_USER / EMAIL_HOST_PASSWORD | SMTP credentials | [email protected] / app-password |
USE_S3 | Store uploads on S3 instead of ./media/ | False |
AWS_S3_ACCESS_KEY_ID / AWS_S3_SECRET_ACCESS_KEY | S3 credentials | AKIA... / ... |
AWS_STORAGE_BUCKET_NAME | S3 bucket | lms-media |
AWS_S3_REGION_NAME | S3 region | ap-south-1 |
USE_AWS_SECRETS | Load settings from AWS Secrets Manager | False |
AWS_SECRETS_NAME | Secret name | lms/prod |
AWS_REGION_NAME | Secrets Manager region | ap-south-1 |
TEST_IP | (tests only) IP used by the test suite | 127.0.0.1 |