Skip to content

Gen Web

The axion-gen-web Helm chart deploys the Next.js 15 frontend that combines consumer dashboards and the analyst chat panel. Cross-source SQL execution lives in Gen API, not in the browser.

Workloads deployed

Component Role See
web Next.js server + static asset serving. The same process hosts the BFF that proxies LLM calls and the ask_data tool to Gen Backend. Gen overview

Gen Web has no database of its own — chat history lives in browser localStorage.

Prerequisites

  • Kubernetes cluster (v1.27+)
  • Helm 3.12+
  • kubectl configured for your cluster
  • Axion Gen Backend API deployed and reachable from the cluster (see Gen Backend)
  • LLM provider — OpenAI-compatible, Anthropic, on-prem, or mock
  • URBI / 2GIS MapGL — required for map widgets (partner-supplied API endpoint and key)
  • OIDC IdP — same one used by Sense and Gen Backend
  • (Optional) Mapbox token, Langfuse, MOMAH GPT

1. Prepare your values file

Create custom-values.yaml and fill in all required values below. Helm will refuse to render the chart if any of them are missing or empty.

Required values

Value path Description
web.image.repository Full image path in your private registry
web.image.tag Image version tag

The chart additionally reads three runtime env vars under web.env that are forwarded to the browser via ConfigProvider:

  • OIDC_REDIRECT_URI — post-login OIDC callback URL
  • URBI_API, URBI_KEY — 2GIS MapGL endpoint + key

BACKEND_URL defaults to http://localhost:5501 and almost always needs to be overridden to the in-cluster Gen Backend service URL.

Conditionally required

Value path When required
web.ingress.hosts If web.ingress.enabled: true
web.certificate.issuerRef.name If web.certificate.enabled: true
web.certificate.dnsNames If web.certificate.enabled: true

Optional (sensible defaults provided)

Value path Default Notes
web.replicaCount 1 Increase for HA
web.service.type ClusterIP Change to LoadBalancer/NodePort if needed
web.service.port 80 Service port exposed to the cluster
web.service.targetPort 3000 Container port (Next.js default)
web.env {} Runtime environment variables (see below)
web.secrets {} Sensitive values stored in a Kubernetes Secret
web.resources 256Mi/512Mi mem Tune per workload
web.hostAliases [] Extra /etc/hosts entries
global.imagePullSecrets ar-registry-secret Set if your registry is private

Runtime environment variables

These can be changed without rebuilding the image. Set non-sensitive values in web.env and sensitive values in web.secrets — secrets are stored in a Kubernetes Secret, injected via envFrom, and the pod automatically restarts on change.

web.env — plain environment variables

