Technology stack
The pupil’s browser records audio. Cloudflare hosts the app and stores its data, while RunPod processes speech on a GPU. Each layer below explains the tools we use and what the choice costs us.
From a pupil’s voice to teacher review
Phil-IRI · Grades 4–6English and FilipinoSteps 1–7 follow one recording
- A pupil records a Phil-IRI passage in the READSmart web app on a phone or tablet.
- The browser uploads the audio straight to private Cloudflare R2 through a short-lived signed link from the Worker API.
- The Worker, which runs the Next.js app through OpenNext, saves the recording in D1 with Drizzle and queues a processing job.
- The Queue wakes RunPod Serverless. The GPU worker leases the job through the Worker API, where D1 holds the lease, and receives a signed link to the audio with the reference passage.
- On RunPod, Silero VAD finds speech, OpenAI Whisper transcribes it, WhisperX aligns the words to the audio, JiWER compares the transcript with the passage, and exported coefficients calibrate WCPM, with grade and language as required features.
- The GPU posts its results to protected Worker API endpoints and the Worker writes them to D1. The GPU never opens D1 directly.
- The Worker reads the result from D1 for the teacher dashboard, where a teacher reviews it.
The web app
Pupil’s phone or tablet · teacher’s browser
Hosting, data & storage
Cloudflare · the Worker controls access
Getting a recording processed
Cloudflare to RunPod
Step 4. Wake RunPod; lease the job
A Queue delivery wakes RunPod Serverless. The GPU worker leases the job through the Worker API; D1 holds the lease.
Maintains jobs and retention, retries eligible work and wakes RunPod while jobs remain.
Speech processing & measurement
RunPod Serverless GPU: Python, PyTorch and CUDA in a Docker image
Step 5. Transcribe, align, score and calibrate
Whisper’s model size is a configuration value, chosen by experiment.
Silero VADFind speech
OpenAI Whisper
Transcribe
- WhisperX
Align words to the audio
JiWER
Compare with the passage: WER and raw WCPM
- WCPM calibration
Exported coefficients; grade and language are required features
Compares Whisper model sizes, fits the WCPM calibration with scikit-learn and checks agreement with ICC and Bland–Altman. Its exported coefficients feed the calibration stage.
Step 6. Write the results
The Worker writes the results to D1. The GPU never opens D1 directly.
Step 7. A teacher reviews the result
The dashboard shows the measurements beside the recording. Word highlighting is an unvalidated assistive comparison; the teacher decides.
Alongside assessment
Practice stories and releases run separately from the recording path.
Original practice & illustrations
Worker API to Workers AI, through AI Gateway except the picture call
Stories and comprehension questions
Queues the pupil's request; the story is made in the background while a progress bar shows each step.
Writes the passage, rewriting until it fits the grade's word and readability ranges.
Labels the passage, flags unchecked facts for the teacher and writes the questions.
Passage covers
Draws the scene in the style of two sample covers, a new pair each time. Sent straight to Workers AI: the gateway cannot take its multipart input.
Checks safety, fit and style; a rejected cover is drawn again, up to three tries.
R2Private, version-linked covers
Teacher approvalApproved readings and covers become available to pupils.
Building & checking the application
Tests, builds and release
TypeScript, ESLint, Vitest and Playwright check each change. Workers Builds builds the main branch from GitHub and deploys it.
The web app
Browser + Cloudflare Workers
One responsive web app serves pupils, teachers, and administrators. The browser handles recording and interaction; server code checks access and coordinates the work.
Next.js 16, React 19 & TypeScript
- Next.js App Router provides pages, server rendering, and API route handlers. React builds the interface, while TypeScript checks the shapes of data shared across the web application.
Tailwind CSS 4 & custom CSS
- Tailwind supplies layout and styling utilities through PostCSS. Shared CSS defines READSmart’s colors, typography, reading layouts, and responsive components.
PWA & browser APIs
- A web app manifest and service worker support the PWA. MediaRecorder captures microphone audio; IndexedDB holds pending classroom submissions for retry when a connection returns. Speech recognition still needs the server.
- Trade-off
- A shared web app reduces separate device-specific builds, but microphone support, browser storage, and connectivity still vary across devices.
Hosting, data & storage
Cloudflare
The application, structured records, and stored audio have distinct responsibilities. This keeps large recordings out of the database and access decisions in the API.
Workers & OpenNext
- OpenNext adapts the Next.js application to Cloudflare Workers. Workers serve the application and its API; static assets deliver the built browser files.
D1 & Drizzle ORM
- Cloudflare D1 stores SQLite tables for accounts, classrooms, passages, jobs, and results. Drizzle gives the TypeScript application typed queries and a shared schema; Drizzle Kit generates SQL migrations.
- Trade-off
- This arrangement uses one hosting platform for the web services, but it depends on Cloudflare bindings, service limits, and deployment tooling. Audio and database retention must be coordinated.
Getting a recording processed
Cloudflare → RunPod → Worker API
Uploading audio and analysing it are separate steps. A durable job record lets the system track processing, recover interrupted work, and return results to the right recording.
Queues & D1 job leases
- A Cloudflare Queue delivery wakes the RunPod endpoint. The GPU worker claims an eligible job through the Worker API; D1 holds the authoritative job state and processing lease.
- Trade-off
- Results are asynchronous. Queue time, GPU startup, and processing add delay; retries and leases are needed when either service is interrupted.
Speech processing & measurement
RunPod Serverless GPU + local research environment
GPU compute handles the work that would be too demanding for a pupil’s phone. The RunPod handler reuses the Python processing pipeline, which can also run as a local polling worker.
Python, Docker, PyTorch & CUDA
- A Docker image packages the pipeline and its audio tools for RunPod Serverless. PyTorch uses CUDA on the GPU. FFmpeg converts audio; SoundFile supports audio input, output, and duration measurement.

