Interactive Lottie characters that teach children aged 3–6 the Urdu alphabet. Each letter is an animal or object whose body is the letter: Alif is a finger pointing up, Ba is a duck, Tay is a leaf with two butterflies for its dots, Meem is a fish, Noon is an orange sitting over its peel. Tap a character and it reacts and says its letter. Everything is generated from code, so a fix is a number and a re-run, and every design choice is tied to a cited reason in research/.
Live review page: https://oyekamal.github.io/urdu-letter-friends/review/ (tap the characters)
Most “alif bay pay” apps are slop: a static picture, a chant, a coin animation. Kamal’s rule for this project is that nothing ships that does not demonstrably help a small child learn to read Urdu, and that the app should be something a child wants to open, without dark patterns. So the order of work is: research first, contract second, characters third. See What the research says and the three files in research/.
| Path | What |
|---|---|
lotties/ |
The characters (alif-ungli.json, ba-duck.json, tay-titli.json; retired legacy/alif-worm.json) and manifest.json, the single source of truth: letter, sound, mnemonic word, canvas, segments, audio, status |
scripts/harf_rig.py |
Shared python-lottie rig: canvas sizes, easing, face(), blink(), bob(), sway(), look(), sparkle_burst(), export() with idle/tap markers. Run it to self-check |
scripts/make_tay.py |
The first generated character; copy it for the next letter |
scripts/render_frames.py |
Renders N frames with lottie-web in headless Chrome to review/frames/<name>.png, the same renderer the app will use |
scripts/build_review.py |
Builds review/index.html from the manifest |
review/ |
Review page, frame strips, and the Lottie inspector Kamal uses |
audio/names/ |
Letter-name clips (pilot machine voice from urdu-reading-course, CC BY-NC; record a human before release) |
research/ |
Cited research: early-years letter pedagogy, Orenda/Taleemabad practice and Pakistan ECE curriculum, kids-app engagement and Lottie interactivity |
docs/ |
App plan and the decision log |
.claude/skills/letter-character/ |
The Claude Code skill that builds a new letter under the contract (pedagogy gate, motion numbers, verification) |
idle (frames 0–90, a 3 s loop) and tap (frames 90–180, a 3 s reaction that lands back on the idle pose). The app plays by marker name with playSegments, so timing can change without touching app code.pip install lottie playwright pillow && playwright install chromium # once
python3 scripts/harf_rig.py # self-check
python3 scripts/make_tay.py # -> lotties/tay-titli.json
python3 scripts/render_frames.py tay-titli 8 # -> review/frames/tay-titli.png, look at it
python3 scripts/build_review.py # -> review/index.html
python3 -m http.server 8000 # open http://localhost:8000/review/ (fetch needs http, not file://)
With Claude Code in this repo: “make the Pay character” invokes the letter-character skill, which walks the same steps and refuses to skip the pedagogy gate.
const anim = lottie.loadAnimation({container, renderer: 'svg', loop: true, autoplay: false, animationData});
anim.addEventListener('DOMLoaded', () => anim.playSegments([0, 90], true)); // idle
stage.onclick = () => { sayLetter(); anim.loop = false; anim.playSegments([90, 180], true);
anim.addEventListener('complete', function once() { anim.removeEventListener('complete', once);
anim.loop = true; anim.playSegments([0, 90], true); }); };
Segment numbers come from lotties/manifest.json, never hard-coded.
Full synthesis with citations: docs/app-plan.md. The short version:
How to teach a 3–6 year old a letter (research/01, research/02)
How the app should look (research/03)
Engaging without manipulating (research/01 §3, research/03 §1)
How the characters carry all of that (docs/app-plan.md §4)
| Letter | Character | Mnemonic check | Status |
|---|---|---|---|
| ا alif | finger pointing up (ungli) | passes (انگلی) | generated, in review; worm retired to lotties/legacy |
| ب be | duck | passes (بطخ) | Kamal’s reference, no markers yet |
| ت te | leaf + two butterflies | passes via butterflies (تتلی) | generated, in review |
| م meem | fish (loop = body, stroke = tail) | passes (مچھلی) | generated, in review |
| ن noon | orange as the dot over a peel bowl | passes (نارنگی) | generated, in review |
Open decisions for Kamal are in docs/decisions.md: Alif re-theme, eye style (round eyes near strokes read as extra dots), tap length, marker set, stack. Next build: ک ل د to finish wave 1.
Code MIT. Character art and animations CC BY 4.0. Pilot audio inherits CC BY-NC from its TTS model.