Ship a single-tap Android APK that bundles JSS for non-technical users. Realizes part of #46 ("Solid Pod on Every Phone").
History: original framing was Flutter; pivoted to native Kotlin after research showed there's no maintained Flutter↔nodejs-mobile plugin, and that the plugin layer is unnecessary for a WebView-shell architecture. Decision rationale in this comment.
Architecture
- Native Android Studio project (Kotlin), single MainActivity
- libnode.so linked directly via JNI/CMake — vendored from nodejs-mobile/nodejs-mobile releases
- ~80 lines of C++ (JNI shim + stdout/stderr → logcat)
- Foreground service wrapping the Node thread (persistent notification)
- WebView pointed at http://127.0.0.1:4443/
- JSS bundled as APK assets (full node_modules/, copied to Context.filesDir on first launch — ~62 MB tree per scripts/bundle-jss.sh)
- All deps are pure JS — see feasibility spike
Repo
https://github.com/JavaScriptSolidServer/jss-android (default branch: gh-pages)
v1 scope (Android only)
- Repo scaffolded with README + ARCHITECTURE + LICENSE
- scripts/bundle-jss.sh — pulls JSS from npm, installs prod deps, refuses to bundle native modules
- Launch args verified end-to-end on dev box: bin/jss.js start --single-user --port 4443 --host 127.0.0.1 --root <files-dir>/data --idp
- Android Studio Kotlin project bones (gradle, manifest, MainActivity, theme)
- scripts/fetch-libnode.sh — pulls libnode.so for arm64-v8a + armeabi-v7a from nodejs-mobile releases
- JNI shim (native-lib.cpp, ~80 LOC, lifted from JaneaSystems samples)
- Foreground service + persistent notification ("JSS pod running")
- WebView wired to http://127.0.0.1:4443/, with port-bind retry (4443 → 4444 → ...)
- First-launch asset copy from APK assets to Context.filesDir
- AAB build with ABI splits (arm64-v8a, armeabi-v7a)
- Documented v1 caveat: --git, --terminal disabled (both shell out via child_process, not supported by nodejs-mobile)
v1 caveats
- No --git, no --terminal — nodejs-mobile's sandboxed Node disallows child_process.
- Loopback only by default (HTTP, not HTTPS). Public exposure path is --tunnel against a remote JSS.
- Node 18.20.4 is the upstream mobile build (Node 18 EOL'd April 2025). 127.0.0.1 bind cuts the attack surface materially; long-term watch for a community Node 20/22 mobile build.
- APK size: libnode is ~30 MB/ABI. Ship as AAB so Play Store delivers per-device.
Out of scope (v1)
- iOS — App Store rule 2.5.2 grey zone on dynamic JS eval; needs separate audit.
- postmarketOS / Linux ARM64 — later.
- A native (Compose/Views) UI replacing the WebView — v2.
Prior art for this pattern
Refs
Reactions are currently unavailable
Ship a single-tap Android APK that bundles JSS for non-technical users. Realizes part of #46 ("Solid Pod on Every Phone").
Architecture
Repo
https://github.com/JavaScriptSolidServer/jss-android (default branch: gh-pages)
v1 scope (Android only)
v1 caveats
Out of scope (v1)
Prior art for this pattern
Refs