← All projects

Svenska OS

My Swedish textbooks turned into a course I actually use: capture a word, let AI enrich it, practise the chapter, review it later.

Year
2026
Role
Solo — design and build
Stack
Next.js 15 · React 19 · TypeScript · Prisma · Postgres · Claude API
The Svenska OS dashboard: a Swedish greeting, an A1 to A2 progress bar at 50 percent, and four ranked tasks for the day
The daily dashboard answers one question — what should I study today — and is a live projection over the data rather than a streak counter.

The problem

I am learning Swedish from A1 towards B2 and I already had the curriculum: the Rivstart books and a Swedish–English dictionary. What I did not have was a way to work through them daily. Language apps do not follow my books, and a chatbot will happily talk to me in Swedish without ever telling me which chapter I am behind on.

So the books stay the source of truth. The app is the layer that turns them into something I open every morning.

The material

The three Rivstart course books and the Hippocrene dictionary, modelled as books → chapters → grammar topics, plus the vocabulary I capture myself as I read.

The book PDFs never leave my machine. They are excluded from the repository, and in production the buttons that would open a page in the textbook disable themselves rather than break.

What I built

Three layers: the content layer that models the real course; a learning engine with vocabulary, generated exercises and spaced-repetition review; and an intelligence layer that enriches words and explains grammar.

The loop is deliberately short. Find a Swedish word, save it tagged with the chapter it came from, and the AI fills in the translation, whether it takes en or ett, its forms, examples and a usage note. Practise the chapter against exercises generated from its grammar and your own vocabulary. Review with flashcards. A daily dashboard answers one question — what should I study today — as a live projection over the data rather than a streak counter.

The Swedish Journey screen: cards for CEFR levels A1 to C1 above the chapter list of the Rivstart A1 + A2 textbook, with completed chapters ticked
The learning path is the real course — five CEFR levels, the actual Rivstart chapters, each with its grammar topics and word count.
The dictionary screen listing Swedish words with their English translations, CEFR level, word class, and a saved marker on words already in the vocabulary
Every entry carries its gender, level and word class, and shows whether it is already in my vocabulary — unknown words save into review in one click.

The result

It is live, and it is the tool I actually use for my own Swedish — which is the only test it was built to pass.

The public demo is deliberately read-only. It had been running against a free hosted Postgres that was suspended after two months of inactivity, so the page answered 500 while the code was fine; it now reads a SQLite database shipped inside the build, which cannot expire. Browsing, the learning path and the dictionary all work; adding a word does not, because there is nowhere to write.

Technical notes

For anyone who wants the detail.

The AI lives behind a service layer. Feature code never imports the Anthropic SDK — it calls enrichWord(). Output comes back through tool-use and is validated with Zod at the boundary, so there is no prose parsing to go wrong.

Two decisions were made to be reversed later. The scheduler sits behind a swappable interface — a transparent interval ladder today, FSRS when I want it — and a User row exists from day one even though the app is single-user, so adding authentication is a where userId change rather than a redesign.

SQLite locally, Postgres in production: enum-like fields are stored as strings and validated in the application layer, which makes the provider swap a config change.