// chapter 1
The problem
Live classes are the heart of the course, but joining one was the hardest part: links in chats, wrong meetings, names Zoom couldn’t match to a student, and classes that looked live long after they had ended.
The goal was simple to say: a student opens the app, sees today’s class, taps Join and is in the room. A teacher opens their app and starts the class. Everything else (who attended, what’s next, recordings) should just happen.
// chapter 2
What I built
I owned the whole project: planning, screen design, the Flutter apps for students and teachers, the API behind them and the Zoom integration.
Live classes in the app
Zoom runs inside the app through its Meeting SDK, so students never copy a link or install anything else. The same join flow works on Android, iOS and the web portal.
Teacher app
Teachers sign in with a one-time code, see their dashboard and timetable, and start their class from the phone as the host.
Courses and lessons
Enrolled courses, recorded video lessons with watch progress, notes, assignments and certificates, all in one place.
Sign-in
One-time code by SMS, with tokens that refresh in the background so students stay signed in safely.
Notifications
Push notifications for classes and updates through Firebase.
Exams on the phone
Students take timed exams in the app, with the timer kept by the server and answers saved even on weak connections.
// chapter 3
How joining a class works
- 1The app asks the server if this student can join this class right now (enrolled, and the class is on today and not finished).
- 2The server signs a short-lived join bundle for Zoom. The secret key never leaves the server.
- 3The app opens the meeting inside itself with the student’s name in the format attendance expects.
- 4When the class ends, attendance is already recorded and the class shows as completed.
// chapter 4
The hard parts
- Classes stuck on “live”: if Zoom’s end-of-meeting message was missed, the app kept showing a Join button. The server now works out the real status from several signals, so finished classes show as finished.
- False “class not started” errors: classes started from the teacher’s app report a different status to Zoom’s API. Joining now trusts the class schedule instead of blocking students wrongly.
- Video and Zoom on the web: the browser security settings Zoom needs blocked the embedded lesson videos. I tracked it down and kept both working.
- One join flow everywhere: a single signed bundle serves Android, iOS and the web, so there’s one set of rules to test.
// chapter 5
Results
- Students join live classes in one tap, inside the app, on Android and iOS.
- Teachers start their own classes from their phone.
- Attendance is recorded automatically, with no extra system to run.
- Courses, recordings, exams and live classes live in one app instead of scattered links.
- Flutter
- Android
- iOS
- Zoom Meeting SDK
- Node.js
- Fastify
- MySQL
- Firebase push
- Vimeo
- JWT