westfarn 9e1449f0db
Deploy Beta / unit-tests (push) Successful in 12s
Unit Tests / test (push) Successful in 11s
Deploy Beta / deploy-beta (push) Successful in 2m23s
Add public account-deletion page for Google Play (#103) (#110)
## Summary
- Closes [#103](#103).
- Adds public SPA route `/account-deletion/` (no auth) with Hesychia / `ai.hesychia.chat` branding, in-app deletion steps, soft-delete data retention copy, and a contact path (30-day SLA) for users who cannot sign in.
- Documents Play Console **Account deletion URL** in `ANDROID.md` and `android/README.md` (`https://hesychia.ai/account-deletion/`, legacy host, HashRouter form).

## Notes
- Retention copy matches backend soft-delete (v1): no claim of full erasure / hard purge yet.
- Play Console field still needs to be set out-of-band after deploy.

## Test plan
- [ ] Open `/account-deletion/` signed out — page loads (no redirect to sign-in)
- [ ] Confirm steps match Account → Delete my account + email confirm
- [ ] Confirm retention sections are accurate vs soft-delete
- [ ] `npm run test:ci -- --testPathPattern=AccountDeletionPage`
- [ ] After beta deploy, set Play Console Account deletion URL to the public HTTPS URLReviewed-on: #110
2026-08-04 10:53:48 -07:00

Hesychia (chat_web_app)

Frontend for Hesychia — a React + TypeScript single-page app for a calm AI assistant experience (quiet, rest, stillness).

Public product domain: hesychia.ai (replacing chat.aimloperations.com).

Companion backend: chat_backend

Production serve is node-static (not Docker). Hosts build with npm into a document root; the shared web-static nginx container from server-infra serves those assets. Same pattern as dta_webapp.

Android ships the same CRA build/ via Capacitor (display name Hesychia; see llm-fe/ANDROID.md).

Domain migration

Role Current (still live) Target
Web UI chat.aimloperations.com hesychia.ai
REST / WS API chatbackend.aimloperations.com TBD under hesychia.ai (infra cutover)
Deploy webroot /var/www/{env}.chat.aimloperations/html Keep until server-infra renames

Committed .env.production / .env.beta still point at the current *.aimloperations.com API hosts so builds keep working. Flip those URLs (and deploy webroots / NPM) when DNS and server-infra cut over to hesychia.ai.

Stack

  • React 18, TypeScript, Create React App (react-scripts 5)
  • Material UI (MUI) 5 + Emotion for components and theming
  • React Router 6 for routing (BrowserRouter on web; HashRouter under Capacitor)
  • Axios for REST against chat_backend (JWT Authorization header)
  • WebSocket for live chat (REACT_APP_BACKEND_WS_API_BASE_URL)
  • Capacitor 7 for Android (and later iOS) WebView shells
  • Jest + React Testing Library for unit tests

Repository layout

chat_web_app/
├── README.md
├── .gitea/workflows/          # Unit tests + deploy-prod / deploy-beta
└── 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)
        ├── App.tsx
        ├── index.tsx
        └── llm-fe/
            ├── pages/         # Route-level views
            ├── components/    # Shared & feature UI
            ├── contexts/      # Auth, account, WebSocket, theme
            ├── platform/      # Capacitor routing / native chrome
            └── ui-kit/        # MD* design-system wrappers

Prerequisites

  • Node.js 20 (matches CI)
  • npm (lockfile: llm-fe/package-lock.json)
  • Running chat_backend locally for full chat/auth (default in .env.development: port 8001)
  • For Android: JDK 17+, Android Studio / SDK (see llm-fe/ANDROID.md)

Local setup

1. Clone and install

git clone ssh://git@git.aimloperations.com:30009/ai_ml_operations/chat_web_app.git
cd chat_web_app/llm-fe
npm ci

2. Configure environment

CRA loads mode-specific env files. Variables must be prefixed with REACT_APP_ to be visible in the browser bundle.

File Used when Backend (current)
.env.development npm start http://127.0.0.1:8001
.env.production npm run build / build:prod https://chatbackend.aimloperations.com + prod Tianji ID
.env.beta npm run build:beta https://beta.chatbackend.aimloperations.com + beta Tianji ID
.env.mobile npm run build:mobile prod by default (override for beta shell)

Each committed env sets REACT_APP_DEPLOY_ENV (production / beta) and REACT_APP_TIANJI_WEBSITE_ID.

Required keys (already set in the committed env files):

REACT_APP_BACKEND_REST_API_BASE_URL=http://127.0.0.1:8001/api/
REACT_APP_BACKEND_WS_API_BASE_URL=ws://127.0.0.1:8001/ws/chat_again/

These are baked into the JS at build time. There is no host secret file for this frontend (unlike Django apps under ~/Documents/secrets/). Change the committed .env.* files if API domains change, then redeploy.

SSO (Google / Microsoft)

OAuth client IDs/secrets live in chat_backend env (GOOGLE_OAUTH_*, MICROSOFT_OAUTH_*). The SPA only redirects to /api/auth/oauth/<provider>/start/ and lands on /auth/callback/ with JWTs. SSO buttons appear when /public/settings/ reports the provider as configured.

Capacitor / mobile: IdP redirect URIs must match the backend callback URL (not the WebView origin). Custom URL schemes / in-app browser for native OAuth are out of scope for the initial web SSO; use the web app for Google/Microsoft sign-in until native redirect handling is added.

Optional local overrides (gitignored): .env.local, .env.development.local, .env.production.local, .env.mobile.local.

3. Start the backend

From the chat_backend repo (adjust to however that service is run locally):

# example — follow chat_backend README for the current command
cd chat_backend
# run Django on the port matching .env.development (8001)

4. Start the dev server

cd llm-fe
npm start

Open http://localhost:3000.

5. Android (Capacitor)

cd llm-fe
npm run build:mobile
npm run android:open

Full signing / Play Store notes: llm-fe/ANDROID.md.

npm scripts

Command Purpose
npm start CRA dev server (port 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)

build:prod / build:beta are intended for deploy hosts (or a machine that can write those /var/www/... paths). Paths must match server-infra app_catalog.chat_web_app.webroot_pattern until renamed:

/var/www/{env}.chat.aimloperations/html

Tests

cd llm-fe
npm test          # watch
npm run test:ci   # one-shot (matches Gitea Unit Tests)

CI / deployment

Gitea Actions workflows in .gitea/workflows/ (same pattern as dta_webapp):

Workflow Trigger Behavior
unit-tests.yml push/PR to master npm ci + npm run test:ci in llm-fe/
deploy-beta.yml push to master (after unit tests in-workflow) server-infra/scripts/deploy.sh --app chat_web_app --env beta --ref <sha>
deploy-prod.yml manual workflow_dispatch only tests, then deploy --env prod

Push/merge to master auto-deploys beta only. Prod requires the Gitea Run workflow button on Deploy Prod.

Deploy flow (on each webserver listed in host_apps):

  1. Git checkout at the pinned ref under /opt/apps/src/chat_web_app_<env>
  2. npm ci in llm-fe/
  3. npm run build:<env> → writes the static tree under /var/www/...
  4. web-static nginx serves that root on the host port (prod 8082, beta 8083)

Manual deploy from the control node:

~/Documents/repos/server-infra/scripts/deploy.sh \
  --app chat_web_app --env prod --ref <sha>

NPM (not managed by Ansible) should balance public Hesychia domains to:

  • adama:8082 + roslin:8082 + ai-server-4080:8082 (prod)
  • beta hosts on 8083 / beta.chat.aimloperations.com (see server-infra)

See server-infra IMPLEMENTATION.md.

Tianji analytics

Build Env file Website ID
prod .env.production REACT_APP_TIANJI_WEBSITE_ID (prod site)
beta .env.beta distinct beta site ID (set after creating website in Tianji)
  • Script: https://tianji.aimloperations.com/tracker.js
  • Page views always load on prod/beta (no consent gate)
  • Custom events / identify require analytics consent (AnalyticsConsentBanner + trackEvent / identifyUser)
  • Consent choice stored in localStorage key hesychia_analytics_consent_v1 (granted / denied)
  • Banner links to /terms_of_service/#analytics for the always-on vs optional split
  • Event catalog: llm-fe/ANALYTICS.md
  • Backend: chat_backend — Django API + WebSocket
  • Infra: server-infraapp_catalog, host_apps, deploy.sh, web-static
  • Pattern reference: dta_webapp — node-static frontend deploy
S
Description
Front end react app for chat site
Readme
40 MiB
Languages
JavaScript 51.4%
TypeScript 47.9%
Swift 0.2%
HTML 0.2%
CSS 0.1%
Other 0.1%