Live at: https://timing-react-vibe.aa349-1l5zl3.intility.dev/
Container image: ghcr.io/intility/timing-react-vibe.
A React SPA on the Intility vibe app platform (aa349-vibe). Bootstrapped from intility/react-vibe-template. Vite + React 19 + TypeScript + Bifrost. MSAL is wired up for Entra ID login.
The platform handles deployment: git push to main builds an image, pins its sha tag in deploy/base/kustomization.yaml, and Argo CD reconciles the cluster. Steady-state push-to-live is around 50 seconds.
Prerequisites: Node 20+, just, a populated ~/.npmrc (see Intility NPM setup).
just install # npm ci
just dev # http://localhost:3000 with HMR
just check # lint + test + build (run before pushing)Live edits go in src/. Static assets in public/. The Vite dev server listens on :3000; the production container listens on :8080.
Conventional Commits are required. release-please opens a release PR on each push to main, bumping package.json based on commit history.
feat: add profile dropdown # minor bump
fix: correct redirect URI # patch bump
feat!: switch to Dex # major bump
Merging the release PR cuts a tag, which the build-image.yml workflow turns into an immutable semver-tagged image.
src/— React app (App.tsx, router, routes, components, MSAL auth helpers).public/— static assets served at the site root (favicons).index.html— Vite entry HTML.Dockerfile— multi-stage build. Builder runsnpm ci+npm run build; runtime isghcr.io/intility/nginx-unprivileged-react. Listens on:8080.deploy/base/— Kustomize manifests Argo CD applies to the cluster (Deployment, Service, HTTPRoute, NetworkPolicy, ResourceQuota).deploy/overlays/— per-environment overrides (empty by default)..github/workflows/—build-image.yml(image build + sha-pin),template-init.yml(one-shot, deletes itself),release-please.yml(semver releases).justfile— task runner.
When you create a new repo from this template, GitHub Actions runs template-init.yml once on the first push. It:
- Substitutes
timing-react-vibeandintilityin the tree. - Substitutes
__ENTRA_CLIENT_ID__in.env(you replace this manually with your Entra app registration's client ID). - Writes
apps/<repo>.yamltointility/aa349-vibe, which registers the app with the platform. - Self-deletes.
CI uses the org-level NPM_INTILITY_COM_TOKEN secret (inherited automatically) and feeds it to the Dockerfile under the env name NODE_AUTH_TOKEN. No per-repo secret setup is needed unless your repo opts out of org secret inheritance.
intility/aa349-vibe runs an Argo CD ApplicationSet that watches apps/*.yaml. When template-init.yml writes your apps/<repo>.yaml, the ApplicationSet creates an Application pointing at this repo's deploy/base/ and syncs it to namespace app-<repo>.
After that, every push to main:
build-image.ymlbuilds and pushesghcr.io/intility/timing-react-vibe:sha-XXXXXXX.- The same workflow rewrites
deploy/base/kustomization.yaml'snewTag:and pushes the manifest commit back. - Argo CD detects the manifest change (org-level webhook to
argocd-server) and rolls the Deployment.
- Resources / replicas: edit
deploy/base/deployment.yamldirectly, or add an overlay underdeploy/overlays/. - Hostname: edit
deploy/base/httproute.yaml. Default is<repo>.aa349-1l5zl3.intility.dev. - NetworkPolicy: defaults allow only ingress from the platform Gateway, plus DNS and HTTPS egress. Add rules in
deploy/base/networkpolicy.yamlif you need to call internal services. - Auth: MSAL is wired in
src/auth/. To switch off auth-required routes, see comments insrc/App.tsx. To swap auth providers entirely, replacesrc/auth/. - Telemetry: not configured by default. Add
OTEL_*env vars indeploy/base/deployment.yamland an egress rule indeploy/base/networkpolicy.yaml(seegohtmx-vibe-templatefor the pattern).
Platform questions: https://github.com/intility/aa349-vibe. Template questions: https://github.com/intility/react-vibe-template.