Bot Studio
Deployment & environment
Deploy WRNexus Bot Studio at bots.wrnexus.com — every environment variable the Astro app and bot runtime need (with the BOTS_ENABLED kill-switch and shared DATABASE_URL / ENCRYPTION_KEY), plus the exact local, Docker, Fly.io and CI run/build/test commands.
Bot Studio is the apps/bots Astro SSR app served at
bots.wrnexus.com, backed by the shared Rust API
(services/api) that owns all bot state, the public chat runtime, the widget
assets and the outbound webhooks. The app reuses the API’s database and
encryption key — no separate database is provisioned.
This page lists every environment variable the bot surfaces add, then the exact commands to run, build and test the app locally, in Docker, on Fly.io and in CI.
Environment variables
These are the variables introduced for Bot Studio. They live in
.env.example; the values below mirror it exactly.
Bot Studio (apps/bots)
| Variable | Required | Purpose |
|---|---|---|
BOTS_ENABLED |
yes (false default) |
Master kill-switch. While unset/false the runtime accepts no inbound events and dispatches no replies — mirrors PUSH_ENABLED / WHATSAPP_ENABLED. Flip to true only once the runtime pipeline is verified. |
PUBLIC_BOTS_PUBLIC_KEY |
no | Public (browser-safe) key identifying a workspace’s embeddable web chat widget. Surfaced to the page like PUBLIC_VAPID_PUBLIC_KEY — safe to expose. |
BOTS_RUNTIME_TOKEN_SECRET |
yes (prod) | Server-only secret used to sign the short-lived per-conversation runtime tokens minted for the chat widget / channel connectors. Generate with openssl rand -hex 32. |
BOTS_WEBHOOK_SECRET |
yes (prod) | Shared secret a channel provider must present (header X-Webhook-Token or ?token=) to POST inbound conversation events to the bot webhook. Leave blank to disable the check in development; always set a strong value in production. |
PUBLIC_BOTS_URL |
yes | Public origin of the Bot Studio app (https://bots.wrnexus.com). Used to build clean post-login redirect URLs behind the TLS-terminating proxy. Falls back to bots.<BASE_DOMAIN>. |
Generate the secrets with
openssl rand -hex 32(64 hex chars), the same as every other WRNexus 32-byte secret. Never commit the real values.
Reused from the shared platform config
Bot Studio deliberately rides on existing variables rather than duplicating them — the app and the API must agree on all of these:
| Variable | Why Bot Studio needs it |
|---|---|
DATABASE_URL |
All bot state (bots, versions, conversations, messages, contacts, forms, submissions, channels, webhooks) lives in the API’s database. |
ENCRYPTION_KEY |
Must match the API’s. Per-channel credentials and webhook signing secrets are stored AES-256-GCM-encrypted and must be decryptable by the API. |
REDIS_URL |
Backs the per-IP / per-conversation / per-key rate limiters on the runtime and client API. |
SSO_SVC_URL, ACCOUNT_SVC_URL, ADMIN_SVC_URL, BILLING_SVC_URL |
Server-to-server base URLs the Astro app calls (container DNS in Docker, https://wrnexus-api.fly.dev on Fly). |
PUBLIC_SSO_URL, PUBLIC_ACCOUNT_URL, PUBLIC_ADMIN_URL |
Browser-visible origins for cross-app links and post-login redirects. |
PUBLIC_ALLOWED_REDIRECT_HOSTS |
Must include bots.wrnexus.com so post-login redirects to the app are allowed. |
SESSION_COOKIE_NAME, SESSION_DOMAIN / COOKIE_DOMAIN, BASE_DOMAIN |
Shared session cookie so a user signed in to any WRNexus app is signed in to Bot Studio. |
The public widget, hosted page and runtime are served from the API origin (
https://app.wrnexus.com), so theapp.wrnexus.comdeployment must be live for the embed surfaces to work — thebots.wrnexus.comapp hosts the dashboard and the/c/{bot_id}hosted page wrapper.
Run, build & test
The app is a standard Astro SSR app (Node adapter) on port 4333, deployed via
the shared Dockerfile.app with APP_NAME=bots — exactly like every other
WRNexus app.
Local development
# from the repo root — install workspace deps once
pnpm install
# run the Bot Studio app with live reload (http://localhost:4333)
pnpm dev:bots
# …or, scoped to the package:
pnpm --filter @wrnexus/bots dev
The dashboard needs the API running too. The simplest path is the Docker stack
below; otherwise start services/api (port 9001) and point the *_SVC_URL
vars at it.
Type-check, lint & build
# type-check (astro check + tsc)
pnpm --filter @wrnexus/bots typecheck
# lint
pnpm --filter @wrnexus/bots lint
# production build (emits apps/bots/dist/server/entry.mjs)
pnpm build:bots
# …or: pnpm --filter @wrnexus/bots build
# preview the built SSR output on :4333
pnpm --filter @wrnexus/bots preview
Build the whole monorepo (packages then apps) with pnpm build:all.
API tests (runtime, widget, webhooks, client API)
The bot endpoints documented across these pages live in services/api. Run its
Rust test suite:
cd services/api
# all bot tests
cargo test --lib bot
# or target one surface
cargo test --lib bot_widget # widget config + branding resolution
cargo test --lib bot_chat # runtime token + grounded replies
cargo test --lib bot_webhooks # signature + retry backoff
cargo test --lib bot_api # client API key scoping + pagination
# compile check
cargo build
Docker Compose (full local stack)
# build + start every app, the API, Postgres, Redis and MailHog
docker compose up --build -d
# run DB migrations + seed (creates the bot tables)
docker compose --profile migrate run --rm migrate
Bot Studio is then on http://localhost:4333 and the API (widget assets,
runtime, webhooks) on http://localhost:9001. BOTS_ENABLED is wired through
the shared Astro env block in docker-compose.yml.
Deploy to Fly.io
Bot Studio has its own Fly app config, fly.bots.toml (app wrnexus-bots,
region bom, internal port 4333, /healthz checks).
# first-time custom domain + TLS
fly certs add bots.wrnexus.com --config fly.bots.toml
# set secrets once (never commit these). Flip BOTS_ENABLED only after
# the runtime pipeline is verified in production.
fly secrets set --config fly.bots.toml \
BOTS_ENABLED="true" \
PUBLIC_BOTS_PUBLIC_KEY="…" \
BOTS_RUNTIME_TOKEN_SECRET="$(openssl rand -hex 32)" \
BOTS_WEBHOOK_SECRET="$(openssl rand -hex 32)" \
SENTRY_DSN="…"
# deploy
fly deploy --config fly.bots.toml
DATABASE_URL and ENCRYPTION_KEY are inherited from the shared API secrets and
must match the API app — Bot Studio reads and writes the same database and
must decrypt the same channel/webhook secrets.
Go-live checklist
- Migrations applied — the
bot_*tables exist in the shared database. bots.wrnexus.comdeployed withPUBLIC_BOTS_URLset and added toPUBLIC_ALLOWED_REDIRECT_HOSTS.app.wrnexus.com(the API) live — it serveswidget.js,widget/config,embed/{id}, the/api/v1/chat/*runtime, the/api/v1/bot/*client API and the outbound webhooks.- Secrets set —
BOTS_RUNTIME_TOKEN_SECRET,BOTS_WEBHOOK_SECRET, and a matchingENCRYPTION_KEY. - Flip
BOTS_ENABLED=trueonce the runtime is verified end-to-end. - Publish a bot and confirm the widget loads, the hosted page renders, and a test webhook is signed and delivered.