diff --git a/README.md b/README.md index 945a597..6271b57 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,9 @@ # adventure-web -Frontend service generated from `nholtware/service-template-react`: a Vite + -React 19 + React Router (data mode) SPA, served as static files by -unprivileged nginx. +Library, player and builder for choose-your-adventure stories (Vite + React Router data mode), +scaffolded by `platform/new-service adventure-web --kind frontend --api adventure`. -## Develop +- `/` library of published stories, `/play/:id` player (progress saved per story in localStorage, undo/restart) +- `/build`, `/build/:id` builder: scenes, choices, endings, live problem checks (mirrors backend `analyze`), save, publish -```sh -npm install -npm run dev # http://localhost:5173, /api proxied to API_PROXY_TARGET (default http://localhost:3000) -npm test -npm run lint -npm run format -``` - -## Runtime config - -`/config.js` sets `window.__APP_CONFIG__`. In the container, -`docker-entrypoint.d/10-config.sh` writes it at start from env vars, so one -image runs in every environment. Read values through `getConfig()` in -`src/lib/config.ts`. - -| Env var | Default | Meaning | -| ------------------------ | ------- | --------------------------------------------------- | -| `API_BASE_URL` | `/api` | Backend base URL; `/api` is the same-host route | -| `APP_NAME` | `app` | Display name | -| `UNLEASH_URL` | (empty) | Unleash base URL for the browser; empty = flags off | -| `UNLEASH_FRONTEND_TOKEN` | (empty) | Unleash frontend token (public by design) | - -Everything in `config.js` is public. Never put secrets there. - -## Feature flags - -Flags come from Unleash (UI: http://unleash.192.168.1.83.nip.io, environment `development`) -through its Frontend API, using the official `@unleash/proxy-client-react` SDK. -`src/lib/flags.tsx` wraps it: `FlagsProvider` is mounted once in `main.tsx`; -components call the wrappers, never the SDK directly: - -```tsx -import { useFlag, useVariant } from "../lib/flags"; -const showBanner = useFlag("hello-banner"); -``` - -- In the cluster the deployment sets `UNLEASH_URL=http://unleash.192.168.1.83.nip.io` - and `UNLEASH_FRONTEND_TOKEN` from Secret `unleash-client-token` (key `frontendToken`). -- The SDK fetches on load and refreshes every 15 s; components re-render on change. - A reload always picks up the current state. -- With `UNLEASH_URL` unset (local `npm run dev`, tests) every flag reads `false`, nothing is fetched. -- Tests: `vi.mock("@unleash/proxy-client-react")` and control `useFlag` (see `src/app.test.tsx`). -- `hello-banner` on the home page is the platform demo flag; delete it when you don't need it. - -## Container - -- `GIT_SHA` build arg is baked in as `import.meta.env.VITE_GIT_SHA`. -- nginx listens on 8080: `/healthz` returns 200, unknown paths fall back to - `index.html`, `/assets/*` are cached as immutable, and `index.html` and - `config.js` are not cached. -- Access log: one JSON line per request in the platform logging contract - (`level`, `time`, `service` = `APP_NAME`, `version` = `GIT_SHA`, `req.id` - (echoes `X-Request-Id`), `req.method`, `req.url`, `res.statusCode`, - `responseTime` in ms, `msg: "request completed"`), the same shape as the backend - template. In Kibana (http://kibana.192.168.1.83.nip.io, data view `kube-*`): - `service:"adventure-web" and res.statusCode >= 400`. `/healthz` isn't logged. - nginx's own startup/error lines stay plain text (field `log`). - -## Deploy - -Push to `main`: Forgejo CI runs lint/test/format, builds and pushes -`192.168.1.230:3000/nholtware/adventure-web:`, and bumps the tag in the -gitops repo. ArgoCD then syncs it. Manifests come from gitops -`templates/frontend/`. The repo needs Actions secrets `REGISTRY_USER`, -`REGISTRY_TOKEN`, and `GITOPS_TOKEN`. +Backend calls go through `/api` (see `adventure`).