Silero VAD, OpenAI Whisper & WhisperX
- Silero VAD detects speech regions. OpenAI Whisper transcribes the recording, and WhisperX aligns words with audio timestamps. Whisper model size is configurable and evaluated through the model-size experiment.
JiWER & recording-level scoring
- JiWER supports word error rate measurement. The pipeline compares the transcript with the reference passage and calculates raw reading measurements. Word highlighting is an unvalidated assistive view of differences, not mispronunciation detection.
scikit-learn, NumPy, pandas & Pingouin- The research workflow uses these tools for feature preparation, calibration regression, and agreement analysis. Grade and language are required calibration features. Runtime WCPM correction uses exported coefficients when applicable; it does not train a new model for each reading. Continuous agreement is assessed with ICC and Bland–Altman analysis.
- Trade-off
- GPU processing introduces compute cost and startup time. Transcripts, alignment, and calibrated measurements can still be wrong, so teachers retain final judgement.
Original practice & illustrations
Cloudflare Workers AI
Practice generation is a separate AI workflow from oral-reading assessment. It creates draft reading material and artwork within consent, school-policy, and usage limits.
Mistral Small 3.1, Llama 3.3 & Llama Guard 3
- Workers AI runs Mistral Small 3.1 24B to write each passage as plain text, rewriting until it fits the grade's word and readability ranges; in our September 2026 tests it kept to a word count and wrote natural Filipino where Llama 3.3 70B wrote 8–45 words when asked for 55–200. Llama 3.3 70B then labels the passage in JSON mode, reviews its facts and writes the comprehension questions; Llama Guard 3 8B moderates. Fact-review findings are flagged for the approving teacher rather than discarding the story.
FLUX.2 [klein] 9B & Llama 4 Scout
- FLUX.2 [klein] 9B draws each passage cover from a literal scene written by the labelling step, with two of four READSmart sample covers sent as style references. The pair changes with every picture, and the prompt asks for new characters and a new setting, because with a plain style request the model redrew a reference's family and room. It replaced FLUX.1 Schnell, whose text-only brief gave flatter pictures than the site's artwork; a picture now costs about $0.016 instead of $0.002. FLUX.2 takes multipart input, which AI Gateway cannot receive from the Workers binding, so the picture call goes straight to Workers AI and READSmart counts it in its own usage records. Llama 4 Scout reviews each image against the reading for child safety, faithfulness and style. A rejected image is drawn again, up to three tries within the image limits, and a teacher can ask for a new picture later. Version-linked artwork is stored privately in R2.
Cloudflare Queues & background jobs
- A story request returns at once: the Worker reserves it and queues it, and the queue consumer writes, checks and saves the story in the background, recording each stage (writing, checking, saving, questions, picture). Pupils see a progress bar and, on Stories and Home, a notice when the story is ready or waiting for the teacher, even after leaving the page.
AI Gateway & review controls
- Cloudflare AI Gateway provides inference observability and spending controls for the text and review calls. Application quotas and budget reservations bound every call, including the pictures that bypass the gateway, and generated readings require teacher approval before pupil access.
- Trade-off
- Automated review can miss factual, language, or visual errors. Matching passage metrics does not establish validated reading-level equivalence; educator review and learner validation remain necessary.
Building & checking the application
Development and release tooling
Changes are checked with component tests, browser tests, and a Cloudflare build: Workers Builds builds the main branch from GitHub and deploys it. The Python pipeline has separate checks for scoring and its API payloads.
pnpm, TypeScript & ESLint
- pnpm manages the web dependencies and scripts. TypeScript checks types, and ESLint checks source-code conventions and common mistakes.
- Trade-off
- Passing software checks does not establish educational validity. Deployment checks and research validation answer different questions, and both need evidence.
