jennylabs.tech logo

A Russian learning app for my son

He can read Cyrillic. What he often doesn't know is how a word sounds and what it means. The app answers those two questions — and listens when he says it back.

Personal project · no public access Live since 4 November 2026

Diese Seite auf Deutsch lesen →

russian/readme.md

$ No word lists. No streaks. No accounts.

$ Just the text he has to learn this week.

The problem

My son learns Russian at school. The alphabet was the easy part. What he gets stuck on: he sees a word and doesn't know where the stress sits, how it sounds, or what it means. In Russian the stressed syllable changes the sound of the whole word, and schoolbooks don't print stress marks.

The learning apps that exist solve a different problem. They bring their own word lists, levels and a daily streak. He needed none of that. He needed this text, on this page, by tomorrow.

The solution

He photographs the page with his phone. Claude reads the Cyrillic text out of the photo, marks the stress, adds a phonetic transcription and translates it — all visible from the start, nothing to unfold. ElevenLabs then reads the text aloud, at 0.7× speed if he wants. He says it back, the recording goes to speech recognition, and Claude marks the words that were off, with a hint written in language a schoolkid actually understands.

  • Photo up to 6 MB or text up to 4,000 characters. Analysis in about 10 seconds.
  • Read aloud at normal or slow speed (factor 0.7). One fixed voice, no picker — one less decision.
  • What he says back is transcribed and compared to the original word by word.
  • History of the last 60 texts, deletable one by one, kept locally on the phone. No account, no data on the server.
  • Installable as a PWA on the home screen. Looks like an app, is a web page.
  • Cache for analyses and audio: the same text a second time costs nothing.
  • Password login. The API keys live on the server only, never in the browser.
Condensed from app.py
# With a photo the vision model, without it the text model
model = VISION_MODEL if img_bytes else TEXT_MODEL

# Identical request? Serve from cache, zero cost
key = _hash(model.encode(), text.encode(), img_bytes, ANALYZE_SYSTEM.encode())
cached = CACHE_DIR / "analyze" / f"{key}.json"
if cached.exists():
    return JSONResponse(json.loads(cached.read_text("utf-8")))

# Slow means genuinely slower, not chopped up
speed = SLOW_SPEED if body.slow else 1.0   # 0.7
stream = eleven().text_to_speech.convert(
    voice_id=stimme, text=spoken, model_id=TTS_MODEL,
    voice_settings={"stability": 0.5, "similarity_boost": 0.8, "speed": speed},
)

Stack

  • Python
  • FastAPI
  • Claude Sonnet 5 (text + vision)
  • ElevenLabs Flash v2.5 (text to speech)
  • ElevenLabs Scribe v2 (speech to text)
  • JavaScript (no framework)
  • PWA + service worker
  • Railway

The result

Built in one evening, in use the same evening.

635 lines of Python, a frontend with no framework, 9 commits. Running cost: $6 a month for the voice, plus a few cents per text for the model, plus hosting. No licence, no subscription, no ads, no data in the cloud.

My role

Concept, development, deployment, and the written guide that lets it run without me.

What I learned

The value wasn't in the technology. It was in the fit. The building blocks are public and I wired them together in an evening. What makes the app usable is everything that is not in it: no sign-up, no learning path, no choice of 300 voices. Every decision I made up front is one he doesn't have to make at eight in the evening.

Four fully planned features didn't get built. Conversation mode, role play with several voices, pronunciation scoring, history synced across devices. All sensible, all designed, none built — version 1 has to survive a week of real use first. The most common way to ruin a working tool is the second version.

Speech recognition hears what was said, not how well. Scribe transcribes reliably, but a word with the wrong stress is usually still recognised correctly — so the mistake slips through. Actually scoring pronunciation needs a dedicated tool for that job. That was the most important technical finding for anything I build in this direction next.

Want one for your case?

I build learning apps for one clear purpose and one clear group.

The skeleton stays the same: text or photo in, read aloud, say it back, get feedback. What changes is the fit, and the fit is the whole point. German for care workers with the sentences they actually use on a ward. Pronunciation drills for a choir, on the piece they're performing. Speech exercises for a therapy practice, on the sounds being worked on right now.

I work remotely and the result runs in a browser, so where you are doesn't matter. I work in English and German.

  • A 30-minute call. Who practises, what exactly, on which device. Then I tell you whether I think it's worth building — including when the answer is no.
  • Prototype within a week. Runs in the browser, installable on a phone. You try it with your real content before any money moves.
  • Fixed price, agreed up front. Plus the running cost for model, voice and hosting — itemised, and paid by you straight to those providers, not to me.
  • The code is yours. Your repository, your keys, your hosting. No subscription you can't leave.