In development, not in the stores yet

Practising for the theory exam, as a game with an honest pass chance

An iOS and Android app for the Dutch car theory exam: short rounds with points and a weekly leaderboard, while the pass chance stays honest on purpose.

Role
Everything, built alone
Period
June 2026 to now
Stack
TypeScript, React Native, Expo, Fastify, PostgreSQL
Status
In development
Home: level, streak, daily goal and the Play button
Result of a round: points, hits, combo and XP
Home and the result of a round. Demo data.

The problem

Learners are nervous about the theory exam, practise in short bursts on their phone, and a resit costs money. Existing practice apps feel like studying or like a bought template.

What I built

Every question becomes a quick round with points, combos, levels, a daily streak and a weekly leaderboard, while one number, the pass chance, stays honest on purpose. Mistakes come back through spaced repetition in a queue of their own.

The app works offline, since all questions and images are inside it, and syncs progress with its own backend once you log in. The question bank: 2,616 questions, merged, deduplicated and checked in 26 categories.

What matters technically

  1. A leaderboard where cheating does not pay

    The app computes the points itself for the animation, but the server derives from the same rules the most a round can earn. A modified app can never post more, and the week boundary follows the real time zone, also around daylight saving time.

  2. Offline first, never counted twice

    A finished round is first stored on the phone and waits in a bounded queue until the server accepts it. Sending the same round again does nothing, so a retry never counts twice.

  3. Syncing between devices without loss

    Progress travels with a version number; an outdated write is fetched again and merged. Practice sessions are facts with their own id, so two devices merge without totals disappearing or doubling.

  4. Own validation of in-app purchases

    The server checks App Store and Google Play purchases itself, and one unique key per transaction stops the same purchase from granting premium twice. A second payment rail through Mollie grants access through the same function, so the two never drift apart.

  5. An API nobody else can look into

    The session token decides who you are; the app sends no user id of its own. On top of that, bcrypt for passwords, rate limits per route and unique nicknames with a list of reserved names.

  6. Traffic scenes from a description

    A small JSON description of a traffic situation is rendered in Blender as an exact scene, in 30 styles such as night and rain. This is a prototype, tried on 30 questions.

Measured

Counted in the repository, not estimated.

questions, merged and checked
2,616
categories
26
screens in the app
12
test cases in app and server
566
database tables
7
How measured
python3: len(json.load(open('src/data/questions.json')))
python3: len(json.load(open('src/data/categories.json')))
find src/app -name '*.tsx' ! -name '_layout.tsx' ! -name '+*' | wc -l
grep -rn "it(\|test(" server/test src --include=*.ts --include=*.tsx | wc -l
grep -c "pgTable(" server/src/db/schema.ts

Measured on 27-10-2026 in the project's own repository.

Need something similar, or a team that builds systems like this?

info@bitvire.com