
Arabic AI tutoring platform
Faheem
The real-time layer of an Arabic AI tutor for 200,000+ students: streamed answers, voice-to-voice at ~300–500 ms, and AI-generated lessons — on a 16-module clean architecture.
The challenge
Students needed tutoring that felt live and trustworthy in Arabic — real-time answers, voice, and visuals — not a generic chatbot bolted onto a form. A tutor that pauses to think reads as broken to a fourteen-year-old, so the latency budget was a product requirement, not an optimisation.
What it had to do
- Answers in Arabic that appear as they are generated, not after a pause
- Voice conversation at a ~300–500 ms round-trip that the student can interrupt — and the tutor can't
- AI-generated lessons whose narration, subtitles and diagrams stay in sync
- A full Arabic, right-to-left interface
- Separate Dev, Staging, QA and Prod builds: the Ministry's official app can't be tested against production
My role
Core engineer on the realtime tutoring layer and the app architecture the rest of the product is built on.
How I built it
- Built realtime AI tutoring over WebSocket with Azure OpenAI streaming so answers arrive token by token.
- Engineered a voice-to-voice tutor at ~300–500 ms round-trip with speech-to-text and text-to-speech.
- Built the AI Board session engine: AI-generated lessons rendered as streamed multimodal scenes, synchronising TTS audio, live subtitles, and CustomPainter-animated diagrams into frame-accurate playback per curriculum topic.
- Added an adaptive Smart Quiz with AI-generated questions, and a camera-based Solve feature for step-by-step maths and science problems.
- Structured 16 modules in clean architecture (Data → Domain → Presentation) with Provider, flutter_modular DI, Dio interceptors and dartz Either, plus full Arabic RTL, ~52 analytics events across 14 modules, Crashlytics, FCM, and Dev/Staging/QA/Prod builds.
Decisions, and why
WebSocket, not request/response
A tutor that returns a finished paragraph feels broken even when it is fast — the student stares at a spinner. Streaming over a persistent socket puts the first token on screen in a fraction of the total generation time, and the same connection carries the voice session, so there is one transport to keep alive rather than two.
Native platform audio with VAD thresholds, to stop the model interrupting itself
In voice mode the tutor was reacting to its own output: its speech re-entered the microphone and was transcribed as a new student question. Routing capture and playback through native platform audio and setting voice-activity-detection thresholds for barge-in fixed it — the student can still cut the tutor off mid-sentence, which is what makes it feel like a conversation, but the tutor can no longer cut itself off.
~300–500 ms as a budget, not a target
The round-trip number was fixed first and every layer was built to fit inside it — streaming rather than batching, native audio rather than a plugin chain, and no post-processing between recognition and the model. Treating it as a budget is what kept it from drifting as features landed.
Frame-accurate sync instead of three independent players
A generated lesson plays audio, subtitles, and an animated diagram at once. Driven separately they drift, and a diagram that explains the wrong sentence is worse than no diagram. The Board engine plays them as one timeline, so the drawing, the caption, and the voice stay on the same beat.
Four build environments from the start
An app that is the Ministry of Education's official product cannot be tested against production. Dev, Staging, QA and Prod builds were set up before the feature work, which is why 200,000 students never saw a QA release.
Stack
From the product
Each caption describes what the screen is doing — several of these products have an Arabic-only interface.



See it live
Building something like this?
Tell me what you are trying to ship and I will tell you, honestly, whether I am the right person to build it.
Hire me for the same thing