Files
zapstore/README.md
T

3.9 KiB

Zapstore

Release Kotlin Compose

Zapstore is an open Android app store where apps can be published directly by developers and curated by communities.

It combines app discovery, publisher identity, direct APK distribution, and social trust signals into a different model for Android app distribution.

This repo is the Kotlin / Jetpack Compose client for Zapstore. Catalog listings, curated stacks, releases, and publisher profiles sync from Nostr relays through the local iolite module.

Get the app

The production APK is still published from the Flutter client. This tree is the Kotlin rewrite (dev.zapstore.beta).

GitHub Releases · zapstore.dev

Requirements

  • JDK 21
  • Android SDK (compile / target API 37, min SDK 29)
  • An arm64-v8a device for make run (this is the only ABI the app ships).

Build from source

make build

That runs ./gradlew assembleDebug. The debug APK lands in build/outputs/apk/debug/. Set CATALOG_BUNDLE to a tar.zst seed and make build, make run, and make release copy it to src/main/assets/bundle-0-1.tar.zst. Without it, the APK ships no catalog bundle. First launch then requests GET /deltas?from=0 from wss://brelay.zapstore.dev and imports that bundle.

Tor uses a size-optimized libarti_android.so from tools/arti-build (Amethyst's JNI wrapper, zapstore package names). Rebuild the arm64-v8a library and commit it when bumping Arti:

make vendor

That needs rustup, cargo-ndk at the version in tools/arti-build/CARGO_NDK_VERSION, and the NDK revision in tools/arti-build/ANDROID_NDK_VERSION.

make run            # installDebug, launch, then press r to rebuild
make run-release    # assembleRelease (R8), install, launch

make install clears app data and embeds CATALOG_BUNDLE when that path is set. make build only builds.

The catalog relay URLs and signer come from that bundle's signed manifest, not from the build. make run-release reverses port 3334 so a bundle that lists ws://127.0.0.1:3334 can reach a relay on the host.

Release builds run R8 (minify + optimize + shrink resources, English locales only). Mapping lands in build/outputs/mapping/release/.

Or call Gradle directly (a seed in src/main/assets/ is packaged if present):

./gradlew assembleDebug
./gradlew installDebug
./gradlew test

./gradlew test runs unit tests for the app and iolite. Instrumented UI tests need a connected device:

./gradlew connectedDebugAndroidTest

Layout

  • src/main/kotlin/dev/zapstore/app/ — ZapstoreApplication (singletons), MainActivity (routes), AppConfig (build-time endpoints and query options)
    • screens/ — one *Screen.kt + *ViewModel.kt per destination (Home, AppDetail, StackDetail, Profile, Updates, Settings)
    • components/ — shared UI on Iolite records (AppCard, StackCard, AppList, ProfileImage, primitives)
    • catalog/ — CatalogSync (foreground GET /deltas) and installed-package matching
    • transport/ — Tor/direct network runtime
  • tools/arti-build/ — reproducible Arti JNI build; make vendor writes src/main/jniLibs/arm64-v8a/libarti_android.so
  • iolite/ — local-first Nostr client: SQLite rows derived from verified events, relay sessions, typed queries

Contributing

Minor fixes: PRs welcome. For larger changes, please reach out first while the project is in beta.