Mobile · Android release
A Flutter learning app with stroke-order grading, spaced repetition, AdMob and Google Play Billing 8 — running entirely on-device.
Aigaku is a Japanese kana and kanji learning app I designed, built and published myself. The interesting part is not the flashcards — it is that a full subscription business (three SKUs, free trial, in-app plan switching, entitlement gating) ships without a single server to maintain.
Learning apps live or die on two things: correction that feels immediate, and a reason to come back tomorrow. Most kana apps do multiple choice only — you can pass every quiz and still not be able to write a single character.
The second problem was commercial. A solo app cannot carry the cost or the compliance burden of a backend: user accounts, payment verification servers, uptime, a database of personal data to protect. I needed subscriptions and per-user progress without any of that.
The boundaries that shaped every decision that followed.
Entitlement had to be verified client-side against Google Play, and all content had to ride along in the APK. That rules out the usual "download premium content after purchase" pattern.
Stroke-order and dictionary data come from KanjiVG, KANJIDIC2 and JMdict — all CC BY-SA. Usable commercially, but only with correct attribution, which had to be built into the app before release.
Revenue had to come from advertising without the app feeling like an ad delivery vehicle.
KanjiVG ships SVG paths, not something you can grade a finger swipe against. I wrote a preprocessing pipeline that resamples every glyph to a fixed 25 points per stroke in normalised 0–1 coordinates, and validates the resulting stroke counts against KANJIDIC so a bad parse fails the build instead of shipping. The result is 142 kana and 79 N5 kanji the app can score for start point, direction and shape in real time.
Every answer feeds a local SRS store, so characters a learner keeps missing resurface sooner. Progress syncs through the user's own Google account with a union-based merge, which means two devices converge without a server arbitrating.
Three SKUs — monthly, yearly and a founder tier — with a 7-day trial. Existing subscribers can move between plans inside the app using proration, rather than cancelling and resubscribing. Entitlement is a client-side check that flips a single flag; everything premium reads from that flag.
Premium N4–N1 content (~1 MB) ships inside the APK and is unlocked by entitlement. No download server, no partial-download failure states, and premium content works offline — which became a selling point rather than a compromise.
Daily local notifications with correct timezone handling (which required core library desugaring on Android), streaks with a premium "streak freeze", eleven progression ranks, and a five-slide onboarding flow gated behind a version flag so it can be re-run after major releases.
No banners anywhere. One interstitial roughly every third completed quiz session, and rewarded video used only where the user actively wants something — a hint. Premium removes ads entirely, and rewarded hints stay free for subscribers.



Tell me what you are building and where it is stuck. I will tell you honestly whether I am the right person for it — and roughly what it would take.
Automation · AI tooling
A resumable Python pipeline that produced 68 style-matched illustrations on local hardware — averaging 9 KB each, with the licensing actually checked.
Web · Infrastructure
A containerised Next.js + Payload CMS template with automatic SSL, shared Postgres, off-site backups and a documented restore path.