Builds/003
Studentify
DeployedAn AI study scheduler that reads your Canvas and texts you a plan
- Logged
- 2025.04
- Timeframe
- 2025
- Role
- Project lead — 3-person team
- Stack
- PythonGemini 1.5 ProCanvas APITelegram Bot APITypeScriptUbuntu VPS
- Source
- —
Photo pending — telegram-chat.jpg
Why I built it
Every generic study planner has the same flaw: you have to tell it everything. Your courses, your deadlines, how you’re doing, what’s hard for you. Nobody maintains that for more than a week — the planner becomes another chore.
But all of that data already exists, sitting in Canvas: course schedules, assignment deadlines, submission history, grades, past exam performance. Studentify’s premise was simple — stop asking students for data their university already has. Read Canvas, reason about it with an LLM, and deliver a plan where students actually look: their messages.
I led a 3-person team to design, build, and deploy it end-to-end.
The stack
Hardware builds get a bill of materials; software builds deserve one too.
Bill of materials
| Item | Qty | Notes |
|---|---|---|
| Canvas API token | 1 per user | Token-based login — the backend only sees what the student authorizes. |
| Gemini 1.5 Pro API | 1 | The planning brain, orchestrated with OpenClaw. |
| Telegram bot | 1 | Delivery channel: daily plans, refinement, study Q&A. |
| Hostinger Ubuntu VPS | 1 | Where the whole stack lives. |
Photo pending — architecture.jpg
Reading Canvas the hard way
The backend is Python, and its first job is authentication: token-based Canvas login, so each student connects with their own access token and the backend only touches what they’ve authorized.
From there it pulls the full academic picture:
- Course schedules — including the gaps between classes, which turn out to be the most valuable study windows students waste
- Assignment deadlines and submission history — what’s due, and whether you’re the type who submits early or at 11:58 PM
- Grades and past exam performance — the signal for which subjects actually need the hours
The interesting engineering was normalization: every course structures its Canvas presence differently, and the pipeline has to turn that mess into one consistent workload model before any AI sees it.
Making Gemini plan like a human
Raw LLM scheduling is bad. Ask a model to “make a study plan” and you get a generic, evenly-spread grid that ignores reality. The work was in the orchestration — we integrated Gemini 1.5 Pro with OpenClaw and fed it a structured picture of the student:
- Grade risk — courses where the current grade is drifting toward trouble get weighted hours
- Weak subjects — inferred from exam history, not self-reporting
- Deadline urgency — a real ranking, not just “sorted by due date”
- Preferred study windows — plans land in the hours the student will actually use, including those between-class gaps
Photo pending — plan-output.jpg
Delivery via Telegram
A plan nobody sees is a plan nobody follows, so delivery went through a Telegram chatbot rather than another dashboard tab:
- Daily schedule delivery — the day’s plan arrives as a message, every morning
- Conversational refinement — “move my physics block to tonight” just works; the bot regenerates around the constraint
- Study Q&A — the same pipeline answers questions with the student’s actual course context behind it
Meeting students inside an app they already check twenty times a day beat every engagement idea we had for a web UI.
Shipping it
The whole stack runs on a Hostinger Ubuntu VPS — Python backend, bot process, and scheduling jobs deployed and kept alive as services. This was the project where “works on my machine” became “survives a server reboot at 3 AM”: process supervision, logs you can actually read, and API failure handling for three external services that each have opinions about rate limits.
We validated it end-to-end with 10+ real users across 3+ live APIs — real Canvas accounts, real deadlines, real plans followed (or ignored, which is also data).
What I’d do differently
- Schema-lock the LLM output from day one. We started with free-text plans and paid for it in parsing bugs. Structured output with validation should have been the first commit, not a refactor.
- Build the feedback loop. We know when plans are delivered; we only anecdotally know when they’re followed. Lightweight completion tracking would turn the scheduler into something that learns.
- Cache Canvas aggressively. Re-pulling course data on every planning cycle was simple but slow and rate-limit-hungry. A sync layer with change detection is the obvious v2 move.