Merge pull request 'docs(android): add design-pass workflow to app PLAN' (#7) from docs/android-design-pass-workflow into main

Reviewed-on: #7
Reviewed-by: Colby Whitlock <whitlocktech@gmail.com>
This commit is contained in:
2026-07-19 08:36:23 +00:00

View File

@@ -82,6 +82,17 @@ runs `openapi-generator` against the committed spec. Endpoints that return
service (Retrofit) → DTO`. Repositories expose `Result`-like sealed types so the UI degrades
gracefully (see §7).
### 2.1 Build workflow: Kotlin first, then design-led UI
The app is built in two passes. **First**, the functional Kotlin is written — the layering above with
placeholder/functional Compose screens: navigation, ViewModels, repositories, the generated API
client, auth/token handling, and every screen wired to its endpoints and working end-to-end. **Then**,
once that Kotlin code is done, **Claude Design produces the front-end design** for the app, and
**Claude Code implements the final UI (Compose screens, theming, components) according to that
design.** The design pass restyles and refines the already-working screens; it does not change the
architecture, data flow, or endpoint contracts established in the first pass. Keeping strings
externalized and branding data-driven (§2, §3) from the start is what lets the design pass reskin
freely without touching logic.
---
## 3. Base URL: first-run + settings
@@ -294,7 +305,7 @@ maintenance cost. Reserve v2 for a real breaking re-shape if one ever arises.
stay website-handled and the app hands off to them (§4.2). This is a deliberate scope reduction.
3. **Push notifications** — see §11. Additive v1 endpoints under `/auth/me/devices*` and
`/auth/me/notifications*`, plus a **self-hosted `ntfy` service added to `website/docker-compose.yml`**
with fully declarative, zero-interaction config. Not required for the first release (M6, not M1M5).
with fully declarative, zero-interaction config. Not required for the first release (M7, not M1M6).
4. **Version/health surfacing** — ensure `/public/status` (or a light `/public/version`) exposes
enough for the app's first-run probe and version-mismatch guard.
5. **Docs** — update `docs/website/BACKEND_DESIGN.md` for any new/changed endpoint; keep this file and
@@ -309,25 +320,41 @@ No `link/` or `servuo-plugins/` changes are expected — the app is downstream o
## 9. Milestones
**Two passes (§2.1).** M0M4 are the **functional Kotlin pass** — every screen wired to its endpoints
and working end-to-end with placeholder/functional Compose UI, no design investment yet. **M5 is the
design pass**: once the functional Kotlin is done, Claude Design produces the front-end design and
Claude Code implements the final UI to it. Polish/release, push, and Play (M6M8) follow the designed
app.
1. **M0 — Repo scaffold**: Gradle + Compose + Hilt skeleton, CI (build + lint + unit test), license
headers (GPL-3.0-or-later), CONTRIBUTING/AI-disclosure parity with the other repos.
2. **M1 — Connect & browse**: first-run base-URL flow, `/public/status`+`/public/settings` theming,
generated API client, public content (news/wiki/pages) + contact. No auth yet.
3. **M2 — Public shard**: shard widgets + SSE live stream with reconnect/degradation.
4. **M3Auth (§4)**: native password+TOTP login (429 handling), token storage, refresh interceptor,
logout, `/auth/me` role re-validation, the access-level menu. Custom-Tab **hand-offs** to the website
for register / invite / password-reset / SSO (no native screens for those). Optional biometric
app-lock. *Prerequisite:* the website password-reset flow (§8) is already built.
5. **M4 — Player self-service & game data**: account management (via `/auth/me/*`), game-account
linking, own roster/characters/vendors/houses/sales — **text-only** presentation (§6.3).
6. **M5 — Polish & first release**: settings (server switch = hard reset), version-mismatch guard,
2. **M1 — Connect & browse** *(functional pass)*: first-run base-URL flow,
`/public/status`+`/public/settings` theming, generated API client, public content
(news/wiki/pages) + contact. No auth yet.
3. **M2Public shard** *(functional pass)*: shard widgets + SSE live stream with
reconnect/degradation.
4. **M3 — Auth (§4)** *(functional pass)*: native password+TOTP login (429 handling), token storage,
refresh interceptor, logout, `/auth/me` role re-validation, the access-level menu. Custom-Tab
**hand-offs** to the website for register / invite / password-reset / SSO (no native screens for
those). Optional biometric app-lock. *Prerequisite:* the website password-reset flow (§8) is
already built.
5. **M4 — Player self-service & game data** *(functional pass)*: account management (via
`/auth/me/*`), game-account linking, own roster/characters/vendors/houses/sales — **text-only**
presentation (§6.3).
6. **M5 — Design pass & final UI (§2.1)**: with the functional Kotlin from M1M4 working end-to-end,
**Claude Design produces the front-end design** for the app, then **Claude Code implements the final
UI to it** — Compose screens, Material 3 theming from the per-shard branding (§3), reusable
components, loading/error/empty states, the designed access-level menu. Restyles the existing
screens only; no changes to architecture, data flow, or endpoint contracts. Text-only game data
(§6.3) still holds — this is visual design of the data screens, not paperdoll art.
7. **M6 — Polish & first release**: settings (server switch = hard reset), version-mismatch guard,
release build hardening (HTTPS-only, no token logging). No offline cache in v1 (§7). **Ship v1 as a
signed APK attached to a Gitea release** (see §10).
7. **M6 — Push notifications** (post-v1): add the self-hosted `ntfy` service to
8. **M7 — Push notifications** (post-v1): add the self-hosted `ntfy` service to
`website/docker-compose.yml` (declarative, zero-interaction config), UnifiedPush integration in the
app, device registration, the subscriptions UI, and the content-free-tickle backend fan-out (see
§11). The app is built with room for this from M0 but it does not gate the first release.
8. **M7 — Google Play**: Play Console listing, signing/upload key, and (optionally) an FCM build flavor
9. **M8 — Google Play**: Play Console listing, signing/upload key, and (optionally) an FCM build flavor
— after the direct-APK release is stable.
---
@@ -344,7 +371,7 @@ No `link/` or `servuo-plugins/` changes are expected — the app is downstream o
## 11. Push notifications (built-for, shipped post-v1)
The app is architected from M0 to accommodate push, but push itself ships in M6 — it does not block the
The app is architected from M0 to accommodate push, but push itself ships in M7 — it does not block the
first release. Users **opt in per stream**: nothing is pushed unless subscribed.
### Transport — UnifiedPush via self-hosted ntfy (decided)
@@ -422,7 +449,7 @@ repos use), on a bare `ubuntu:latest` container.
frequent: run the job under a prebuilt Android-SDK `container:` image so nothing installs per-run.)
- **PR gate** (`.gitea/workflows/pr-checks.yml`, on PR → `main`): `./gradlew lint test assembleDebug`.
Debug builds are auto-signed, so the gate needs no secrets. Mirrors `website/`'s pre-merge gate.
- **Release** (`.gitea/workflows/release.yml`, M5+): build a **signed release APK** and attach it to a
- **Release** (`.gitea/workflows/release.yml`, M6+): build a **signed release APK** and attach it to a
Gitea release (mirrors `link/`'s release job). The **keystore is a base64 Gitea Actions secret**
decoded in CI; store/key passwords are secrets. The keystore never lives in the repo. Keep the
signing identity stable from the first release (Play later requires consistency).
@@ -445,7 +472,7 @@ ntfy / UnifiedPush (§11).
own verified app links — confirm whether any deep-link-back is wanted at all for v1.
- ntfy: exact upstream image + pinned tag, its reverse-proxy hostname/path, and whether to add a
backend publish token (optional hardening — the content-free-tickle design does not require one).
- FCM flavor: build it for the Play release or ship Play on UnifiedPush too? Decide at M7.
- FCM flavor: build it for the Play release or ship Play on UnifiedPush too? Decide at M8.
- Deep-link / share targets for wiki pages, posts, and notification taps.
- iOS: none planned (this is the Android-only choice); revisit only if cross-platform is later
required (would change §2 — and push, which would then favor a cross-platform transport).