Desco Languages.
English practice with audio transcribed word by word and flashcards that play the original voice.

The problem
Listening to an audio track from start to finish teaches little. A student needs to see the text, repeat a passage, slow it down and review vocabulary at the right moment. And the material should reach invited students only.
What I built
I built the platform and its content pipeline. 249 audio tracks were transcribed with Whisper running locally, with the timing of every word. Students get a clickable transcript, dictation, A-B looping and 0.75× playback. The 1,049 flashcards use SM-2 and play the word clipped from the original audio. There are 7 exercise types with forgiving answer checking, XP, levels, streaks, 12 achievements and an activity heatmap. Writing feedback from Claude is optional. Everything runs on Docker with Caddy and daily backups.
Technical decisions
01Local transcription, word by word
All 249 tracks went through Whisper running locally on MLX, which returns the timing of every word. There is no per-minute cost, and the material never leaves the machine. Word timing is what makes the transcript clickable and lets a flashcard play just that one word.
02Content stays on the server
The content used to ship inside the page’s JavaScript. I moved all of it to the server, and the JS went from 1.86 MB to 283 KB. Pages load faster, and anyone reading the page source does not walk away with the material.
03Audio behind a session, with Range support
Audio files go through the server, which checks the session before serving them and answers Range requests. Without Range, the player cannot jump into the middle of a track or loop a passage. Without the session check, a leaked link would play for anyone. The user id also comes only from the session, never from what the browser sends.
Numbers
249
audio tracks transcribed
1,049
flashcards
Stack
- TanStack Start
- React 19
- Vite 8
- Nitro
- Tailwind 4
- shadcn/ui
- Better Auth
- node:sqlite
- Whisper
- Docker
- Caddy
Screens

Team Desk