ASK Frontend¶
Repo: ask-frontend-main
Language: TypeScript / Node.js ≥ 22
Framework: Next.js (standalone mode)
Helm Chart: frontend v1.0.0
Port: 3000
Architecture¶
The Frontend is a Turborepo monorepo containing a Next.js web application (apps/web) and shared workspace packages. It serves the ASK platform UI and communicates with the Core Service and Assistant Service APIs.
ask-frontend-main/ ← Turborepo monorepo root
├── apps/
│ └── web/ ← Next.js application (the deployed artifact)
│ └── Dockerfile ← Production container build
└── packages/ ← Shared workspace packages
├── @workspace/ui
├── @workspace/analytics
├── @workspace/errors
└── @workspace/network
Container Images¶
Multi-Stage Build Pattern¶
| Stage | Base Image | Purpose |
|---|---|---|
base |
node:22-alpine |
Common Node.js + corepack (pnpm) |
pruner |
base |
turbo prune --scope=web — extract only web app from monorepo |
builder |
base |
pnpm install + pnpm turbo run build --filter=web |
runner |
node:22-alpine |
Minimal standalone Next.js server |
The DEPENDENCY_PROXY_PREFIX ARG allows routing through a registry mirror.
Image Produced¶
| Image Name | Dockerfile | Port | Entrypoint |
|---|---|---|---|
frontend |
apps/web/Dockerfile |
3000 | node --max-old-space-size-percentage=75 apps/web/server.js |
Production image registry:
Dev image uses a separate tag:
Build Arguments¶
| ARG | Default | Description |
|---|---|---|
DEPENDENCY_PROXY_PREFIX |
"" |
Registry mirror prefix for base images |
ENV_FILE |
.env.production |
Source .env file copied to apps/web/.env.local at build time |
COMMIT_SHA |
"" |
Git SHA embedded in the Sentry release identifier |
Runtime Environment Variables¶
| Variable | Value | Description |
|---|---|---|
NODE_ENV |
production |
Node.js mode |
NEXT_TELEMETRY_DISABLED |
1 |
Disable Next.js telemetry |
PORT |
3000 |
HTTP listen port |
User¶
The runner stage creates and uses a non-root user:
- Group: nodejs (gid 1001)
- User: nextjs (uid 1001)
Helm Chart¶
Chart: helm/Chart.yaml
No subchart dependencies — the frontend is stateless and has no external service dependencies managed by Helm.
Environments¶
| Environment File | Environment | Cloud/DC | Notes |
|---|---|---|---|
values-dev.yaml |
Development | Azure UAE North | Uses frontend-dev image; Azure Spot VM node pool |
values-stg.yaml |
Staging | Azure UAE North | Pre-prod |
values-mec1-stg.yaml |
MEC1 Staging | Azure MEC1 | Secondary staging region |
values-prod.yaml |
Production | Azure UAE North | |
values-ai71-pp-auh1-prod-ask.yaml |
PP Production | On-prem Abu Dhabi | Gov cloud, air-gapped |
values-mod-auh1-dev-ask.yaml |
core42 Dev | On-prem RKE2 (core42) | Air-gapped, Harbor images |
PP Environment — Frontend¶
Full PP environment details: PP Environment page
PP Image¶
imagePullSecrets: harbor-registry-secret
PP Configuration¶
| Setting | PP Value | Notes |
|---|---|---|
image.repository |
registry.pp.gov.ae/ask/frontend-prod |
Note: frontend-prod not frontend |
replicaCount |
1 |
Base (autoscaling takes over) |
autoscaling.enabled |
true |
|
autoscaling.minReplicas |
3 |
|
autoscaling.maxReplicas |
100 |
|
autoscaling.targetCPUUtilizationPercentage |
80 |
|
NODE_TLS_REJECT_UNAUTHORIZED |
0 |
Private CA cert — bypass TLS verification |
| Liveness probe path | /api/health |
|
| Liveness initial delay | 60s |
Longer than default (Next.js startup time) |
| Readiness initial delay | 60s |
PP Ingress — Three Hostnames¶
| Hostname | Purpose |
|---|---|
ask.pp.gov.ae |
Main tenant entry point |
chat.ask.pp.gov.ae |
Single-tenant organization UI |
admin.ask.pp.gov.ae |
Super Admin organization UI |
TLS: ask-pp-gov-ae-cert (all three hostnames share the same wildcard secret).
PP-Specific Notes¶
NODE_TLS_REJECT_UNAUTHORIZED=0is set because the frontend calls backend APIs via the public*.ask.pp.gov.aehostnames which are signed by an internal private CA.- Three ingress hostnames serve different organizational contexts (main, single-tenant chat, super-admin).
- Build-time
ENV_FILEfor PP must setNEXT_PUBLIC_API_URLtohttps://api.ask.pp.gov.ae.
core42 Environment — Frontend (mod-auh1-dev-ask)¶
Values file: helm/environments/values-mod-auh1-dev-ask.yaml
core42 Image¶
imagePullSecrets: harbor-pull-secret
Image must be rebuilt with air-gap NEXT_PUBLIC_* vars baked in
The staging image has NEXT_PUBLIC_APP_BASE_URL=https://ask.stg.ai71.ai baked at build time.
The AI71 build for this env must set:
NEXT_PUBLIC_APP_BASE_URL=https://ask.mod.auh1.dev.dir, NEXT_PUBLIC_APP_ENV=mod-auh1-dev-ask,
NEXT_PUBLIC_AMPLITUDE_ENABLED=false, NEXT_PUBLIC_SENTRY_ENABLED=false,
NEXT_PUBLIC_FF_DISABLE_VOICE_MODE=true, NEXT_PUBLIC_FF_DISABLE_SPEECH_TO_TEXT=true.
core42 Configuration Changes vs PP¶
| Setting | PP Value | core42 Value |
|---|---|---|
image.repository |
registry.pp.gov.ae/ask/frontend-prod |
harbor.cl1.sq4.aegis.internal/ask/frontend-stg |
NODE_TLS_REJECT_UNAUTHORIZED |
0 |
0 (same — internal CA not in Node.js trust store) |
autoscaling.minReplicas |
3 |
disabled, 1 replica for bring-up |
core42 Ingress¶
| Hostname | Purpose |
|---|---|
ask.mod.auh1.dev.dir |
Main tenant entry point |
admin.ask.mod.auh1.dev.dir |
Super Admin organization UI |
TLS: frontend-tls (cert-manager internal-ca-issuer).
core42 Secrets¶
| Key | Vault path | k8s secret |
|---|---|---|
AUTH_SECRET |
secret/ask/frontend/auh1-dev |
frontend-secret |
BILLING_API_KEY |
secret/ask/frontend/auh1-dev |
frontend-secret |
Secret is created manually from bastion (no ExternalSecret template in this chart). See 41 — Frontend Deployment Phase 2 for the creation command.
core42 Notes¶
- No TOML config file — frontend uses Next.js env vars, not Dynaconf TOML
- No ESO —
frontend-secretcreated manually from Vault on bastion (one-time) - Two ingress hostnames —
ask.*(main) +admin.*(super admin), matching PP's 3-host pattern
Configuration Variables¶
The frontend application is largely configured at build time via the ENV_FILE argument (.env.production, .env.staging, etc.). Runtime configuration is minimal.
Typical Build-Time .env Variables¶
| Variable | Description |
|---|---|
NEXT_PUBLIC_API_URL |
Core Service API base URL |
NEXT_PUBLIC_ASSISTANT_API_URL |
Assistant Service API base URL |
NEXT_PUBLIC_SENTRY_DSN |
Sentry browser SDK DSN |
NEXT_PUBLIC_APP_ENV |
Environment label (dev, staging, production) |
NEXT_PUBLIC_ANALYTICS_WRITE_KEY |
Analytics/telemetry write key |
NEXT_PUBLIC_* |
Any other public client-side config |
Secrets¶
The frontend has minimal server-side secrets. Build-time secrets (API keys baked into .env.local) are the primary concern:
| Secret | Description | Injection Method |
|---|---|---|
SENTRY_AUTH_TOKEN |
Sentry release upload token (build-time) | CI environment variable |
NEXT_PUBLIC_* values |
Public config (not secret) | ENV_FILE build arg |
There are no ExternalSecret manifests in the frontend Helm chart — the stateless nature of the app means secrets are limited to build artefacts and any server-side API routes that proxy backend calls.
Key Dependencies¶
Runtime (apps/web/package.json — selected)¶
| Package | Version | Purpose |
|---|---|---|
next |
(workspace) | Next.js framework |
react / react-dom |
(workspace) | React |
@sentry/nextjs |
~10.51.0 | Sentry error/performance monitoring |
@sentry/profiling-node |
~10.51.0 | Node.js profiling |
@tanstack/react-table |
~8.20.6 | Data tables |
@radix-ui/react-* |
various | Accessible UI primitives |
framer-motion |
~12.4.1 | Animation library |
date-fns |
~4.1.0 | Date formatting |
dompurify |
~3.3.1 | XSS sanitization |
html2canvas |
~1.4.1 | Screenshot / canvas |
json-bigint |
~1.0.0 | BigInt-safe JSON parsing |
@notionhq/client |
~3.1.3 | Notion API client |
@microlink/mql |
~0.13.14 | URL metadata |
fast-deep-equal |
~3.1.3 | Deep equality comparison |
import-in-the-middle |
~3.0.1 | Module instrumentation |
@workspace/analytics |
workspace | Internal analytics package |
@workspace/errors |
workspace | Internal error handling |
@workspace/network |
workspace | Internal API client |
@workspace/ui |
workspace | Internal component library |
Build / Dev (monorepo root devDependencies)¶
| Package | Version | Purpose |
|---|---|---|
turbo |
2.9.3 | Monorepo build orchestration |
typescript |
5.5.4 | TypeScript compiler |
eslint |
9.17 | Linting |
prettier |
3.2.5 | Code formatting |
prettier-plugin-tailwindcss |
0.6.11 | Tailwind class sorting |
husky |
9.1.7 | Git hooks |
commitlint |
20.4.2 | Conventional commit enforcement |
only-allow |
— | Enforce pnpm as package manager |
Package Manager¶
pnpm (enforced via only-allow). Node.js ≥ 22 required.
Security Overrides (pnpm)¶
The monorepo pins these transitive dependencies for security:
| Package | Pinned Version |
|---|---|
tar-fs |
≥ 2.1.3 |
form-data |
4.0.4 |
esbuild |
≥ 0.28 |
picomatch |
4.0.4 |
flatted |
3.4.2 |
minimatch |
5.1.2 |
lodash |
4.18.1 |
@sentry/cli |
3.4.1 |
import-in-the-middle |
3.0.1 |
CI/CD Pipeline¶
File: .gitlab-ci.yml
Tool: GitLab CI
| Stage | Key Jobs | Description |
|---|---|---|
validate |
validate |
ESLint, TypeScript type-check |
build-dev |
build-dev |
Docker build to ACR with dev ENV_FILE |
auto-version-bump |
auto-version-bump |
Semantic version bump on merge to main |
helm-release |
helm-release |
Publish Helm chart to GitLab OCI registry |
The production build uses a separate ENV_FILE override passed as a CI/CD variable per environment.