Phandroid — the Phanpy Mastodon web client, wrapped as a native Android app with Capacitor. Install via Obtainium; see the README.
  • JavaScript 79.7%
  • CSS 17.4%
  • Python 1.8%
  • Kotlin 0.6%
  • Shell 0.3%
  • Other 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-22 08:25:33 +00:00
.forgejo/workflows fix: a rebase or cherry-pick can no longer lose a fork-owned file silently 2026-10-19 07:13:31 +02:00
.github Use more defaults, rebuild table when yml changes 2026-10-13 12:47:41 +08:00
android chore(release): bump to 2.0.84 (auto, upstream merge) 2026-10-22 08:25:33 +00:00
assets feat(android): branded adaptive launcher icon and splash screens 2026-07-07 18:42:24 +02:00
compose initial-scale no longer needed 2026-10-08 19:03:22 +08:00
design feat: import Phanpy web app as project base 2026-07-07 18:12:48 +02:00
fastlane/metadata/android docs: fastlane dir was a trap; en.po noise and the timeline cap trade-off undocumented 2026-10-11 16:01:15 +02:00
fdroid fix: fdroid config hardcodet the runner image's SDK path 2026-10-11 15:38:42 +02:00
public initial-scale no longer needed 2026-10-08 19:03:22 +08:00
readme-assets feat: import Phanpy web app as project base 2026-07-07 18:12:48 +02:00
scripts fix: the What's New converter must not leave a heading in the text 2026-10-19 20:32:28 +02:00
src Merge remote-tracking branch 'upstream/main' 2026-10-22 08:17:16 +00:00
tests Try upgrade react-hotkeys-hook again 2026-09-27 23:56:59 +08:00
tests-phandroid fix: status bar style was set once and never followed the theme 2026-10-11 17:00:02 +02:00
.env docs: record that the GIPHY key in .env is deliberate, not a leak 2026-10-11 18:02:47 +02:00
.env.production feat: import Phanpy web app as project base 2026-07-07 18:12:48 +02:00
.gitattributes fix: a rebase or cherry-pick can no longer lose a fork-owned file silently 2026-10-19 07:13:31 +02:00
.gitignore test: unit tests for the F-Droid What's-New converter, gated before signing 2026-10-07 18:32:13 +02:00
.oxfmtrc.json feat: import Phanpy web app as project base 2026-07-07 18:12:48 +02:00
.release.env.example fix(dist): release-gitea.sh works on bash 3.2 + auto-loads token 2026-07-08 10:24:40 +02:00
capacitor.config.json fix: shared text cannot delete private files; localised decrypt notice; hygiene 2026-10-06 19:29:44 +02:00
CHANGELOG.md chore(release): bump to 2.0.84 (auto, upstream merge) 2026-10-22 08:25:33 +00:00
CHANGELOG.phanpy.md feat: import Phanpy web app as project base 2026-07-07 18:12:48 +02:00
crowdin.yml feat: import Phanpy web app as project base 2026-07-07 18:12:48 +02:00
env.schema.json feat: import Phanpy web app as project base 2026-07-07 18:12:48 +02:00
index.html initial-scale no longer needed 2026-10-08 19:03:22 +08:00
LICENSE Initial commit 2026-07-07 17:48:47 +02:00
lingui.config.js new config style for lingui 2026-10-16 10:09:34 +08:00
package-lock.json chore(release): bump to 2.0.81 (auto, upstream merge) 2026-10-19 14:25:56 +00:00
package.json Merge remote-tracking branch 'upstream/main' 2026-10-19 14:17:40 +00:00
PHANDROID_CUSTOMIZATIONS.md fix: a rebase or cherry-pick can no longer lose a fork-owned file silently 2026-10-19 07:13:31 +02:00
playwright.config.js feat: import Phanpy web app as project base 2026-07-07 18:12:48 +02:00
playwright.phandroid.config.js test: Phandroid's own Playwright tests, gated in the sync and before signing 2026-10-06 19:51:39 +02:00
PRIVACY.MD fix: PRIVACY.MD missed a third-party server and Rollbar was only presumed gone 2026-10-11 15:46:12 +02:00
README.md Update README.md 2026-10-18 00:02:48 +00:00
rollbar.js security: drop inherited Phanpy Rollbar client token from rollbar.js 2026-07-23 16:41:43 +00:00
SECURITY.md docs: Phandroid's own SECURITY.md; keep SECURITY/PRIVACY on upstream merges 2026-10-06 18:54:52 +02:00
vite.config.js Merge remote-tracking branch 'upstream/main' 2026-10-14 08:17:39 +00:00
wrangler.jsonc [autofix.ci] apply automated fixes 2026-10-03 13:04:08 +00:00

Phandroid

This is a fork of Phanpy, with the goal of making it installable as an Android app.

It uses Capacitor to wrap the Phanpy web app into a native Android app — the same approach iPhanpy takes for iOS. Rather than reimplementing the UI natively, Phandroid ships the proven Phanpy web client inside an Android WebView shell and adds a thin, well-isolated layer of Android-specific tweaks (deep-link OAuth, native camera, in-app browser, hardware back button, edge-to-edge insets).

