# HAN Chat frontend test site Expo / React Native Web SPA для проверки публичных пользовательских потоков HAN Chat. ## Запуск ```bash cp .env.example .env.local npm install npm run web ``` Проверки: `npm test`, `npm run typecheck`, `npm run build:pwa`, `npm run test:e2e`. ## PWA Иконки лежат в `public/`: | Файл | Размер | |---|---| | `favicon.png` | 64×64 | | `icon-192.png` | 360×360 | | `icon-512.png` | 1024×1024 | | `apple-touch-icon.png` | 360×360 | Manifest: `public/manifest.json`. Корневой HTML: `app/+html.tsx`. ```bash npm run build:pwa # export + service-worker.js (Workbox) npm run serve # локальная проверка dist/ ``` Chrome DevTools → Application → Manifest / Service Workers. API и `/auth/` не кэшируются. ## Production `npm run build:pwa` создаёт `dist/` с manifest, иконками и `service-worker.js`. Каталог монтируется в корневой nginx; отдельный frontend nginx не используется. Для SPA nginx должен применять `try_files $uri /index.html`, не кэшировать `index.html`, `manifest.json`, `service-worker.js` и бессрочно кэшировать hashed assets. Dockerfile собирает статический OCI-артефакт `/dist` без runtime-сервера: ```bash docker build --target static \ --build-arg EXPO_PUBLIC_API_BASE_URL=https://tohin.ru \ --build-arg EXPO_PUBLIC_AUTH_BASE_URL=https://tohin.ru/auth \ --build-arg EXPO_PUBLIC_KEYCLOAK_REALM=han-chat \ --build-arg EXPO_PUBLIC_KEYCLOAK_CLIENT_ID=han-chat-frontend . ``` Во frontend разрешены только публичные URL, realm, client id и имя среды. Service tokens, S3 credentials и mock OTP code добавлять запрещено. На web refresh token хранится в browser storage с известным XSS-риском; production требует строгой CSP и отсутствия сторонних scripts. WebSocket использует subprotocols `han-chat-v1` и `bearer.`. Они должны совпадать с реализацией api-backend. Query-token намеренно не используется.