Ship Android app by wrapping the web build with Capacitor (#20) (#28)
Unit Tests / test (push) Successful in 11s

## Summary
- Closes #20
- Add Capacitor 7 to `llm-fe/` (`capacitor.config.ts`, appId `com.aimloperations.chat`, `webDir: build`) and commit the generated `android/` project
- npm scripts: `build:mobile` (`.env.mobile` + CRA build + `cap sync`), `android:open`, `android:sync`, `assets:generate`
- `.env.mobile` defaults to prod backend; override independently of web deploys
- Native chrome: Android back button (history / exit at root), status bar + keyboard resize, safe-area CSS; Preferences registered for JWT mirror (#22)
- Icons/splash via `@capacitor/assets`; signing via optional `keystore.properties`; docs in `llm-fe/ANDROID.md` + root README

Blockers #22 / #23 / #24 already on master.

## Test plan
- [x] `npm run test:ci` (79 tests)
- [x] `npm run build` + `npx cap add android` / `cap sync`
- [ ] `npm run build:mobile` + open in Android Studio on a machine with SDK
- [ ] Emulator/device QA: login, chat stream, theme, back button, keyboard/safe-area, WS resume
- [ ] Generate upload keystore outside repo; `./gradlew bundleRelease` for internal testing trackReviewed-on: #28
This commit was merged in pull request #28.
This commit is contained in:
2026-07-26 17:12:48 -07:00
parent b7f23eb16c
commit a4a28ef13e
94 changed files with 5541 additions and 9 deletions
+26 -5
View File
@@ -12,8 +12,8 @@ document root; the shared **web-static** nginx container from
[server-infra](https://git.aimloperations.com/ai_ml_operations/server-infra) serves
those assets. Same pattern as `dta_webapp`.
Android Capacitor shell (display name **Hesychia**) lands via the Capacitor wrap
PR; branding strings there use Hesychia once that tree is on `master`.
Android ships the same CRA `build/` via **Capacitor** (display name **Hesychia**;
see `llm-fe/ANDROID.md`).
## Domain migration
@@ -43,11 +43,16 @@ deploy webroots / NPM) when DNS and `server-infra` cut over to hesychia.ai.
chat_web_app/
├── README.md
├── .gitea/workflows/ # Unit tests + deploy-prod / deploy-beta
└── llm-fe/ # CRA npm root (+ Capacitor when Android wrap merges)
└── llm-fe/ # CRA + Capacitor npm root
├── package.json
├── capacitor.config.ts
├── ANDROID.md # Android build, signing, Play Store notes
├── android/ # Native Android project (committed)
├── assets/ # Source icon/splash for @capacitor/assets
├── .env.development # Local dev API/WS URLs
├── .env.beta
├── .env.production
├── .env.mobile # Capacitor shell API/WS URLs
├── public/
└── src/
├── axiosApi.js # Axios instances (JWT Authorization)
@@ -67,7 +72,7 @@ chat_web_app/
- **npm** (lockfile: `llm-fe/package-lock.json`)
- Running [chat_backend](https://git.aimloperations.com/ai_ml_operations/chat_backend)
locally for full chat/auth (default in `.env.development`: port **8001**)
- For Android (after Capacitor wrap merges): JDK 17+, Android Studio / SDK
- For Android: JDK 17+, Android Studio / SDK (see `llm-fe/ANDROID.md`)
## Local setup
@@ -89,6 +94,8 @@ to be visible in the browser bundle.
| `.env.development` | `npm start` | `http://127.0.0.1:8001` |
| `.env.production` | `npm run build` / `build:prod` | `https://chatbackend.aimloperations.com` |
| `.env.beta` | `npm run build:beta` | `https://beta.chatbackend.aimloperations.com` |
| `.env.mobile` | `npm run build:mobile` | prod by default (override for beta shell) |
Required keys (already set in the committed env files):
```env
@@ -101,7 +108,7 @@ this frontend (unlike Django apps under `~/Documents/secrets/`). Change the
committed `.env.*` files if API domains change, then redeploy.
Optional local overrides (gitignored): `.env.local`, `.env.development.local`,
`.env.production.local`.
`.env.production.local`, `.env.mobile.local`.
### 3. Start the backend
@@ -122,6 +129,16 @@ npm start
Open **http://localhost:3000**.
### 5. Android (Capacitor)
```bash
cd llm-fe
npm run build:mobile
npm run android:open
```
Full signing / Play Store notes: [`llm-fe/ANDROID.md`](llm-fe/ANDROID.md).
## npm scripts
| Command | Purpose |
@@ -130,6 +147,10 @@ Open **http://localhost:3000**.
| `npm run build` | Production build into `llm-fe/build/` |
| `npm run build:prod` | Prod build + copy to `/var/www/prod.chat.aimloperations/html` |
| `npm run build:beta` | Beta env build + copy to `/var/www/beta.chat.aimloperations/html` |
| `npm run build:mobile` | Mobile env build + `cap sync android` |
| `npm run android:open` | Open `android/` in Android Studio |
| `npm run android:sync` | `cap sync android` only |
| `npm run assets:generate` | Regenerate Android icons/splash from `assets/` |
| `npm test` | Jest watch mode |
| `npm run test:ci` | Single CI run (`CI=true`, no watch) |