Open-source project
kolplattformen/skolplattformen avatar
kolplattformen/skolplattformen

Öppna Skolplattformen replaces Stockholm's school platform with a React Native app on a reverse-engineered API

The source code to the civic tech project Öppna Skolplattformen.

809 stars170 forksTypeScriptApache-2.0

At a glance

What is it?
Skolplattformen is an Nx monorepo from parents who were fed up with the City of Stockholm's school administration platform and rebuilt it as a React Native app over reverse-engineered API libraries for Skolplattformen, Vklass and Infomentor. It ships a website, a fake mode for development, and a per-platform API layer that other apps can reuse.
Who is it for?
Skolplattformen fits contributors who want to work on public-sector software with real users and a fast feedback loop, and it fits developers who want a reusable client library for the Stockholm school platform APIs rather than a full app.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 40 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Parents built this because the official platform frustrated them

The project description calls itself a civic tech project, and the README explains the motivation in the first person: we are parents who got fed up with Skolplattformen, the City of Stockholm's school administration platform.

What they did was reverse-engineer the platform's API to create what they describe as a simpler, faster, more consistent and secure experience for parents and guardians. The website for people who just want information about the app is at skolplattformen.org.

That framing tells you what kind of project this is and who it is for. It is not a commercial product and it is not an official Stockholm project. It is a volunteer effort by the users of a public service, and the value proposition is usability and speed against an incumbent administrative system.

The project is Apache-2.0 licensed, with a LICENSE file at the root and a badge saying so. There is a Patreon badge for the project, a Weblate translation status badge, a Vercel deployment badge and a Bitrise build status badge.

The primary language is TypeScript, the app is built with React Native, and the topic tags name the app, civic-tech, react-native and school-education. The last push to the repository was on 2026-09-14 and there are no GitHub releases, with the version tracked in package.json at 2.17.1 instead.

An Nx monorepo with two apps and five libraries

The architecture section describes the project as several apps and libraries inside an Nx monorepo, with the sources for each under apps and libs.

The apps directory holds two runnable applications. The skolplattformen app is the central part of the project, written in TypeScript using React Native and React Native Kitten, and the stated main goal is to make it as fast and easy to use as possible. The README says they are starting small, with more features being added over time. The website is the code for skolplattformen.org, built using Next.js.

The libs directory holds the reusable pieces, and the README makes a point of the rule it follows: there are many different kinds of libraries and each library defines its own external API so that boundaries between libraries remain clear.

The api library is the base for all API implementations. api-vklass is the implementation for the school platform Vklass. api-infomentor is the implementation for the school platform Infomentor. api-skolplattformen is the one for the platform the project is named after. curriculum holds translations of curriculum codes to clear text descriptions, and hooks is a set of React hooks to make using the API in the app easier.

The library split is the most reusable part of the design. Somebody who wants their own client for the same platform can take api-skolplattformen rather than reverse-engineering anything, and the README says exactly that: by not having to worry about the complex nature of the official API, the app becomes light-weight, and it also makes it easier for others to develop their own applications for the Skolplattformen API.

Fake mode is how you develop without touching the live platform

There is one feature in this repository that tells you more about how the project is run than any other, and it is called fake mode.

The README describes it as a pro tip: if you do not want the API to make requests to the back-end, you can turn on fake mode to return static data instead. You do so by logging in using 12121212121212 or 1212121212 as your personal identity number.

That is a deliberate design decision. A reverse-engineered API client is one where a mistake can mean an authenticated request against a live municipal system. Making fake mode reachable through the normal login flow with a magic identity number means a developer cannot easily hit production by accident, and it means automated tests and pull request previews never touch real student data.

The cost is that fake mode has to be maintained alongside the real implementation. Every API change needs a matching static fixture, and a fixture that drifts from the real response is worse than no fixture because it hides a bug.

