A directory of USSD codes for mobile operators in West and Central Africa: Benin, Cameroon, Côte d'Ivoire, Mali, Niger, Nigeria, Senegal and Togo. Users run codes in one tap and no longer need to remember them. The app also works offline.
This Flutter app replaces the legacy native Java app (Play Store). It keeps the same application id, so it ships as an update of the legacy app.
Features:
- Codes by country and operator. The app opens on the user's SIM operator (MCC/MNC, read without any permission).
- Typed parameters. Amounts, phone numbers and PINs each get the right keyboard. A PIN is masked and never stored. Every code is confirmed before it runs.
- Direct run. The app runs codes directly on Android with the Phone permission, and falls back to the dialer pre-filled with the code. iOS doesn't let apps dial
*/#codes, so the app copies the code there. - Personal data. Users keep favorites and their own codes, and search covers every country.
- Device codes. IMEI and test menus, filtered by brand.
- Catalog updates. Codes are a versioned catalog, separate from the app (see catalog/), and can be updated without a store release.
- Legacy migration. The first launch imports the legacy app's favorites, personal codes and default country.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
The Play Store images, in English; other languages are in store/screenshots/<lang>/.
- Mobile: Flutter, Dart SDK
>=3.8.0 <4.0.0 - State management: Riverpod (
riverpod_generator, code-gen) - Routing: go_router (
go_router_builder) - Local storage: SharedPreferences
- i18n: Slang (French and English, English base locale)
- Native: a small Kotlin channel (
ussd_codes/telephonyinMainActivity.kt) to dial, read the SIM operators and read the legacy app's database
- Flutter SDK matching
>=3.8.0 <4.0.0(CI runs on thestablechannel) - A
.envfile (see Environment variables)
cp .env.example .env
flutter pub get
dart run slang
dart run build_runner build
flutter run --flavor devThe app bundles .env as an asset, so every value in it is public.
| Variable | Description | Example |
|---|---|---|
APP_CATALOG_URL |
Public URL of the built catalog, which the app downloads to update its codes. When empty, the app only uses its bundled catalog. | https://netersoft.github.io/ussd-codes/catalog.json |
APP_CONTACT_EMAIL |
Where users send code suggestions and corrections. When empty, the contact and report actions are hidden. | support.netersoft@gmail.com |
APP_PRIMARY_COLOR |
Primary theme color, hex | #008000 |
APP_SECONDARY_COLOR |
Secondary theme color, hex | #32DC32 |
APP_ACCENT_COLOR |
Accent theme color, hex | #f5f5f5 |
APP_CATALOG_URL must be reachable without authentication. This repository is private, so the catalog is published on GitHub Pages, in the public netersoft.github.io repository (see USSD catalog).
The codes live in catalog/, one JSON file per operator. After editing them:
dart run tool/build_catalog.dart # validates and builds assets/catalog/catalog.jsonOnce the change is merged, publish it so installed apps receive it. The command below regenerates the public site in a netersoft.github.io checkout: ussd-codes/catalog.json, plus one page per country and operator and a sitemap. Then open a PR there:
dart run tool/build_site.dart ~/Dev/Projects/Web/netersoft.github.ioThe site (https://netersoft.github.io/ussd-codes/) lists the codes for search engines and links to the Play Store. Its pages are built by lib/core/catalog/site.dart, in French except Nigeria (English).
catalog/README.md describes the format, the update flow and the data still to verify.
flutter test
# with coverage, as run in CI:
flutter test --coverage| Env | URL | Deployment |
|---|---|---|
| Production | Play Store | Manual upload of the prod flavor |
- Tech lead:
- Product owner:
lib/core/catalog/: the catalog in pure Dart (models, validation, search, source assembly), plusCatalogRepository. The repository uses the bundled copy, downloads newer versions and caches them on disk.lib/core/library/: the user's own data (favorites, personal codes) and the one-time legacy import.lib/core/services/telephony/: dialing, SIM detection and reading the legacy database, through the Android channel.lib/core/providers/: Riverpod providers.catalog_provider.dartholds the catalog, the SIM operators and the device codes.library_provider.dartholds favorites, personal codes, the selected country, direct call and startup.settings_provider.dartholds language, theme, sharing and contact.
lib/view/: screens, components, modals and theme.- Screens: the main shell with the operators, favorites and phone tabs, plus search and settings.
- Components and modals: code tile, run sheet, add sheet, country picker.
tool/build_catalog.dart: the catalog build and check script.
Runtime composition starts from lib/main.dart → lib/core/bootstrap/app_bootstrap.dart (env, DI, locale) → lib/app.dart. MainScreen waits for appStartupProvider while the native splash stays up. That provider loads the catalog and runs the legacy import.
Generated files (*.g.dart, *.config.dart) are excluded from git. To rebuild them, run dart run slang and dart run build_runner build.
The privacy policy ships in the app (assets/docs/<locale>/privacy_policy.html, one per app language, opened from Settings). The store listings link to the public copy at https://netersoft.github.io/ussd-codes/privacy/ (English: /en/), served by GitHub Pages from the public netersoft/netersoft.github.io repository, next to the catalog. After editing the policy, regenerate the pages and push that repository:
python3 tool/build_privacy_pages.py ~/Dev/Projects/Web/netersoft.github.iodart format .
flutter analyze
flutter testflutter run --flavor dev
flutter build appbundle --flavor prod --releaseEach flavor has its own applicationId suffix (.dev, .staging, none for prod) and app name, so all three can be installed side by side. Only prod (com.neteru.mobileussdcodex) updates the Play Store app.
To update the existing Play Store listing:
- Sign
prodwith the legacy app's key: theneteru-keyalias of the Neteru upload keystore, shared with the other Neteru apps. Put the keystore atandroid/app/upload-keystore.jksand its credentials inandroid/key.properties(template:android/key.properties.example). Both are gitignored;android/app/build.gradleuses them for release builds when present. - Keep
versionCodeabove the legacy12(versioninpubspec.yaml).
iOS flavors need a one-time Xcode setup (schemes and configurations per flavor) before --flavor works there. Until then, use flutter run without a flavor.
Pushing a v* tag (or running the workflow manually) builds an Android APK (prod flavor) and an unsigned iOS build in CI. Both builds need the quality job to pass first. The ENV_FILE secret, when set, provides the production .env; without it, CI uses .env.example.
USSD Codes is free software by Netersoft.
- Code: the source code (
lib/,test/,tool/and the platform folders) is licensed under the GNU General Public License v3.0. - Content: the texts, translations and pictures made by Netersoft for the app are licensed under Creative Commons Attribution-ShareAlike 4.0.
- Third-party files keep their own licenses: the Montserrat and Open Sans fonts (SIL Open Font License 1.1,
assets/fonts/*/OFL.txt). - Names and icons: the Netersoft name, the USSD Codes and Codes USSD names, and the app icons and logos (
assets/images/launcher/) are not covered by these licenses. A modified version must use another name and icon.
Copyright © 2018-2026 Netersoft.





