An unofficial, minimal Android shell for the maintained Pokémon Showdown website.
Animated Android device capture from a live guest Random Battle. The upstream site is loaded live; its client code and assets are not bundled in this repository or APK.
Showdown Web Client displays play.pokemonshowdown.com as the top-level page in a native Android WebView. The native layer is intentionally limited to safe areas, loading and retry states, URL policy, persistent WebView storage, lifecycle behavior, and Android Back handling.
This is not an official Pokémon Showdown app, a native battle client, a local Showdown server, or an offline client. It does not bundle, fork, proxy, or iframe the upstream client. A minimal first-run bootstrap only initializes Showdown's official theme preference when no theme has been chosen.
| Area | Behavior |
|---|---|
| Native shell | Safe areas, loading/error/retry UI, external-link handoff, and Android Back integration |
| Web client | Served directly by the production Pokémon Showdown site |
| Persistence | App-local WebView cookies, local storage, teams, and preferences survive relaunch |
| Appearance | New profiles default to Match system theme; Light and Dark choices remain available and persist |
| Navigation | Only the exact HTTPS host play.pokemonshowdown.com stays in-app |
| Privacy | No analytics, ads, native credential collection, notifications, camera, microphone, location, or storage access |
| Platform | Android 7.0+; portrait and landscape |
A network connection is required. Upstream outages or incompatible website changes can affect the app without an APK update. Chrome cookies and sessions are not shared with Android WebView.
Requirements: Node.js 24+, pnpm 11.11.0, Just, JDK 17, and a writable Android SDK.
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export ANDROID_SDK_ROOT="$HOME/.local/share/android-sdk"
export PATH="$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$PATH"
just doctor
just install
just startIn another terminal, generate the native project and run it on an emulator or attached device:
pnpm androidThe generated android/ directory is intentionally ignored. app.json and Expo prebuild are the native source of truth.
| Command | Purpose |
|---|---|
just install |
Install exactly the locked dependency graph |
just start |
Start Expo Metro |
just generate |
Cleanly regenerate the Android project |
just debug |
Build the debug APK |
just install-debug |
Build and install the debug APK |
just release |
Build a locally installable release APK |
just verify |
Run dependency, test, type, lint, and format checks |
just build-apks |
Run Android lint, assemble both APK variants, and verify release metadata |
just build |
Run the complete local verification and APK build |
just is the canonical workflow surface. Equivalent pnpm scripts remain as compatibility wrappers.
Every pull request and push to main runs two GitHub Actions jobs:
| Gate | What it proves |
|---|---|
| Locked install | pnpm-lock.yaml resolves unchanged with --frozen-lockfile |
| Expo dependency check | Installed package versions match Expo SDK 57 requirements |
| Navigation contracts | Vitest exercises exact-host routing, external handoff, and blocked schemes |
| Strict TypeScript | The Expo entry point, WebView shell, and tests type-check without emitting files |
| Biome | Supported source and configuration files pass the repository formatter and linter |
| Android lint | The generated release project passes Android's static analysis |
| Android build | A clean Expo prebuild assembles both debug and release APK variants with JDK 17 |
| APK contract | The release APK keeps the expected identifier, version, SDK levels, launcher, backup policy, and minimal permissions |
The source-verification job must pass before the Android build begins. CI builds are verification artifacts only; the repository does not publish or promote an APK from CI or GitHub Releases.
Live production-service behavior cannot be made deterministic on a hosted CI runner. The USB device suite below remains the required pre-release acceptance pass.
Start Metro once, connect exactly one authorized Android device, then run the flows serially:
just qa-metro
# In another terminal:
just qa-allIndividual flows are also available:
just qa-teambuilder
just qa-layout
just qa-navigation
just qa-battle
just qa-assets
just qa-offlineThe device suite checks:
- portrait and landscape layout plus keyboard resize
- WebView persistence across force-stop and relaunch
- Android Back history and app-exit behavior
- internal, external, popup, and blocked navigation policy
- a real guest Random Battle WebSocket flow with cleanup
- offline error handling and retry recovery
- live icon sheets, type/category icons, representative front/back sprites, and multi-frame animated GIFs
- bounded logcat output for application crashes and fatal native exceptions
Screenshots, UI hierarchy XML, asset reports, and bounded logcat evidence are written under the ignored .qa/ directory.
Local APKs are written to:
- Debug:
android/app/build/outputs/apk/debug/app-debug.apk - Release:
android/app/build/outputs/apk/release/app-release.apk
Expo's generated local release configuration uses the debug signing key. The resulting release APK is suitable for local verification only; it is not production-signed for Google Play or public distribution.
This repository's source is licensed under AGPL-3.0-only.
- Maintained web client: smogon/pokemon-showdown-client — AGPLv3
- Official server: smogon/pokemon-showdown — MIT
- Inspected protocol reference: castdrian/showdown-ds
No Pokémon Showdown client/server code or assets and no showdown-ds code or assets are vendored into this repository.
Pokémon, Pokémon Showdown, and related names and marks belong to their respective owners. This project is unofficial, unaffiliated, and must not be presented as endorsed by The Pokémon Company, Nintendo, Game Freak, Creatures, Smogon, or the Pokémon Showdown maintainers. Public app-store distribution under Pokémon-related naming or branding requires separate trademark and store-policy review.