The documentation for the api-skolplattformen library is linked from the README, and the repo also carries an AGENTS.md file for AI and agent helpers that documents the repository conventions and the automated verification setup. That file, plus the CHANGELOG.md the README points to for new features and fixed bugs, is where a new contributor should start.

Building it needs Node, Yarn and an Nx workspace

The getting started section is short and assumes a JavaScript toolchain.

You need git, node and yarn installed, then clone the repository.

bash
$ git clone https://github.com/kolplattformen/skolplattformen.git

Then install the dependencies.

bash
cd skolplattformen && yarn

The root package.json shows what Nx is used for. The scripts are thin wrappers: start is nx start, ios is nx ios, android is nx android, build is nx build, test runs nx run-many with the test target across all projects, and lint does the same for lint. There is also a prebuild and a prebuild-clean pair, and a release-managed .releaserc file at the root.

One script is worth calling out because it is unusual in an app repository.

bash
    "extract-licenses": "react-native-oss-license --json > licenses-oss.json && node library-extractor.js && rm licenses-oss.json && mv libraries.json apps/skolplattformen-app",
    "postinstall": "yarn extract-licenses"

The app runs a licence extraction on every install, generating a licenses file into the app directory. For a project distributed to parents through app stores that is a sensible thing to automate, since it keeps the third-party licence inventory current without anyone remembering to do it.

The repository also carries .nvmrc and .node-version files, which pin the Node version for contributors and for continuous integration.

Expo on the phone, and the Infomentor BankID complication

The app uses Expo for building and running, and the Expo CLI has to be installed globally.

bash
npm install -g expo-cli

On iOS you need a Mac with Xcode, then yarn ios to start the app or yarn start to run it in Expo Go. On Android you need Android Studio with an emulator or a device, then yarn android or yarn start.

The Infomentor path is the exception, and the README is explicit that Expo Go will not work for it. Infomentor, in Stockholm, is the default school platform in the app, and it requires native cookie storage through @react-native-cookies/cookies, so you have to build and run with the embedded expo-dev-client instead.

Logging into Infomentor goes through BankID. For local development there is a shortcut described as a dev session, and the explanation is unusual enough to repeat: the verification order is auto-approved by Stockholm's BankID gateway for a device already registered with BankID, so no scan is needed.

bash
# 1. Mint a fresh session (prints a DEV-SESSION line, ~40 min TTL)
cd libs/api-infomentor && npx tsx scripts/e2e-qr-server.ts

# 2. Paste the printed line into apps/skolplattformen-app/.env.local
#    (gitignored — NEVER commit it):
#    EXPO_PUBLIC_INFOMENTOR_DEV_SESSION=ASP.NET_SessionId=...; BIGipServer~...=~...; TS0116cbba=...; IMHome=...

# 3. Restart Metro WITH cache clear (EXPO_PUBLIC_* values are inlined into
#    the bundle at transform time — a plain restart will keep the old value)
npx expo start -c

Three practical details there. The dev session is pasted into a .env.local file that is gitignored, and the comment says never to commit it. The Metro restart needs the cache clear flag because EXPO_PUBLIC_ variables are inlined into the bundle at transform time, so a plain restart keeps the old value. And sessions expire after roughly 40 minutes, at which point the hub answers 200 OK with an empty body, while expired or wrong cookies cause a 302 to the login page.

The last detail is the kind of failure mode that costs an afternoon if you have not been told. Detailed endpoints, quirks and implementation notes are in libs/api-infomentor/README.md.

Where this project is the wrong tool

The first limitation is the one the project itself is built around: the official API is complex and undocumented, so this is a reverse-engineered client. The api-skolplattformen library exists precisely so that the app does not have to worry about that complexity, which means the complexity is now contained in a library the project maintains rather than removed. When Stockholm changes the official platform, the fix lands in the lib, and every consumer waits for it.

The second limitation is platform scope. These libraries are for Skolplattformen, Vklass and Infomentor, and all three are Stockholm school platforms. There is nothing here for other municipalities, and the api library is the extension point for another platform, which means writing a new implementation, not configuring an existing one.

