TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
We know when you're not ready — and get you there by making you teach it.
EducationTypeScript · JavaScriptGitHub @sab333nOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗An AI study assistant that knows a student's deadlines and goals, texts them when they are not ready, and gets them ready by making them teach the material to AI students.
Built for the Nexus Technology Cup (demo: Dec 14, 2026). Core loop: deadline known → readiness measured → plan made → student teaches AI students → readiness updated → next text sent.
| Phase | What | State |
|---|---|---|
| 1 | Onboarding + semester map | Built |
| 2 | Teaching classroom (probe, AI students, teach-back, reflection, voice) | Built |
| 3 | Readiness per topic and per exam, "Up next" on the semester page | Built (weekly plan not started) |
| 4 | Nudges by phone notification (free) or text (Twilio), one-tap links, Later/STOP | Built |
| 5 | Instructor dashboard (consent-based sharing) + demo seed | Built |
Readiness is derived from evidence, never stored: every probe answer, teaching session and teach-back writes a
topic_scores row, and src/lib/readiness.ts weighs them by source and recency (14-day half-life). An exam or quiz
covers the topics its title names plus what they build on; an exam that names none covers the whole course.
Students turn on notifications on the semester page. On Android and desktop that's one tap; on iPhone (iOS 16.4+)
Ready must be added to the home screen first, and the page says how. Notifications carry Teach now and Later
buttons. Push is free and is used whenever a student has allowed it; otherwise Ready falls back to texts (below).
Set NEXT_PUBLIC_VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY (npx web-push generate-vapid-keys); without them pushes
are logged as dry runs.
Once a day (Vercel Cron, vercel.json) Ready checks every student who agreed to texts. If it is inside their texting
hours and an exam or quiz in the next 7 days covers a topic that isn't ready, it texts them a one-tap link that signs
them in and opens a session on that topic. Rules (src/lib/sms/nudge.ts): up to 2 texts a day, never the same test and
topic twice within 20 hours, LATER snoozes until tomorrow, STOP always opts out. Students can also press "Text me now",
and instructors "Send a nudge" on the dashboard (ignores the hour window, still capped). Every text in or out is logged
in sms_messages. Without Twilio settings, texts are logged as dry runs and shown on the semester page.
Twilio setup: set TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM and CRON_SECRET, and point the number's
incoming-message webhook to https://<your-app>/api/sms/inbound (HTTP POST). On a Twilio trial, texts only reach
verified numbers. Vercel Hobby runs cron once a day (22:30 UTC, 5:30pm Central); Pro can run it hourly.
On the dashboard, an instructor picks a topic (Ready suggests the one the class is most confidently wrong about), adds an
optional focus, and clicks Make a video. Gemini writes a 4–6 scene script (prompts/lesson-video.v1.md) from the
topic, course and misconception counts, never from students' notes. Gemini text-to-speech (TTS_MODEL, TTS_VOICE)
records one clip per scene. The browser plays it as narrated slides with captions; a scene without a clip uses the
device's voice. The instructor previews the draft and shares it; students who aren't ready on that topic get a
notification, and everyone in the class sees it on their semester page. The video ends with Teach it back, which
opens a session on the topic. Watching never changes readiness; the dashboard shows who watched, finished, and taught
it back since.
Instructors sign up at /faculty, create a class with its Canvas course code, and get a join code (e.g. PHARM-7KQ2).
A student enters the code on their semester page, sees exactly what will be shared, and agrees. The dashboard shows,
for students whose latest consent is "share": readiness for the next exam, who needs attention and why, topics the class
is confidently wrong about, and a student × topic heatmap. It reads only scores for that course, never notes, files,
transcripts or phone numbers. "Stop sharing" takes effect immediately; every consent change is kept as an audit row.
Demo: npm run seed:demo creates a fictional PHARM 201 class (24 students, exam in four days). Sign in at /faculty
as [email protected] with password ready-demo-2026 (override with DEMO_PASSWORD). Students can join it with PHARM-DEMO.
Needs Node 20.9+ and a Postgres database (local or Supabase).
cp .env.example .env.local # defaults work with local Postgres
createdb ready_dev && createdb ready_test
npm install
npm run db:migrate
npm run fixtures # fake demo calendar + syllabus
npm run dev
Open http://localhost:3000, continue with Google or create an account, finish the chat, then on the next page paste
http://localhost:3000/demo/demo-canvas.ics and upload fixtures/pharm-201-syllabus.pdf.
NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY. Add http://localhost:3000/auth/callback to the Supabase redirect allow list.LLM_PROVIDER=gemini plus GEMINI_API_KEY uses Gemini to read syllabi and screenshots, and to run questions, grading, and the classroom. none uses an offline parser for PDFs; screenshots need the AI reader. anthropic is the Claude alternative.LLM_MODEL, then each of LLM_FALLBACK_MODELS (default gemini-3.5-flash-lite). A model that returns 429/503/404 is skipped for a while, so one exhausted quota doesn't slow every call. If every model fails, each step falls back to the offline engine, and the session keeps going.npm test # unit tests + integration tests against ready_test (TEST_DATABASE_URL)
npm run lint && npm run typecheck
prompts/ versioned LLM prompts (<name>.v<N>.md)
supabase/migrations/ SQL schema, one file per phase
scripts/ migrate, demo fixtures
src/lib/llm/ provider-agnostic LLM interface (Gemini or Claude), model fallback
src/lib/onboarding/flow.ts onboarding state machine (pure, tested)
src/lib/calendar/ics.ts Canvas / Moodle / Blackboard .ics parsing
src/lib/materials/ PDF text, AI extraction, offline parser
src/lib/lesson/service.ts lesson orchestration: probe → teach → teach-back → reflection
src/lib/readiness.ts readiness from evidence; which topics an exam covers (pure, tested)
src/lib/sms/ phone numbers, STOP/START/HELP, Twilio signatures
src/lib/db/repo.ts all SQL, always scoped by student
src/lib/classes/report.ts instructor view: class readiness, at-risk students, misconceptions (pure, tested)
src/lib/db/classes.ts instructors, classes, per-class sharing consent
src/app/ pages: / → /onboarding → /connect → /map → /learn → /session/[id]; /faculty for instructors