Built with LLM: this Android port — the Capacitor integration, the Android-specific override layer and the surrounding tooling — was created with the assistance of a large language model.

Status: released and installable from the self-hosted F-Droid repository at fdroid.umrath.dev — works with F-Droid clients and Obtainium (see Installation). Supports OAuth login, native camera, an in-app browser, an Android share target, edge-to-edge UI and optional FOSS push (UnifiedPush). See CHANGELOG.md and PHANDROID_CUSTOMIZATIONS.md for details.

Channels

Phandroid ships as two side-by-side apps, each tracking a different Phanpy branch. Install either — or both; they don't conflict (separate app id, data and OAuth scheme).

Phandroid (stable) Phandroid Dev (bleeding)
applicationId dev.umrath.android.phanpy dev.umrath.android.phanpy.dev
OAuth scheme phandroid:// phandroiddev://
tracks Phanpy production Phanpy main
updates curated releases — F-Droid repo / Obtainium automatic, every upstream change — F-Droid repo / Obtainium

Start with Phandroid. Phandroid Dev sees new Phanpy changes sooner but may break more often; it installs next to the stable app with its own accounts and settings.

Installation

⚠️ Upgrading from a pre-2.0.0 build? Reinstall required. Version 2.0.0 changes the app package id to dev.umrath.android.phanpy. Android treats the new package as a different app, so it cannot update in place: uninstall the old Phandroid, then install this one from the F-Droid repository below. Logged-in accounts, settings and push registration do not transfer and must be set up again (the signing key and the phandroid:// login are unchanged). If you added the app in Obtainium from the old source, remove it there and re-add it from the F-Droid repository below.

Phandroid is distributed as a signed APK — not on the Play Store.

  1. Install Obtainium (from F-Droid or its GitHub releases).

  2. In Obtainium tap Add App, choose the source type F-Droid Third-Party Repo, and paste the URL for the channel you want:

    https://fdroid.umrath.dev/repo?appId=dev.umrath.android.phanpy
    
  3. Tap Add, then Install — this gives you the stable Phandroid, updated automatically.

To follow Phandroid Dev (instead of, or alongside, the stable app), add a second app the same way with:

https://fdroid.umrath.dev/repo?appId=dev.umrath.android.phanpy.dev

The ?appId= in the URL selects the channel — no further options needed. Phandroid Dev installs alongside the stable app as a separate package.

Via the F-Droid repo (auto-updates)

Add the self-hosted F-Droid repository once, then install Phandroid from it — a compatible client (the F-Droid app, Droid-ify or Neo Store) then checks it for updates automatically.

  1. In your F-Droid client open Settings → Repositories → Add repository and paste:

    https://fdroid.umrath.dev/repo?fingerprint=732DC12007C2873A07AA5E27DB47667F5A08E392C882E13C46D1480C7727CF19
    

    The fingerprint pins the repo to its signing key — keep it in the URL.

  2. Refresh the repo — it lists both apps: Phandroid (stable) and Phandroid Dev (bleeding). Install whichever you want, or both side by side.

All APKs are signed with the developer's own key, so you can move between the F-Droid client, Obtainium and a sideloaded APK without reinstalling.

Direct APK (sideload)

Download the latest phandroid-vX.Y.Z.apk (the stable Phandroid) from the releases page and open it to install (allow "install unknown apps" for your browser / file manager if prompted). The …-vX.Y.Z-dev.apk releases are Phandroid Dev — a separate app, not an update to the stable one.

Push notifications (optional, FOSS — no Google)

Phandroid uses UnifiedPush: encrypted Web Push, decrypted on-device, with no Google/FCM.

  1. Install a UnifiedPush distributor, e.g. Sunup. Open it once and grant its permissions (notifications + battery-optimization exemption — it keeps the push connection alive).
  2. In Phandroid go to Settings → Push Notifications (beta), turn it on and choose which notification types you want.
  3. Allow the two prompts Phandroid then shows: the notification permission and the battery-optimization exemption (so push keeps working reliably).

Building

Phandroid is a Capacitor app: the web client is built with Vite, then wrapped by the native Android project under android/.

Prerequisites

  • Node.js 22+ and npm 10.x
  • Android Studio with an Android SDK (platform android-35 and build-tools 35) — required to compile and run the APK
  • A JDK 17–21 (Android Studio bundles a suitable JDK; JDK 21 is known to work)

1. Install and build the web app

npm install
npm run build          # outputs to dist/
npx cap sync android
npx cap open android

Then run the app on an emulator or a connected device from Android Studio.

2b. Or build a debug APK from the command line

Point Gradle at your SDK by creating android/local.properties with sdk.dir=/absolute/path/to/Android/sdk, then:

npx cap sync android
JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home" \
  ./android/gradlew -p android :app:assembleDebug

The APK is written to android/app/build/outputs/apk/debug/app-debug.apk.

Live reload during development

npx cap run android --livereload --external

Regenerating the launcher icon / splash

npx capacitor-assets generate --android

(reads assets/logo.png; the adaptive icon background colour is set in android/app/src/main/res/values/ic_launcher_background.xml).

Credits