The Multiplatform Emulation Frontend.
196
stars
568
commits
Dart
primary language
Sep 9, 2026
updated
NeoStation provides a fast, lightweight, and customizable experience for managing and launching retro games across desktop and mobile devices, with seamless integration for RetroArch and standalone emulators.
.m3u playlists for your multi-disc games and organize them into game folders.The built-in organizer helps prepare multi-disc games for emulators that use .m3u playlists:
Disc, Disk, or CD filename markers..m3u playlist. Existing playlists are reused rather than duplicated.Folders that already contain .m3u playlists are skipped during the scan.
| Platform | Status | Notes |
|---|---|---|
| Windows | ✅ Supported | x64 |
| Linux | ✅ Supported | x64, ARM64 (AppImage, Flatpak) |
| macOS | ✅ Supported | Apple Silicon & Intel |
| Android | ✅ Supported | ARM64, Android TV compatible |
.fvmrc, and
pubspec.lock is committed as that version resolves it. Build on the pinned
version (fvm use reads .fvmrc directly) or CI will reject your lockfile:
every job runs flutter pub get --enforce-lockfile.# Coming soon to Flathub! In the meantime, you can build locally:
flatpak-builder --user --install-deps-from=flathub \
--repo=repo --force-clean \
build-dir linux/flatpak/com.neogamelab.neostation.yml
Download the x86_64 AppImage, then add it to Steam and launch it from there — either from Game Mode, or from the desktop with Steam running:
.AppImage by default)This matters for the controls. With Steam not running, the Deck's controller sits in lizard mode, where the hardware emulates a keyboard and mouse instead of a gamepad: the D-pad sends arrow keys, A/B send Enter/Escape, the trackpad moves the mouse pointer, and the bumpers send nothing at all. Running through Steam hands the app a proper virtual gamepad, and every button works.
So if the shoulder buttons seem dead, or A/B behave oddly, or a mouse cursor sits on screen, the app isn't at fault — it's being run outside Steam.
# Clone the repository
git clone https://github.com/misobadev/neostation-frontend.git
cd neostation-frontend
# Install dependencies
flutter pub get
NeoStation uses compile-time environment variables (--dart-define) for Flutter configuration, and Gradle properties for Android signing. No .env files are required at runtime.
--dart-define or .env)Create a .env file from .env.example for local development.
| Variable | Description |
|---|---|
SCREENSCRAPER_DEV_ID | ScreenScraper developer ID |
SCREENSCRAPER_DEV_PASSWORD | ScreenScraper developer password |
RetroAchievements no longer uses a build-time key. Each user signs in with their own RetroAchievements username and web API key (from retroachievements.org/controlpanel.php) inside the app.
If you want your release APKs signed with a release certificate (required for app store distribution and seamless user upgrades), create android/key.properties from android/key.properties.example.
storePassword=your_password
keyPassword=your_password
keyAlias=upload
storeFile=../release.jks
If android/key.properties is not present, the build automatically falls back to debug signing, which is sufficient for local testing and sideloading.
The release workflow (.github/workflows/build-and-deploy.yml) reads build secrets from your repository. You can store them as Environment secrets.
Required for all platforms:
| Secret / Variable | Description |
|---|---|
SCREENSCRAPER_DEV_ID | ScreenScraper developer ID |
SCREENSCRAPER_DEV_PASSWORD | ScreenScraper developer password |
Required for Android release signing:
| Secret | Description |
|---|---|
ANDROID_KEYSTORE_BASE64 | Your release.jks file encoded as base64 (binary, not text). See below. |
ANDROID_KEYSTORE_PASSWORD | Keystore password |
ANDROID_KEY_PASSWORD | Key password |
ANDROID_KEY_ALIAS | Key alias (e.g. upload) |
Important:
ANDROID_KEYSTORE_BASE64must be the binary keystore file (.jks), not thekey.propertiestext file. To encode it:# Linux / macOS base64 -w 0 release.jks # Windows PowerShell [Convert]::ToBase64String([IO.File]::ReadAllBytes("release.jks"))
If the Android secrets are missing, the CI build falls back to debug signing (users will need to uninstall before installing a new release).
# Development
flutter run \
--dart-define=SCREENSCRAPER_DEV_ID=your_id \
--dart-define=SCREENSCRAPER_DEV_PASSWORD=your_password
# Production builds
# Replace these with your actual keys
DART_DEFINES="--dart-define=SCREENSCRAPER_DEV_ID=your_id --dart-define=SCREENSCRAPER_DEV_PASSWORD=your_password"
# Android APK
flutter build apk --release $DART_DEFINES
# Windows
flutter build windows --release $DART_DEFINES
# Linux
flutter build linux --release $DART_DEFINES
# macOS
flutter build macos --release $DART_DEFINES
lib/
├── data/
│ └── datasources/ # SQLite access, migrations, raw queries
├── l10n/ # Localization files (12 languages)
├── models/ # Data models
├── providers/ # ChangeNotifier state management
├── repositories/ # Data access abstraction layer
├── screens/ # Application pages
├── services/ # Business logic and external APIs
├── sync/ # Provider-agnostic cloud sync (SyncManager + adapters)
├── themes/ # App themes
├── utils/ # Helpers and utilities
├── widgets/ # Reusable UI components
├── main.dart # Entry point
For more details, see ARCHITECTURE.md.
NeoStation is built upon the incredible work of the open-source community. To achieve the specific performance and compatibility goals of this project, we utilize modified versions of several libraries.
These packages are "vendored" within the /packages directory to ensure long-term stability and to include custom optimizations:
| Package | Description |
|---|---|
gamepads | Cross-platform gamepad input (based on Flame Engine's gamepads) |
flutter_7zip | FFI bindings for 7-Zip archive extraction |
NeoStation's system configurations, emulator definitions, and launch arguments are maintained in this repository under assets/systems/.
If you want to add new emulators, fix launch arguments, or update system configurations, please open a pull request here.
The bundled assets/manifest.json drives the over-the-air systems update mechanism, so compatible changes can be delivered to existing installs without requiring a full app release.
Please read CONTRIBUTING.md for guidelines on bug reports, feature requests, and pull requests.
If you discover a security vulnerability, please follow the instructions in SECURITY.md to report it responsibly.
These co-maintainers and collaborators work very hard to make NeoStation what it is today.
This project is licensed under the GNU General Public License v3.0 (GPL-3.0). See LICENSE.md for details.
Third-party components and assets have their own licenses — see NOTICE.
Dart
79.2%
C
17.3%
Kotlin
1.7%
The Multiplatform Emulation Frontend.
196
stars
568
commits
Dart
primary language
Sep 9, 2026
updated
NeoStation provides a fast, lightweight, and customizable experience for managing and launching retro games across desktop and mobile devices, with seamless integration for RetroArch and standalone emulators.
.m3u playlists for your multi-disc games and organize them into game folders.The built-in organizer helps prepare multi-disc games for emulators that use .m3u playlists:
Disc, Disk, or CD filename markers..m3u playlist. Existing playlists are reused rather than duplicated.Folders that already contain .m3u playlists are skipped during the scan.
| Platform | Status | Notes |
|---|---|---|
| Windows | ✅ Supported | x64 |
| Linux | ✅ Supported | x64, ARM64 (AppImage, Flatpak) |
| macOS | ✅ Supported | Apple Silicon & Intel |
| Android | ✅ Supported | ARM64, Android TV compatible |
.fvmrc, and
pubspec.lock is committed as that version resolves it. Build on the pinned
version (fvm use reads .fvmrc directly) or CI will reject your lockfile:
every job runs flutter pub get --enforce-lockfile.# Coming soon to Flathub! In the meantime, you can build locally:
flatpak-builder --user --install-deps-from=flathub \
--repo=repo --force-clean \
build-dir linux/flatpak/com.neogamelab.neostation.yml
Download the x86_64 AppImage, then add it to Steam and launch it from there — either from Game Mode, or from the desktop with Steam running:
.AppImage by default)This matters for the controls. With Steam not running, the Deck's controller sits in lizard mode, where the hardware emulates a keyboard and mouse instead of a gamepad: the D-pad sends arrow keys, A/B send Enter/Escape, the trackpad moves the mouse pointer, and the bumpers send nothing at all. Running through Steam hands the app a proper virtual gamepad, and every button works.
So if the shoulder buttons seem dead, or A/B behave oddly, or a mouse cursor sits on screen, the app isn't at fault — it's being run outside Steam.
# Clone the repository
git clone https://github.com/misobadev/neostation-frontend.git
cd neostation-frontend
# Install dependencies
flutter pub get
NeoStation uses compile-time environment variables (--dart-define) for Flutter configuration, and Gradle properties for Android signing. No .env files are required at runtime.
--dart-define or .env)Create a .env file from .env.example for local development.
| Variable | Description |
|---|---|
SCREENSCRAPER_DEV_ID | ScreenScraper developer ID |
SCREENSCRAPER_DEV_PASSWORD | ScreenScraper developer password |
RetroAchievements no longer uses a build-time key. Each user signs in with their own RetroAchievements username and web API key (from retroachievements.org/controlpanel.php) inside the app.
If you want your release APKs signed with a release certificate (required for app store distribution and seamless user upgrades), create android/key.properties from android/key.properties.example.
storePassword=your_password
keyPassword=your_password
keyAlias=upload
storeFile=../release.jks
If android/key.properties is not present, the build automatically falls back to debug signing, which is sufficient for local testing and sideloading.
The release workflow (.github/workflows/build-and-deploy.yml) reads build secrets from your repository. You can store them as Environment secrets.
Required for all platforms:
| Secret / Variable | Description |
|---|---|
SCREENSCRAPER_DEV_ID | ScreenScraper developer ID |
SCREENSCRAPER_DEV_PASSWORD | ScreenScraper developer password |
Required for Android release signing:
| Secret | Description |
|---|---|
ANDROID_KEYSTORE_BASE64 | Your release.jks file encoded as base64 (binary, not text). See below. |
ANDROID_KEYSTORE_PASSWORD | Keystore password |
ANDROID_KEY_PASSWORD | Key password |
ANDROID_KEY_ALIAS | Key alias (e.g. upload) |
Important:
ANDROID_KEYSTORE_BASE64must be the binary keystore file (.jks), not thekey.propertiestext file. To encode it:# Linux / macOS base64 -w 0 release.jks # Windows PowerShell [Convert]::ToBase64String([IO.File]::ReadAllBytes("release.jks"))
If the Android secrets are missing, the CI build falls back to debug signing (users will need to uninstall before installing a new release).
# Development
flutter run \
--dart-define=SCREENSCRAPER_DEV_ID=your_id \
--dart-define=SCREENSCRAPER_DEV_PASSWORD=your_password
# Production builds
# Replace these with your actual keys
DART_DEFINES="--dart-define=SCREENSCRAPER_DEV_ID=your_id --dart-define=SCREENSCRAPER_DEV_PASSWORD=your_password"
# Android APK
flutter build apk --release $DART_DEFINES
# Windows
flutter build windows --release $DART_DEFINES
# Linux
flutter build linux --release $DART_DEFINES
# macOS
flutter build macos --release $DART_DEFINES
lib/
├── data/
│ └── datasources/ # SQLite access, migrations, raw queries
├── l10n/ # Localization files (12 languages)
├── models/ # Data models
├── providers/ # ChangeNotifier state management
├── repositories/ # Data access abstraction layer
├── screens/ # Application pages
├── services/ # Business logic and external APIs
├── sync/ # Provider-agnostic cloud sync (SyncManager + adapters)
├── themes/ # App themes
├── utils/ # Helpers and utilities
├── widgets/ # Reusable UI components
├── main.dart # Entry point
For more details, see ARCHITECTURE.md.
NeoStation is built upon the incredible work of the open-source community. To achieve the specific performance and compatibility goals of this project, we utilize modified versions of several libraries.
These packages are "vendored" within the /packages directory to ensure long-term stability and to include custom optimizations:
| Package | Description |
|---|---|
gamepads | Cross-platform gamepad input (based on Flame Engine's gamepads) |
flutter_7zip | FFI bindings for 7-Zip archive extraction |
NeoStation's system configurations, emulator definitions, and launch arguments are maintained in this repository under assets/systems/.
If you want to add new emulators, fix launch arguments, or update system configurations, please open a pull request here.
The bundled assets/manifest.json drives the over-the-air systems update mechanism, so compatible changes can be delivered to existing installs without requiring a full app release.
Please read CONTRIBUTING.md for guidelines on bug reports, feature requests, and pull requests.
If you discover a security vulnerability, please follow the instructions in SECURITY.md to report it responsibly.
These co-maintainers and collaborators work very hard to make NeoStation what it is today.
This project is licensed under the GNU General Public License v3.0 (GPL-3.0). See LICENSE.md for details.
Third-party components and assets have their own licenses — see NOTICE.
Dart
79.2%
C
17.3%
Kotlin
1.7%