A Flutter Shopping list app
  • Dart 74.4%
  • C++ 9.8%
  • CMake 7.8%
  • Shell 3.3%
  • Kotlin 2.8%
  • Other 1.9%
Find a file
SirSlader f6c11ad2e1 Release 3.0.1: fix the release-mode startup hang
- Bump to 3.0.1+4

- Point version.json at nyra.apk for v3.0.1

- Document the shared_preferences_android 2.5.2+ requirement
2026-10-23 18:10:12 -04:00
.agents/skills Update system was implemented for the app to receive updates 2026-06-19 12:26:16 -04:00
android feat: add the Nyra launcher icon across platforms 2026-10-23 15:38:22 -04:00
assets/fonts feat(ui): adopt the shared Slate + Sage design system 2026-10-15 15:59:04 -04:00
docs/releases Release 3.0.1: fix the release-mode startup hang 2026-10-23 18:10:12 -04:00
ios feat: add the Nyra launcher icon across platforms 2026-10-23 15:38:22 -04:00
lib fix: use the renamed nyra repo in release and update links 2026-10-23 12:55:17 -04:00
linux Rename app to Nyra (Keyworks Technology) 2026-10-21 21:36:09 -04:00
macos feat: add the Nyra launcher icon across platforms 2026-10-23 15:38:22 -04:00
test fix: keep shared_preferences JNI classes in release builds 2026-10-23 18:09:50 -04:00
tool fix: use the renamed nyra repo in release and update links 2026-10-23 12:55:17 -04:00
web feat: add the Nyra launcher icon across platforms 2026-10-23 15:38:22 -04:00
windows feat: add the Nyra launcher icon across platforms 2026-10-23 15:38:22 -04:00
.gitignore chore(release): wire shopping_list into the Command Center release pipeline 2026-10-15 15:43:36 -04:00
.metadata Code was rebuilt and logic was added 2026-06-18 14:54:06 -04:00
analysis_options.yaml Upgrade to Flutter 3.47, update plugins, fix bugs, bump Android toolchain 2026-08-24 20:12:50 -04:00
DEVELOPER_GUIDE.md fix: keep shared_preferences JNI classes in release builds 2026-10-23 18:09:50 -04:00
devtools_options.yaml Code was rebuilt and logic was added 2026-06-18 14:54:06 -04:00
pubspec.lock fix: keep shared_preferences JNI classes in release builds 2026-10-23 18:09:50 -04:00
pubspec.yaml Release 3.0.1: fix the release-mode startup hang 2026-10-23 18:10:12 -04:00
README.md fix: use the renamed nyra repo in release and update links 2026-10-23 12:55:17 -04:00
skills-lock.json Update system was implemented for the app to receive updates 2026-06-19 12:26:16 -04:00
version.json Release 3.0.1: fix the release-mode startup hang 2026-10-23 18:10:12 -04:00

Nyra

Nyra is a personal Flutter shopping list app by Keyworks Technology for keeping track of products, quantities, prices, tax, and totals.

The app is designed for personal sideloaded Android use and includes a lightweight in-app update check that can download a newer APK and open Android's installer.

Features

  • Create and switch between multiple shopping lists
  • Add products with:
    • Product name
    • Quantity selector
    • Price
  • Edit existing products
  • Mark products as purchased
  • Swipe products to delete them with undo support
  • Search and sort products
  • Clear the current list with confirmation
  • Calculate subtotal, purchased subtotal, tax, and final total automatically
  • Enter IVU/tax percentage
  • Set an optional budget and see remaining/over-budget status
  • Save lists, products, tax, budget, and theme preference locally
  • Responsive layout for phone, tablet, and desktop-sized windows
  • Settings/About screen with manual update check
  • Light, dark, and system theme modes (shared Slate + Sage palette)
  • Android sideload update flow:
    • Checks version.json on startup
    • Prompts when a newer version is available
    • Downloads the APK directly
    • Verifies the APK's detached .sig signature before installing
    • Opens Android's package installer
  • One-time “App Updated” message after a successful version upgrade
  • Tap the version in Settings → About to view the latest release notes

