Theorio: a Dutch car theory app with its own 3D traffic engine
Our own product. An Expo app for the Dutch car theory exam where every traffic situation is generated and solved by a rules engine, drawn in three.js inside the app, and explained with the article of law behind it. It also lets you drive an Amsterdam canal street in 3D.
1,200
generated 3D traffic situations
2,370
practice questions in four banks
140
hazard photos from 338 candidates
30
practice exams in the real format
Challenge
Learning for the Dutch theory exam usually means memorising a fixed set of pictures. You learn the picture, not the rule, and the first unfamiliar junction on the exam throws you. We wanted a course that can show an endless number of junctions, always knows the right answer, and can say why with the law in hand. And it had to work where people actually study: on a phone, a few minutes at a time. That meant four hard things: priority rules precise enough to compute, pictures that are drawn from data, a question bank that stays correct when the law changes, and 3D that ships inside a phone app.
Solution
Engine first
We wrote the priority rules as a tested engine before drawing anything. A situation is data, the answer is computed, and each step in the answer points at its article.
Draw from data
A three.js renderer builds every scene from primitive shapes. It only draws what the engine decided, from above with arrows or from behind your own car.
Content pipelines
Written questions are drafted against stored law text and verified. Hazard photos are generated from written specs and picked by a reviewer against a checklist.
One app instead of a website
We rebuilt the interface as a single Expo app and retired the web version. The engine, the renderer and the API stayed; both 3D scenes are bundled into the app.
A course and a drive
Fourteen chapters, each a short road with a video, theory, three rounds of questions, a 3D drive and a test, plus thirty practice exams in the real format. Three chapters and one exam are free.
Results
Theorio is in development and not yet released, so there are no learner results to report. What exists today is the app running in the iOS simulator, in Dutch and English, against its own API: the onboarding, the Route with fourteen chapters, all four question banks with their law citations, sign cards on a spaced schedule, the Amsterdam drive and thirty practice exams. Still open are payment in the app, the lesson videos, the drawings in the theory, accounts, reminders and more streets to drive.
(01)
A rules engine that works out every answer
Most theory apps store a picture and the letter of the right answer. Theorio stores neither for its traffic situations. A situation is a small data model: a junction with up to four arms, each with its road type, sign, traffic light or zebra, and two to four road users with where they come from and where they are going.
The engine first checks which paths actually cross or merge. For every pair that conflicts it applies the Dutch priority rules in a fixed order: emergency vehicles, zebra crossings, exits, signs, unpaved roads, trams, traffic alongside, the bent priority road, turning, and finally traffic from the right. Traffic lights and roundabouts have their own rules on top. Those pairwise decisions are layered into an order of who goes when.
Because the answer is derived, the explanation comes for free. In the app it is the answer screen: numbered badges on the vehicles, one line per road user, and under each line the article of law that decided it.
- situations in the generated bank
- 1,200
- situation types
- 7
- priority rules
- 12
- engine tests
- 52
01
Model
Junction, signs, lights and two to four road users, validated so impossible scenes are rejected.
02
Conflicts
Which paths cross or merge. Road users that never meet do not have to wait for each other.
03
Decide
For each conflicting pair the highest applicable rule decides who yields.
04
Order
The pairwise yields are layered into one order. Ties and deadlocks are thrown away.
05
Explain
Each step carries its rule and the article it comes from, in Dutch and English.




(02)
The same three.js scene, packed into the app
The renderer is a separate package that only draws. It receives a situation and an order from the engine and never decides priority itself, so the picture can never disagree with the answer.
There are no model files. Cars, trams, scooters, cyclists, pedestrians, roads, kerbs, shark teeth, zebra bars, signs and traffic lights are all built in code from primitive shapes. For the app we bundle that renderer into one self-contained page of about 640 kB. It ships inside the app and runs in a web view, so drawing a junction needs no server and no download.
React Native hands the scene over as data and gets taps back as messages: tapping a car in the picture selects the same answer as the button below it. The camera has two positions, an overview with an arrow for every path and a view from behind your own car for questions about what you should do. Everything around the scene, from the answer buttons to the feedback sheet, is native.




