thermograph/infra/deploy/twa/README.md
Emi Griffith ae1d9bb534 Subtree-merge thermograph-infra (origin/main) into infra/
git-subtree-dir: infra
git-subtree-mainline: d6df04eab2
git-subtree-split: 99b4b3f78d
2026-07-22 22:01:11 -07:00

3.7 KiB

Thermograph Android app (Trusted Web Activity)

The Android app is a Trusted Web Activity (TWA): a thin native shell that opens https://thermograph.org full-screen in the user's Chrome engine. It is the live PWA — no content is duplicated, and the existing service worker + VAPID web push keeps working inside the app via Android notification delegation (no Firebase, no backend change). enableNotifications: true in twa-manifest.json turns that on and wires the Android 13+ POST_NOTIFICATIONS runtime permission.

This folder holds the build config. Building the APK is a local/manual step — it needs a JDK, the Android SDK, and a signing keystore that only you should hold. The current goal is a signed APK you sideload for testing; Play Store submission ($25 one-time) is deferred.

What's in the repo

  • twa-manifest.json — Bubblewrap config (reference values; see comment inside).
  • ../../frontend/.well-known/assetlinks.json — Digital Asset Links, served at https://thermograph.org/.well-known/assetlinks.json. Its fingerprint is a placeholder until you generate the signing key (step 4).

One-time build (you)

Prereqs: Node 18+, JDK 17. Bubblewrap can download the Android SDK for you.

npm install -g @bubblewrap/cli

# 1. Scaffold from the live manifest (creates ./twa-manifest.json + a keystore).
#    Accept defaults, then reconcile with this repo's twa-manifest.json — in
#    particular set:  packageId = org.thermograph.twa,  enableNotifications = true.
bubblewrap init --manifest https://thermograph.org/manifest.webmanifest

# 2. (Or) copy this repo's config and let Bubblewrap fill the SDK bits:
#    cp deploy/twa/twa-manifest.json ./twa-manifest.json && bubblewrap update

# 3. Build the signed APK (and .aab for the store, for later).
bubblewrap build
#    -> ./app-release-signed.apk  and  ./app-release-bundle.aab
# Print the signing key's SHA-256 fingerprint:
bubblewrap fingerprint list          # or: keytool -list -v -keystore android-keystore.jks

Copy the SHA256 value into frontend/.well-known/assetlinks.json, replacing REPLACE_WITH_TWA_SIGNING_KEY_SHA256_FINGERPRINT, then deploy the site so the new file is live. Confirm:

curl -s https://thermograph.org/.well-known/assetlinks.json    # must show your fingerprint, Content-Type: application/json

If you later publish to Play Store with Play App Signing, add Google's app signing certificate fingerprint (from the Play Console) to assetlinks.json too — the upload-key fingerprint alone won't verify the store build.

5. Sideload and test

adb install app-release-signed.apk

On the device:

  • Launch Thermograph — it must open full-screen with no browser address bar (that confirms assetlinks verified).
  • Subscribe to a city (or trigger a test alert) and confirm the "unusual weather" push arrives as a native Android notification.
  • Grant the notifications permission when prompted (Android 13+).

Keep the keystore safe

android-keystore.jks is required for every future update and for the eventual Play Store listing. Losing it means a new package identity and a fresh install for every user. Store it out of the repo, backed up.

Deferred

  • Play Store listing ($25 one-time Google Play developer account). Upload the .aab; the store review for a well-formed TWA is light. Not part of this pass.

Why no backend changes

Android delegates the TWA's web notifications to the OS, so backend/push.py (VAPID) and backend/notify.py deliver push to the app unchanged. Nothing in backend/ is touched by this track.