All case studies

Mobile · Android release

Shipping a subscription app to Google Play with no backend

A Flutter learning app with stroke-order grading, spaced repetition, AdMob and Google Play Billing 8 — running entirely on-device.

Role
Sole developer — design, build, release
Platform
Android (Flutter 3.44)
Status
Live on Google Play

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.

The problem

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.

Constraints

The boundaries that shaped every decision that followed.

No server budget

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.

Licensed data, properly attributed

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.

Ads that do not poison the experience

Revenue had to come from advertising without the app feeling like an ad delivery vehicle.

What I built

  1. 01

    Stroke-order grading from vector data

    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.

  2. 02

    Spaced repetition, on-device

    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.

  3. 03

    Subscriptions with Google Play Billing 8

    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.

  4. 04

    Bundle-and-unlock instead of download

    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.

  5. 05

    Retention plumbing

    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.

  6. 06

    Advertising that stays out of the way

    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.

Aigaku home screen with streak and progress
Aigaku home screen with streak and progress
Stroke-order tracing practice with live grading
Stroke-order tracing practice with live grading
Quiz screen driven by spaced repetition
Quiz screen driven by spaced repetition

Results

221
Glyphs with validated stroke data (142 kana + 79 kanji)
0
Backend servers to run or pay for
3
Subscription SKUs with in-app plan switching
~1 MB
Premium content bundled, unlocked by entitlement

Built with

  • Flutter
  • Dart
  • Riverpod
  • Google Play Billing 8
  • in_app_purchase
  • google_mobile_ads
  • flutter_local_notifications
  • Google Sign-In
  • KanjiVG / KANJIDIC2
  • Python (data pipeline)

Working on something similar?

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.