Tech Stack

  • Flutter / Dart
  • Provider for app state
  • Shared Slate + Sage design system (lib/ui/theme/) with a bundled Inter font
  • flutter_slidable for swipe-to-delete actions
  • http for update/version checks
  • package_info_plus for reading the installed app version
  • path_provider for temporarily storing downloaded APKs
  • shared_preferences for local app persistence and theme settings
  • Android platform channel for launching the APK installer

Getting Started

Prerequisites

Install Flutter and confirm your environment is ready:

flutter doctor

Install dependencies

flutter pub get

Run the app

flutter run

Build an Android APK

# Release builds are a single arm64-v8a APK (~20 MB); the universal APK ships
# all three ABIs (~57 MB). tool/release.sh builds arm64-only by default.
flutter build apk --release --target-platform android-arm64

The APK is generated at:

build/app/outputs/flutter-apk/app-release.apk

Update System

This app is not distributed through Google Play. Instead, it uses a custom version.json file hosted in this repository on the self-hosted Forgejo instance:

https://forgejo.sladertech.cloud/admslader/nyra/raw/branch/main/version.json

Example version.json:

{
  "version": "1.1.4",
  "download_url": "https://forgejo.sladertech.cloud/admslader/nyra/releases/download/v1.1.4/nyra.apk",
  "release_notes": "Describe what changed"
}

When the app opens, it compares the installed version from pubspec.yaml with the remote version.json. If the remote version is newer, it shows an update dialog.

On Android, tapping Update Now downloads the APK into the app cache, verifies its detached .sig signature against the key embedded in the app, and opens Android's installer. Android still requires the user to confirm installation manually. An update whose signature is missing or invalid is refused.

The Settings screen also includes a Check for updates action for manually checking the hosted version.json.

After a user installs an update and opens the app again, the app shows a one-time message confirming the installed version, for example:

Nyra has been updated to version 1.0.3.

Android install permission

Because this is a sideloaded app, Android may ask the user to allow this app to install unknown apps:

Settings → Install unknown apps → Nyra → Allow from this source

The app will open that settings screen automatically if permission is missing.

Release Workflow

Releases are driven from Orbita (the sibling orbita repo), which builds, signs, and publishes every app. The developer/agent only does the git work — never build or publish by hand.

  1. Bump the version in pubspec.yaml and update version.json to match:

    • pubspec.yaml: version: X.Y.Z
    • version.json:
      • version: same X.Y.Z
      • download_url: https://forgejo.sladertech.cloud/admslader/nyra/releases/download/vX.Y.Z/nyra.apk
      • release_notes: a short single-paragraph summary (shown in the in-app patch-notes screen)
  2. Draft docs/releases/vX.Y.Z.md — a title line, a one-line intro, then emoji-prefixed sections of one-line bullets (see the Developer Guide §12 for the style). Orbita uses this file as the Forgejo release body.

  3. Commit as Release X.Y.Z: <short title>, tag vX.Y.Z, and push main and the tag.

  4. Publish from Orbita — it builds the release APK, signs it, creates the Forgejo release for vX.Y.Z, and uploads the APK plus its signature:

    cd ../orbita
    dart run tool/release.dart status              # local vs. published version
    dart run tool/release.dart publish nyra
    

    FORGEJO_TOKEN is required. Each app keeps its own signing key; Command Center never touches it. nyra exposes tool/release.sh (build/sign/publish/all) and keeps its signing key in the gitignored tool/keys/release_private.json.

Nothing is live until Orbita publishes. You may move the tag while the release is unpublished; once published, its tag is frozen — cut a new version instead.

Users with an older installed version will be prompted to update the next time they open the app.

Important Notes

  • Silent self-updates are not allowed for normal Android apps. The app can download the APK, but Android requires the user to approve installation.
  • Future APKs must use the same Android package name: cloud.keyworks.nyra.
  • The package name changed from cloud.sladertech.shopping_list during the Nyra rename, so the first release under the new name must be installed fresh (export a backup, uninstall, install, import the backup). Later releases update in place normally.
  • Releases must be signed with the app's own release keystore (see the Developer Guide §12) — never the shared debug key.
  • Changing the package name or the signing key makes Android treat the build as a different app; existing installs must be uninstalled and reinstalled once.
  • The version in version.json must be higher than the installed app version for the update prompt to appear.

Repository

Forgejo: admslader/nyra