BookNook was a research and engineering collaboration with SFU Linguistics, and the software itself was the research output. We built a platform that lets students in multilingual classrooms read the same content in the language they are strongest in, including languages that are usually ignored by edtech tools. I served as product owner across five two-week sprints while also contributing implementation work.
What it's built with.
Frontend
- Next.js 14
- TypeScript
- Tailwind CSS
- PWA / Offline
- WCAG Accessibility
Backend
- FastAPI
- Python
- SQLAlchemy
- Async Pipelines
- State Machine Logic
Database
- PostgreSQL
ML & Translation
- Meta NLLB
- Edge TTS
- Matcha-TTS
- PyMuPDF / OCR
- Groq API
- LLM Integration
Testing & DevOps
- Pytest
- Vitest
- Playwright
- Docker
- GitHub Actions
Process & Delivery
- Agile / Scrum
- Product Ownership
- MkDocs
The non-code parts.
How it works.
Project context
BookNook is a multilingual reading platform built with SFU Linguistics for K-12 classrooms where students do not all share the same first language. Teachers upload one book, and students can read that same content in the language they are strongest in.
The platform itself was the research contribution. We built it as a seven-person team over five two-week sprints, and I worked as product owner while also contributing implementation work.
Reading pipeline
When a teacher uploads a book, it goes through a five-stage async pipeline — upload, OCR extraction (via PyMuPDF), a review gate where the teacher can fix any OCR mistakes, translation, then it's ready for students. Each stage can fail independently and the book just stops at that point instead of breaking everything downstream.
Translation runs through Meta's NLLB model, which supports over 200 languages including some that basically no classroom tech handles — Pashto, Somali, Amharic. The catch with NLLB is that loading it takes about 20 seconds. We cache it module-level as a singleton, so the first request pays the cost and everything after that is near-instant.
Audio + karaoke reading support
Each sentence gets rendered to audio via Edge TTS (fast, gives you word boundaries) with Matcha-TTS as a fallback (better quality for English). Word-level timing comes out of the TTS boundary events, which the frontend uses to drive karaoke-style highlighting as the audio plays. For languages where we can't get real boundaries, we fall back to a proportional estimate so the highlighting still works — it's not pixel-perfect but it's better than nothing.
Adaptive quiz system
After you finish a chapter, the app can generate a quiz. Questions come from the Groq API, prompted with child-focused instructions and broken into three difficulty tiers that map loosely onto Bloom's taxonomy — retrieval, comprehension, synthesis. The quiz system checks eligibility before letting you take it: have you read enough of the book, have you used up your attempts, are you still in a cooldown from the last one. That state machine lives in the backend so students can't cheat it by refreshing.
For teachers, there's an analytics dashboard that does sliding-window comparisons — your class's average score over the last 28 days versus the 28 days before that, per-student deltas so a teacher can spot who's trending down and check in before it becomes a problem.
Frontend and accessibility choices
The frontend is Next.js 14 with Tailwind. Accessibility was actually a real constraint given the user base — WCAG compliance, OpenDyslexic font as an option, high-contrast mode, dark mode, and PWA offline support so a student on a flaky connection can still finish a chapter they'd already loaded.
The repo totals about 40,000 lines across 446 commits from seven contributors, with 80% test coverage enforced in CI. Tests split across Pytest for the backend, Vitest for frontend units, and Playwright for end-to-end flows.
The things I'm proudest of.
- ▹The platform itself is the research contribution. Delivered as a seven-person collaborative team effort for the Simon Fraser Dept. Linguistics: scoped, prioritized, and shipped 300+ user stories across 5 two-week sprints, enabling K-12 students in linguistically diverse classrooms to read in 200+ languages including low-resource languages (Pashto, Somali, Amharic).
- ▹Architected a FastAPI backend (14,000+ lines Python, SQLAlchemy ORM) with a 5-stage asynchronous PDF processing pipeline (upload, OCR extraction via PyMuPDF, confidence-threshold review gating, translation, ready); integrated Meta's NLLB model with singleton lazy-loading to cut translation cold-start from 20s to near-zero; synchronized Edge-TTS audio with karaoke-style word-level highlighting across 200+ language pairs.
- ▹Built an LLM-powered adaptive quiz system (Groq API) generating questions across 3 Bloom's taxonomy difficulty tiers; enforced quiz eligibility via a state machine gating on reading progress, per-user attempt caps, and cooldown windows; delivered teacher analytics dashboards with sliding-window class performance deltas and per-student improvement trend lines.
- ▹Shipped a full monorepo (18,000+ lines across 446 commits, 7 contributors): Next.js 14 frontend with Tailwind, WCAG-compliant accessibility (OpenDyslexic font, high contrast, dark mode), and PWA offline support; 88 test files (Pytest, Vitest, Playwright) enforcing 80% coverage; MkDocs documentation; GitHub Actions CI/CD with required PR reviews.