Ìmọ̀, my Yoruba learning app, needs native speaker audio for over 300 vocabulary entries. The naive workflow is a spreadsheet, a voice memo app, and a folder of files named things like greeting_2_final_v3.m4a. That workflow produces mistakes at every step, and Yoruba is a tonal language, so mistakes are not cosmetic.
The vocabulary already exists as one typed TypeScript file inside the app: every entry with its Yoruba text, English meaning, phonetic guide, and tone annotations. That file is the single source of truth. So instead of exporting it to a spreadsheet, I generate the recording tool from it.
A Python script parses the TypeScript directly, using balanced brace extraction rather than a full parser, and emits a JavaScript data file plus a self contained browser recording studio. The studio shows one entry at a time with its tones and phonetics, records through the microphone, writes files named by entry ID via the File System Access API, and tracks which entries are done by checking which recordings actually exist in the folder, not by trusting a checkbox.
vocabulary.ts ──python──▶ vocabulary.js + studio.html
▲ │
└── one source of truth ▼
(app + studio) recordings/greet-01.webmThe whole thing deploys with the studio site: the sync script runs in the build pipeline, so pushing a vocabulary change regenerates the studio automatically. The speaker opens a URL, picks a folder, and records. No setup, no instructions document, no file naming conventions to violate.
The principle: when two artifacts must agree, do not maintain both. Maintain one and generate the other. Every piece of duplicated truth is a future inconsistency with a date on it.