The third is the fake mode trade-off described earlier. It makes development safe, and it makes the fixtures a maintenance burden that only shows up when a real API response changes shape.

The fourth is the BankID dependency for Infomentor. Even with the dev session shortcut, the platform integration is tied to Stockholm's identity gateway, and a developer without a BankID-registered device cannot exercise that path at all.

The fifth is that this is not a school administration system. It is a consumer app for parents and guardians. If you want to run the platform itself, this project does not do that and does not claim to.

How it compares to using the official platform app

The alternative for a parent is the official Stockholm application, or the web interface of the same platform.

The trade is straightforward. The official application is supported, it will keep working when the platform changes, and it is the version the city supports. This project is faster and simpler by design, and it is maintained by people who use it daily, which is a different kind of responsiveness than a public sector release cycle.

What you give up with the unofficial app is any guarantee. The API is reverse-engineered, so a platform change can break the app at any time without warning. There is no support contract, no compliance review and no accessibility audit trail, and the release history lives in a CHANGELOG.md rather than in a versioned distribution with notes for each build.

The more interesting comparison is with the city itself. Projects like this exist because a public service was built for administrative staff and school administrators and then used by parents, and the fit was poor. Skolplattformen and similar efforts across Europe are an argument that a public platform should expose an API, because then the competition happens in the client rather than in procurement. The api-skolplattformen library being a separate published artifact is the clearest sign of that intent, since anyone can build their own client on it.

For a developer, the practical entry point is that library rather than the app. The app is the most visible artefact, but the reusable part is the API layer, and the hooks library makes consuming it from a React app straightforward.

Editorial conclusion

Skolplattformen fits contributors who want to work on public-sector software with real users and a fast feedback loop, and it fits developers who want a reusable client library for the Stockholm school platform APIs rather than a full app. It does not fit an organisation that needs a supported, contracted school administration system, and it does not fit a developer expecting stable upstream APIs, since the whole point is that the official API is reverse-engineered and complex. Before contributing, read AGENTS.md for the repository conventions, use fake mode by logging in with the documented personal identity number so you never hit the live platform, and remember that the Infomentor path needs a native build with expo-dev-client because it depends on native cookie storage.

Frequently asked questions

What is Öppna Skolplattformen and who builds it?

It is a civic tech project that reverse-engineers the API of Skolplattformen, the City of Stockholm's school administration platform, to build a simpler, faster and more consistent app for parents and guardians. The README states the project comes from parents who got fed up with the official platform.

How do I develop the Skolplattformen app locally?

Install git, node and yarn, clone the repository with git clone https://github.com/kolplattformen/skolplattformen.git, then run cd skolplattformen && yarn. The project uses Expo, so npm install -g expo-cli is needed, and you start it with yarn ios, yarn android or yarn start for Expo Go.

What is fake mode in Skolplattformen and how do I turn it on?

Fake mode makes the API return static data instead of making requests to the back-end. You turn it on by logging in using 12121212121212 or 1212121212 as your personal identity number, and the documentation for it lives in libs/api-skolplattformen.

Why does the Infomentor integration not work with Expo Go?

Infomentor requires native cookie storage through @react-native-cookies/cookies, so Expo Go will not work and the app has to be built and run with the embedded expo-dev-client. For local development you can mint a dev session with npx tsx scripts/e2e-qr-server.ts in libs/api-infomentor and paste the printed line into the .env.local file.

What libraries does the Skolplattformen monorepo contain?

The libs directory holds api as the base for all API implementations, api-vklass for the Vklass platform, api-infomentor for Infomentor, api-skolplattformen for the platform the project is named after, curriculum for translations of curriculum codes, and hooks, a set of React hooks for using the API in the app.

Official sources

  1. Issues
  2. kolplattformen/skolplattformen on GitHub
  3. License: Apache-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kolplattformen-skolplattformen.svg)](https://hysenlabs.com/projects/kolplattformen-skolplattformen)

Was this useful?