(03)
A drive through Amsterdam
A junction seen from above teaches the rule. It does not teach you to see the moment coming. So the app also has a drive: you follow your own car up a canal street at 30 km/h, past canal houses, parked cars, houseboats and cyclists.
The drive stops twice. First for a hazard: a pedestrian steps into the road, and you choose between braking, releasing the accelerator and doing nothing. Then at the bridge, where a tram crosses and you say whether it goes first. That second answer is not scripted. The junction goes to the same rules engine as every other situation, and the drive plays on from what you answered.
The street is built the way the junctions are: in code. The house fronts, the trees, the tram and the brick paving with its textures are generated when the drive loads, in about 2,600 lines of TypeScript and without a single model or image file. For now there is one street. It is a stop on the Route and a tile on the start screen.
- street so far, an Amsterdam canal
- 1
- stops: a hazard and a junction
- 2
- model or image files
- 0
- km/h, as the zone sign says
- 30






(04)
A course shaped like a road
The app opens with a language choice and three short questions: when your exam is, how many minutes a day you have, and whether you want to follow the Route or practise freely. The answers become a plan you can change later.
The Route has fourteen chapters. Each chapter is a short winding road with five stops: a video, the theory, three rounds of ten questions, the 3D drive and a test you pass with eight out of ten. The start screen shows where you are on the Route and what is due today, with a tile for everything you can practise on its own.
A streak, points and a daily goal keep score. The theory can also be read on its own, chapter by chapter, with a search across all of it.
- chapters on the Route
- 14
- stops per chapter
- 5
- rounds of ten questions
- 3
- to pass a chapter test
- 8 / 10








(05)
Written questions, each tied to an article of law
The written questions cover what a 3D scene cannot: speed limits, parking, lighting, documents, alcohol, loading. We stored the relevant Dutch traffic law locally, ten texts from the government's own publication, split per article.
Every question is drafted with AI against the stored text of one article and then checked by an independent verifier. The question keeps its source and article number, and the learner sees that citation under the explanation.
An automated test checks every question on each change: the cited article must exist, the photo or sign must exist, the answer options must be complete and both languages must be present. A question you miss comes back the same day and then after one, two, four, seven and fourteen days. The 154 signs are also flashcards: you rate each card with one of four buttons and the standard SM-2 schedule decides when you see it again.
- written questions
- 730
- law articles stored
- 2,888
- sign questions from 154 signs
- 300
- languages, Dutch and English
- 2
01
Store the law
Ten texts saved per article, with the date of the version used.
02
Draft
AI drafts a question against one article, in one of three formats.
03
Verify
An independent verifier checks the draft against the same article.
04
Test
Automated checks on citations, images, options and translations.
05
Review
Reported and often-missed questions go to a review queue in the API.






(06)
Sampling hazard photos instead of shooting them
Hazard perception needs photos from the driver's seat: a ball rolling between parked cars, a pedestrian stepping onto a zebra, a tractor filling the lane ahead. Shooting those safely and legally on Dutch roads is slow and expensive, so we generate them.
Each scene starts as a written spec: what the photo shows, the speed you are driving, the right reaction, and a checklist of what must be visible. For every spec we generate two or three candidates and compare them against that checklist. A reviewer who did not write the spec picks one, or rejects all of them.
We ran a trial with two image models on the same five prompts first. One matched the checklist three times out of five, the other five out of five, and that settled the choice. The most common reason to reject a photo turned out to be distance: the model draws almost everything two to four times closer than asked, which changes whether braking is the right answer.
- scene specs written
- 159
- candidate photos generated
- 338
- photos in the app
- 140
- brake, release, nothing
- 49 / 45 / 46


(07)
Practice exams in the real format
Thirty numbered practice exams follow the format of the real one: fifty questions in thirty minutes, pass at forty-four. Each exam mixes rule questions, signs, 3D situations and hazard photos, and nothing is marked until you hand in.
A map of fifty dots shows which questions are answered, open or flagged, and jumps to any of them. Pausing keeps your answers, but the clock runs on, as it would in the exam room. Afterwards the result is split per part and every mistake goes into the repeat queue with its explanation.
- numbered practice exams
- 30
- questions each
- 50
- minutes on the clock
- 30
- right to pass
- 44




Next step
Want something like this?
Tell us about your version of this problem.

