Veivett is a study tool for the Norwegian driving theory test, and the successor to trafikkskiltene.no, a site I built at fifteen. It covers the theory for car, motorcycle, moped and tractor: the syllabus written out topic by topic, a question bank where every answer is explained, spaced repetition for the signs, and mock exams with the same length and time limit as the real test. It is live at veivett.no, currently in beta.
Where it started
When I was fifteen and about to take my tractor licence, I built trafikkskiltene.no to learn the traffic signs. It was plain JavaScript and PHP on an Apache server, and it did one job: teach the signs. It found its audience through search, has passed 750,000 page views, and has earned advertising revenue every year since, with very little maintenance.
It also showed me its own limits. The theory test covers far more than the signs, and on trafikkskiltene a wrong answer taught you nothing except that you were wrong. In 2026 I started over and built the tool I would have wanted: one that covers the whole syllabus and explains itself along the way. The name had to change with the scope, since “trafikkskiltene” literally means “the traffic signs”. After checking the company register, the app stores and the domains, the rebuild became Veivett.
Teach, not just test
Most sites in this space are question mills: answer, get a score, repeat. Veivett is organised around learning the material. Every question explains all of its answer options, not only the correct one, and carries a reference to the paragraph in the regulations it rests on. The signs, road markings and light signals have a spaced-repetition practice mode, so what you miss comes back until it sticks. Mock exams mirror the real test in both length and time limit. The end goal is that Veivett can tell you honestly when you are ready, rather than leaving you to grind quizzes and hope.
A dataset generated from the regulations
There is no CMS and no content database. All content is committed JSON, generated by scripts from official sources: the skiltforskrift on Lovdata and Statens vegvesen’s official sign artwork, 312 signs across nine categories, plus road markings and light signals. The sources are not static: regulations get amended, signs are added and retired, and on a licensing test an outdated answer is not a cosmetic bug. Two checks keep the dataset honest. A drift check notices when the upstream sources change, and a citation check verifies that every rule reference in the question bank can actually be found in the source texts. The same pipeline generates the sitemap, robots.txt and llms.txt, so search engines and AI assistants read from the same source of truth as the app.
The engine and the app
The quiz logic lives in its own package with no UI, IO or framework dependencies: pure functions over the dataset plus an immutable progress object. Distractors prefer wrong answers from the same category as the sign in question, scheduling is Leitner spaced repetition, and all randomness is injected, so everything is deterministic under test. The package was built test-first, and a future mobile app can reuse it unchanged.
The web app is TanStack Start with React 19, running on Cloudflare Workers. Content pages are prerendered to static HTML, so the theory, the signs and the sample questions are indexable by search engines and readable by AI assistants, while anything that depends on a signed-in user renders on the server.
Built with an agent fleet
Veivett is also an experiment in how much of the development itself can be automated. Work moves through a spec, plan, implement, review pipeline driven by Claude Code in GitHub Actions. An issue is shaped into a spec through questions and answers, the plan is critiqued against the actual codebase, and an implementer agent carries the approved plan through and opens the pull request. Every pull request is then read from five angles: code, security, design, Norwegian language, and the correctness of the published content. Each reviewer judges against convention documents that live in the repository and cites them when it objects, so a disagreement with a review is settled by revising the convention, not by arguing with the bot. The reviewers are advisory: they comment, they never block, and I merge.
The hardest lesson in building this is that nearly every failure mode of an automated reviewer looks exactly like success. A misconfigured job grants no tools, posts nothing and exits green; a prompt that fails to resolve runs zero turns and exits green. So every reviewer ends with a step that fails the job unless its review actually got posted. The agents also share a memory server, so a decision made in one session can be found in the next.
What it taught me
Trafikkskiltene taught me that a small, fast site answering a real need can run for years on its own. Veivett is teaching me what it takes to run a full product alone: content accuracy, engine correctness, rendering and search visibility all have to hold at the same time. Working with the agent fleet has changed how I develop. When every change is judged against written conventions, the real work moves from writing the code to writing down the rules, and being precise about what is true, and where it is written, turns out to matter more than any single feature.