Hosted

The hosted backend replaces your chat database and attachment bucket with @mordn/chat-api. The API key authenticates a tenant and agent; the handler's verified userId scopes each end-user request.

createMordnHandler

One key wires published config, persistence, storage, and feedback. This is the recommended setup.

code
app/api/chat/[[...chat]]/route.ts
import { createMordnHandler } from '@mordn/chat-widget/server';
import { auth } from '@clerk/nextjs/server';
 
export const { GET, POST, DELETE, OPTIONS } = createMordnHandler({
  apiKey: process.env.MORDN_CHAT_KEY!,
  getUserId: async () => (await auth()).userId,
});
code
MORDN_CHAT_KEY="mck_live_..."

Every other createChatHandler option is accepted alongside apiKey and getUserId, so you can add buildTools, cors, or knowledge without giving up the hosted wiring.

Wiring the pieces yourself

createMordnHandler composes these four clients. Use them directly when you want to mix hosted and self-hosted parts — for example hosted config with your own Postgres store.

code
import {
  createHostedChatStore,
  createHostedStorage,
  createHostedConfig,
  createHostedFeedback,
} from '@mordn/chat-widget/server/hosted';
 
const hosted = { apiKey: process.env.MORDN_CHAT_KEY! };
 
export const { GET, POST, DELETE } = createChatHandler({
  getUserId: getChatUserId,
  store: createHostedChatStore(hosted),
  storage: createHostedStorage(hosted),
  getHostedConfig: createHostedConfig(hosted),
  onFeedback: createHostedFeedback(hosted),
});

baseUrl defaults to https://api.mordn.com; timeoutMs defaults to 30 seconds. The key is server-only.

Hosted configuration precedence

createHostedConfig caches per-user results in process for 60 seconds and returns null on failure. The current normalized fields include model, system prompt, greeting, appearance, max output tokens, and follow-ups.

  • Model: code, then hosted config, then an error.
  • System prompt: code, then hosted config, then the package generic prompt.
  • Output cap: code, then hosted config, then provider default.
  • Follow-ups: code, then hosted config, then off.

Warning

A control-plane failure is harmless only when required code fallbacks exist. If you omit model and hosted configuration is unavailable or has no model, the turn fails because there is no package-default model.

Store behavior

The hosted store implements ownership-scoped conversation and message persistence. Its current listMessages implementation fetches the complete conversation and ignores limit/before; do not promise infinite-scroll pagination until the hosted API/store implements it.

Hosted storage provides upload, re-sign, and removal over the same tenant and verified-user axes.