hello-web/README.md
nholtware 4017106dd2
All checks were successful
/ checks (push) Successful in 42s
/ deploy (push) Successful in 3s
ci: use https://git.lab.holtlabs.xyz for workflows and registry (Plan 12)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-11 11:55:08 -06:00

3.3 KiB

hello-web

Test frontend for hello-svc. Frontend service generated from nholtware/service-template-react: a Vite + React 19 + React Router (data mode) SPA, served as static files by unprivileged nginx.

Develop

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:

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:"hello-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 git.lab.holtlabs.xyz/nholtware/hello-web:<sha>, 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.