NL Wallet is a secure app on your phone that lets you keep important personal information in one place, such as your name, age, or official documents like your ID card or driving licence. With the wallet, you can easily prove who you are, or show only the information a service needs.
For example: - Showing you are over 18 without sharing your full date of birth. - Confirming your identity when dealing with the government. - Sharing a digital version of a diploma when applying for a job.
This is useful, because: - You no longer need to upload scans of your passport. - You share only what is needed, not your whole identity. - Your documents are harder to fake, because they are digitally signed. - It works across all EU countries.
You stay in control: you choose what to share, with whom, and when.
NL Wallet is intended for Dutch nationals. It offers convenience, stronger security, and protection against identity fraud — all while giving individuals greater control over their own information.
The app is being developed by Rijksoverheid (Dutch Government), in particular the Ministry of the Interior and Kingdom Relations (MinBZK) and is expected to be available to the public in 2027.
NL Wallet also makes things easier and safer for relying parties, which are organisations that need to check identity or personal information.
For these organisations, this means: - More trust – the information comes directly from trusted sources, so it is harder to fake. - Less sensitive data to store – no need to keep copies of passports or other documents. - Easier compliance with privacy rules – only the necessary information is shared. - Faster and smoother processes – users can identify themselves quickly, with fewer steps. - European coverage – the same approach can be used in all EU countries.
This helps organisations to reduce fraud, protect personal data and offer a better experience to their users.
NL Wallet is being developed in an open and transparent way. We offer the following channels to allow you to contribute:
This documentation reflects the current implementation and will be updated with every software update.
Feel free to look around and share your [feedback and ideas][6].
See the [releases page][7] for the latest release. You can follow the latest work by subscribing to the releases of this GitHub repository at the top of this page.
We have a dedicated [documentation site][25].
If you want to learn more about the NL Wallet development, please read the background information on the [Pleio][5] hub. The development of the user flows and screens can be followed through [Figma][3].
The source code of the NL Wallet is released under the [EUPL license][8]. The documentation is released under the CC0 license. Please see the [.reuse/dep5][9] file for more details, which follows the [Reuse specification][10].
We’re releasing the source code with the explicit intention of allowing contributions. The coordination of the project lies with the development team of the European Digital Identity Progam, but we’re open to all contributions. You can directly create a new Pull Request via Github, or contact the community manager via [edi@minbzk.nl][11].
The development team works on the repository in a private fork (for reasons of compliance with existing processes) and shares its work as often as possible. If you watch the repository on GitHub, you will be notified of a new release. We will also send a notification through Pleio.
Although we are open to contributions, please consider the nature of this project as outlined in this Readme. At this stage the most useful way to contribute to the project is to participate on our community site [edi.pleio.nl][5], and visit our [EDI Meet-ups and/or Heartbeats][12].
If you plan to make non-trivial changes, we recommend that you open an issue beforehand where we can discuss your planned changes. This increases the chance that we might be able to use your contribution (or it avoids doing work if there are reasons why we wouldn't be able to use it).
Note that all commits should be signed using a GPG key.
This section contains the general setup requirements of the project. For more information on how to configure specific components like [wallet app][13], [wallet core][14], [wallet_web][15], and [wallet_provider][16], please see the corresponding README files.
The app's UI is built using Flutter, but to avoid tying the app to Flutter &
Dart, all core business logic is built using Rust. This gives us the more
flexibility to migrate to completely native iOS/Android apps if the need
arises. This does mean building the app is slightly more complex than a simple
flutter run. This section describes how to set up your environment.
The various components of NL Wallet have different requirements. To make sure things run correctly, you need to take the following system requirements into account.
Our mobile apps require at least the following operating system versions:
The app does not put a particularly heavy load on the device, so CPU and memory requirements are low to average. Note that this is subject to change.
The wallet_web frontend helper library effectively runs in the browser of a person that wants to interact with a relying party that integrates with the NL Wallet platform. As such, wallet_web has requirements on the minimum browser version supported:
Note that the above are not recommendations, but simply a statement about the minimum version we have some confidence in running correctly. We always recommend that you run the latest stable browser your platform offers. Also note that the above is subject to change.
We have various backend services, mostly built in Rust that make up the wallet
platform. In general, we build binaries for glibc and musl Linux-based
distributions. We've found that usually the musl binary will work on almost
anything, but the glibc binary really requires a glibc-based distribution.
jsonb support)Specifically for PostgreSQL you need to consider storage requirements. Our
database-backed services are wallet_provider, verification_server,
issuance_server, demo_issuer (usually not built for production environments)
and pid_issuer. They have a very simple database layout. A good ballpark
figure is to allocate 100GiB for a wallet_provider instance and 10GiB for
instances of the verification_server, issuance_server or pid_issuer. Of course,
these requirements will change with time and duration of usage, and are subject
to change. Also note that these size requirements assume somewhat serious usage;
for development purposes you can make do with a lot less.
The above Rust-based services require a regular Linux machine or container based on one of the aforementioned operating systems. Memory requirements of these services are very low (we're seeing 20 to 50 megabytes of usage on our Kubernetes clusters, but of course it depends on usage too). The storage requirements are effectively non-existent due to usage of PostgreSQL for state.
The Wallet app needs several supporting services to run, and also requires the user to log in using DigiD in order to create the Wallet. The services are the following:
All these applications will need to be configured correctly. A local development
environment with automatic configuration of all the above services can be set up
using the scripts/setup-devenv.sh and scripts/start-devenv.sh scripts, which
we'll document later in this Readme.
For end-users, an internet connection is required to use the disclosure and issuance features of the wallet app. For relying parties and issuers, who want to obtain disclosed attributes and issue attributes respectively, the same requirement holds.
To do development work on the NL reference wallet, you need to following tools:
In the following sub-sections we will document how to install and configure these.
To install Rust and Cargo using rustup, follow the [installation guide][20].
After installation, make sure to add the following targets:
rustup target add aarch64-apple-ios x86_64-apple-iosrustup target add aarch64-apple-ios-simrustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-androidMake sure rustc, and cargo are on your path and run the following commands
to install a few additional utilities we use:
cargo install --locked cargo-edit cargo-expand 'cargo-ndk@^4' cargo-nextest
cargo install --locked --version 2.11.1 flutter_rust_bridge_codegen
cargo install --locked --version 1.1.19 sea-orm-cli
cargo install --list
To build for Android you need to have the Android SDK and NDK installed on your
system. You can [download Android Studio here][21]. Note the install location
and set the ANDROID_HOME environment variable to point to that installation
location. The following is an example that assumes you installed Android Studio
in /opt/android, sets the necessary variables, and adds certain
Android-specific tools and utilities to your path:
export ANDROID_HOME="/opt/android"
export ANDROID_NDK_HOME="$(find "$ANDROID_HOME/ndk" -maxdepth 1 -type d | sort -V | tail -n1)"
export PATH="$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_NDK_HOME"
After having done the above, you will have tools like adb, sdkmanager, and
ndk-build on your path.
With sdkmanager --list_installed you can list the installed Android SDK
components. Now let's install some extra components we'll need:
# Install all needed packages. On intel/amd, x86_64 is
# fine, on arm64, use arm64-v8a for the system-image.
sdkmanager --install \
'build-tools;36.0.0' \
'cmdline-tools;latest' \
'emulator' \
'ndk;28.2.13676358' \
'platform-tools' \
'platforms;android-36' \
'sources;android-36' \
"system-images;android-36;google_apis_playstore;$(uname -m|sed s/arm64/arm64-v8a/)"
Note: The ndk version was the latest non-release-candidate version as of this
writing (2025-08-28); If there is a newer stable version, feel free to use that.
Same for the android version - it's 36 as of this writing, but newer might be
available when you read this - feel free to use that too.
You will need to create an Android virtual device (AVD) so you can run the emulator. To do that, do the following:
When you run $ANDROID_HOME/emulator/emulator -list-avds on the command-line,
you should see your just-created virtual device show up.
open -a SimulatorTo install Flutter follow this [installation guide][17]. You can validate your
initial setup by making sure flutter is on your path, and then running
flutter doctor which will tell you if all is well with its dependencies. Make
sure flutter doctor has no complaints or warnings; specifically, it needs to
find the Android and/or Xcode related components (in the case of Android, it
needs to find the SDK toolchain and Android Studio itself).
FVM is a simple CLI to manage Flutter SDK versions per project. It enables fast
switching between Flutter versions and pin them to your Flutter project. When
using FVM; all Flutter related commands need to be prefixed with fvm, e.g.
fvm flutter run.
To install FVM follow this [installation guide][18]. You can validate your
initial setup by running fvm flutter doctor after installation. Select [Y]es
when asked to install the pinned Flutter version defined in
[fvm_config.json][19].
Note that FVM only pins the Flutter version for local development, not for the CI pipelines.
Make sure
$ claude mcp add nl-wallet \
-- python -m otcore.mcp_server <graph>