Flow

Last updated: Apr 1, 2026Section: Integrations

Chat widget --- Next.js (Mailoo apps/web)


This example matches how the Mailoo web app can expose a site chat without putting an API key in the browser.

::: {.contents local=""} :::

Flow

  1. The browser calls only same-origin routes on your Next.js app:
  • POST /api/v1/webhooks/chat/submit --- body { "content": "...", "sessionPublicId?": "..." }.
  • GET /api/v1/webhooks/chat/messages?sessionPublicId=... --- optional polling.
  1. The Route Handler forwards to Mailoo with X-API-Key from server env (see proxyMailooWebhookJsonPost in apps/web/src/app/api/v1/lib/proxy-mailoo-webhook-post.ts). If auth() returns a logged-in user, the handler sets senderEmail / senderName from the session (so the dashboard shows the visitor identity instead of Guest).
  2. Optional: the widget opens WebSocket to the API. The host is resolved at runtime on the server (no NEXT_PUBLIC_* baked at build time):
  • Default order: MAILOO_CHAT_WS_ORIGINMAILOO_CHAT_INTEGRATION_APIAPI_BASE_URL (see getMailooChatWebSocketOrigin in apps/web/src/lib/mailoo-chat-integration.ts).
  • Set MAILOO_CHAT_WS_ORIGIN in production when the browser-visible API hostname differs from the URL the Node server uses to call the API.

Environment variables (apps/web/.env.local)

Server-only (including WebSocket host --- set per deployment / runtime, not at Next.js build):

MAILOO_CHAT_INTEGRATION_API="http://localhost:4077"
MAILOO_CHAT_INTEGRATION_API_KEY="ml_dev_mailoo_web_chat_key"
MAILOO_CHAT_INTEGRATION_PROJECT_UID="mailoo-website"
MAILOO_CHAT_INTEGRATION_ID="mailoo_dev_chat_integration"
MAILOO_CHAT_WELCOME_MESSAGE="Hello! This is the Mailoo demo chat."

# Optional explicit public API origin for ws/wss (otherwise same as line above or API_BASE_URL)


# MAILOO_CHAT_WS_ORIGIN="https://api.example.com"

After pnpm run db:seed, the development seed creates the fixed integration id and API key above for admin@mailoo.dev (see apps/api/prisma/seed.ts). Regenerate apps/web/.env.local with the repo script so defaults stay aligned.

UI: global widget in Mailoo web

When the server-side MAILOO_CHAT_* variables are set, MailooSiteChatGate renders a floating chat control from the locale layout. The WebSocket base URL is read from server env on each request.

Dashboard: chat console

For JSBOX integrations, Open chat console opens /dashboard/projects/{uid}/integrations/{id}/chat. The client loads the WS base from GET /api/v1/internal/chat-ws-origin (server reads the same env as above). REST uses the existing BFF under /api/v1/chat/....

Copy-paste env block

The integration detail page includes an Embed chat on your site (BFF) snippet with the current projectUid and integrationId for your project.

📚