Files
cardy/README.md
T

99 lines
4.2 KiB
Markdown

# Cardy
Discount card storage. Specification: [development specification-v2.md](development%20specification-v2.md).
| Package | Port | Public URL | Proxy auth |
|---|---|---|---|
| `server-fe` — admin UI (Vite) | 10001 | `https://dev.aggtaa.com/` | Authelia |
| `server-be` — admin API | 10002 | `https://dev.aggtaa.com/api/admin/*` → `/admin/*` | Authelia, passes `Remote-Email` |
| `server-be` — client API | 10002 | `https://dev.aggtaa.com/api/*` → `/*` | none |
| `mobile-client` — PWA | 10003 | `https://dev.aggtaa.com/m/*` → `/*` | none |
The proxy strips `/api` and `/m` and passes them in `X-Forwarded-Prefix`.
## Setup
```bash
pnpm install
cp server-be/.env.example server-be/.env # fill in KEY_ENCRYPTION_SECRET, SUPERADMIN_EMAIL
cp server-fe/.env.example server-fe/.env
```
## Run
```bash
pnpm --filter @cardy/server-be dev # API on 127.0.0.1:10002 (tsx watch)
pnpm --filter @cardy/server-fe dev # admin UI on :10001
```
```bash
pnpm --filter @cardy/mobile-client start # PWA: build + vite preview on :10003 (service worker needs a build)
```
Production-like: `pnpm --filter @cardy/server-be build && pnpm --filter @cardy/server-be start`,
`pnpm --filter @cardy/server-fe start` (build + `vite preview` on :10001).
The mobile client dev server (`pnpm --filter @cardy/mobile-client dev`) works locally at
`http://localhost:10003/m/`; behind the proxy use `start`.
## Android app
```bash
pnpm --filter @cardy/mobile-client build:android # web build for Capacitor + cap sync
```
Then open `mobile-client/android` in Android Studio (or `gradlew assembleDebug` there) to build the APK.
The app registers `cardy://login?...` links (key QR codes) and asks for camera access when scanning.
### Live updates (no APK reinstall)
The APK contains the web build and works fully offline. Newer web builds are delivered over the air
(`@capgo/capacitor-updater` in manual mode, no Capgo cloud, telemetry disabled):
```bash
pnpm --filter @cardy/mobile-client publish:android # build + zip into mobile-client/updates/android
```
The mobile-client server on :10003 serves it at `https://dev.aggtaa.com/m/android/version.json`.
On launch and on every return to the foreground (when online) the app checks it, downloads a newer
bundle in the background and reloads into it on the card list; on a card or in the editor it waits
(`next()`: applied on backgrounding). A bundle that fails to start is rolled back automatically.
Versions come from the build time (`2026.929.151230` = 2026-09-29 15:12:30 UTC).
### APK self-update (native part changed)
Changes to the native part (plugins, `AndroidManifest.xml`, Java code) need a new APK:
```bash
pnpm --filter @cardy/mobile-client publish:android-apk # signed release APK into mobile-client/updates/android
```
It needs `mobile-client/android/keystore.properties` (copy `keystore.properties.example`, not committed)
with the release key. `versionCode` is the build time (`yyDDDHHmm`, UTC), `versionName` the web version.
Installed apps show "A new version of the app is available" on the card list; Install downloads the
APK and hands it to Android's installer (first time: allow "Install unknown apps" for Cardy, then
confirm the system dialog). Web updates published after an APK release require that APK or newer.
All builds (also Android Studio debug builds) are signed with the release key, so they can replace
each other. An app signed with another key (e.g. the old debug key) must be uninstalled once.
### Live reload during development
`pnpm --filter @cardy/mobile-client android:dev` (with `pnpm --filter @cardy/mobile-client dev` running
and a device connected via adb) installs an app that loads the dev server through `adb reverse`.
Run `build:android` again before building an APK for real use.
`server-be` listens on `127.0.0.1` by default because `/admin/*` trusts `Remote-Email`.
If the proxy runs on another machine, set `HOST` and `ADMIN_PROXY_SECRET`, and make the proxy add
`X-Cardy-Proxy-Secret` on the `/api/admin` route.
Without the proxy (local development), `server-fe` emulates it: forwards `/api/*` to `server-be`
with `/api` stripped; `DEV_REMOTE_EMAIL` in `server-fe/.env` fakes the Authelia user.
## Tests
```bash
pnpm test
pnpm typecheck
```