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 |