Variable Default Description
OIDC_REDIRECT_URI (required) Post-login OIDC redirect URL (passed to client at runtime)
URBI_API (required) URBI/2GIS MapGL API endpoint (passed to client at runtime)
URBI_KEY (required) URBI/2GIS MapGL API key (passed to client at runtime)
MAPBOX_TOKEN Mapbox token for map widgets (passed to client at runtime, optional)
BACKEND_URL http://localhost:5501 Axion Gen Backend API URL
LLM_PROVIDER openai_compatible LLM provider type: openai_compatible, anthropic, on_prem, or mock
LLM_BASE_URL LLM provider base URL (e.g. https://api.openai.com/v1)
LLM_MODEL gpt-4o-mini Model name to use
AGENT_MODE ask_only ask_only (Q&A only) or full (all tools including DB / charts / dashboards)
AGENT_MAX_CONTEXT_MESSAGES 40 Max messages kept in LLM context window
MOMAH_GPT_API_URL MOMAH GPT API endpoint for external data-question agent
MOMAH_GPT_AUTH_STRATEGY Auth strategy: static (use token as-is) or forward (forward user's SSO token)
LANGFUSE_BASE_URL https://cloud.langfuse.com Langfuse instance URL (tracing disabled if keys absent)

OIDC_REDIRECT_URI, URBI_API, URBI_KEY, and MAPBOX_TOKEN are read at runtime by the Next.js server and passed to the browser via ConfigProvider. Changing them does not require rebuilding the Docker image — restart the container with the new values.

web.secrets — sensitive values (stored in Kubernetes Secret)

Variable Description
LLM_API_KEY LLM provider API key
MOMAH_GPT_API_TOKEN MOMAH GPT API authentication token
LANGFUSE_SECRET_KEY Langfuse observability secret key
LANGFUSE_PUBLIC_KEY Langfuse observability public key

Example configuration

web:
  env:
    OIDC_REDIRECT_URI: "https://app.partner.com/api/auth/callback/oidc"
    URBI_API: "https://mapgl.urbi.ae/api"
    URBI_KEY: "your-urbi-key"
    BACKEND_URL: "http://axion-gen-api:80"
    LLM_PROVIDER: "openai_compatible"
    LLM_BASE_URL: "https://api.openai.com/v1"
    LLM_MODEL: "gpt-4o-mini"
    AGENT_MODE: "ask_only"
    LANGFUSE_BASE_URL: "https://us.cloud.langfuse.com"
  secrets:
    LLM_API_KEY: "change-me"
    LANGFUSE_SECRET_KEY: "change-me"
    LANGFUSE_PUBLIC_KEY: "change-me"

Minimal custom-values.yaml

A working file with only the required values (everything else uses chart defaults):

web:
  image:
    repository: "registry.partner.com/axion/gen-web"
    tag: "1.0.0"
  env:
    OIDC_REDIRECT_URI: "https://app.partner.com/api/auth/callback/oidc"
    URBI_API: "https://mapgl.urbi.ae/api"
    URBI_KEY: "your-urbi-key"
    BACKEND_URL: "http://axion-gen-api:80"

2. Get Helm chart and container image

2.1 Obtain a service-account key

Request sa-key.json from @v.loboda. This key grants read access to the Axion artifact registry.

2.2 Pull the container image

cat sa-key.json | docker login -u _json_key --password-stdin "https://europe-west1-docker.pkg.dev"
docker pull europe-west1-docker.pkg.dev/axionx-infra/axion/gen-web:latest

2.3 Pull the Helm chart

cat sa-key.json | helm registry login europe-west1-docker.pkg.dev -u _json_key --password-stdin
helm pull oci://europe-west1-docker.pkg.dev/axionx-infra/axion/helm/axion-gen-web --version 0.0.0-latest

2.4 Push the image to your private registry

docker tag europe-west1-docker.pkg.dev/axionx-infra/axion/gen-web:latest registry.example.com/axion/gen-web:latest
docker push registry.example.com/axion/gen-web:latest

If your registry requires authentication:

kubectl create namespace axion-gen-web

kubectl create secret docker-registry registry-creds \
  -n axion-gen-web \
  --docker-server=registry.example.com \
  --docker-username=<user> \
  --docker-password=<password>
global:
  imagePullSecrets:
    - name: registry-creds

2.5 Rebuild the image (optional)

docker build -f frontend/Dockerfile frontend/ \
  -t registry.example.com/axion/gen-web:1.0.0

docker push registry.example.com/axion/gen-web:1.0.0

3. Install

helm upgrade --install axion-gen-web \
  oci://europe-west1-docker.pkg.dev/axionx-infra/axion/helm/axion-gen-web \
  --version 0.0.0-latest \
  -n axion-gen --create-namespace \
  -f custom-values.yaml \
  --atomic --wait --timeout 10m

The chart deploys into the axion-gen namespace by convention so it sits next to the backend it talks to. The --atomic flag rolls back automatically on failure.

4. Verify

kubectl get pods -n axion-gen
helm -n axion-gen status axion-gen-web
kubectl port-forward svc/axion-gen-web 8080:80 -n axion-gen
curl http://localhost:8080/api/health

5. Expose the service (optional)

Option A — Ingress

web:
  ingress:
    enabled: true
    className: nginx
    annotations:
      nginx.ingress.kubernetes.io/proxy-body-size: "100m"
    hosts:
      - host: app.partner.example.com
        paths:
          - path: /
            pathType: Prefix
    tls:
      - hosts:
          - app.partner.example.com
        secretName: axion-gen-web-tls

Option B — NodePort / LoadBalancer

web:
  service:
    type: LoadBalancer

6. Upgrade and rollback

Update web.image.tag and re-run the install command. No migrations.

helm -n axion-gen history axion-gen-web
helm -n axion-gen rollback axion-gen-web <REVISION> --wait --timeout 10m

7. Uninstall

helm -n axion-gen uninstall axion-gen-web --wait --timeout 5m

Troubleshooting

# render manifests locally to validate values
helm template axion-gen-web oci://europe-west1-docker.pkg.dev/axionx-infra/axion/helm/axion-gen-web \
  --version 0.0.0-latest -f custom-values.yaml

# application logs
kubectl logs -l app.kubernetes.io/component=web -n axion-gen --tail=100

# describe pod for events/errors
kubectl describe pod -l app.kubernetes.io/component=web -n axion-gen

# Kubernetes events
kubectl -n axion-gen get events --sort-by=.lastTimestamp