Action templates

Action templates turn the widget from a text-only assistant into a guided, interactive surface: buttons, cards, forms, confirmations, status trackers, and vertical presets such as docs, lead capture, services booking, restaurant, ecommerce, and travel.

This is a foundation for assistants that can do useful work without each app forking the widget or inventing one-off UI. The core rule is simple: build verticals from generic primitives, then wire the actual business action on the server side.

Note

Client-side action templates are supported today. Hosted execution of arbitrary customer webhooks (tenant isolation, SSRF guards, idempotency, secrets, audit logs, rate limits, confirmation policies) is not yet available — implement server-side execution yourself in the meantime.

What ships in the widget

Import React primitives from the main package entrypoint, and import server-safe manifest data/types from the ./actions subpath when you are in server code, dashboard code, docs tooling, or any place that should not pull in the client component entry.

code
import {
  ActionButton,
  ActionChips,
  ActionForm,
  ConfirmationCard,
  EntityCard,
  EntityCarousel,
  StatusTracker,
  SummaryCard,
} from '@mordn/chat-widget';
import {
  leadCaptureTemplate,
  type MordnActionDispatcher,
} from '@mordn/chat-widget/actions';

The contract is intentionally small:

code
type MordnActionHandler = 'client' | 'server' | 'hosted';
type MordnActionLoadingBehavior = 'auto' | 'none' | 'self' | 'container';
type MordnActionConfirmationPolicy = 'none' | 'recommended' | 'required';
type MordnActionRiskLevel = 'ui' | 'read' | 'capture' | 'mutation' | 'regulated';
 
interface MordnActionConfig<TPayload = unknown> {
  type: string;                 // e.g. lead.capture, ecommerce.cart.add
  payload?: TPayload;           // untrusted until the server validates it
  handler?: MordnActionHandler;
  loadingBehavior?: MordnActionLoadingBehavior;
  confirmation?: MordnActionConfirmationPolicy;
  idempotencyKey?: string;
  label?: string;
  risk?: MordnActionRiskLevel;
  analyticsName?: string;
  schema?: MordnActionSchema;
}
 
type MordnActionDispatcher = (event: MordnActionEvent) => Promise<MordnActionResult | void> | void;

Example: lead capture

Use an action form to collect values, then hand the event to your host code. The host still validates and persists server-side.

code
import { ActionForm } from '@mordn/chat-widget';
import { leadCaptureTemplate, type MordnActionDispatcher } from '@mordn/chat-widget/actions';
 
const onAction: MordnActionDispatcher = async ({ action, values }) => {
  if (action.type !== 'lead.capture') return;
 
  await fetch('/api/leads', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(values),
  });
};
 
export function LeadCaptureDemo() {
  return (
    <ActionForm
      title="Book a demo"
      description="Tell us where to follow up."
      action={leadCaptureTemplate.actions[0]}
      onAction={onAction}
      fields={[
        { name: 'email', label: 'Work email', type: 'email', required: true },
        { name: 'company', label: 'Company' },
        { name: 'message', label: 'What are you trying to do?', type: 'textarea', required: true },
      ]}
    />
  );
}

Warning

Client-side examples are only interaction wiring. Never treat browser-submitted payloads or browser-supplied user ids as authoritative. Server actions must use getUserId / getChatUserId verified identity.

Generic primitives

ActionButton and ActionChips

Use for guided next steps, quick replies, local UI actions, or server actions.

  • ActionButton emits one MordnActionConfig.
  • ActionChips renders a small set of next actions.
  • Use client handlers for local UI work such as opening a modal or checkout.
  • Use server or hosted handlers for reads, capture, and mutations.

ActionForm

Use for lightweight structured input:

  • lead capture
  • reservation requests
  • callback requests
  • service intake
  • quote requests
  • support ticket details

For complex validation, payments, or sensitive data, open a host-owned page or modal and send only the final safe result back to the widget.

EntityCard and EntityCarousel

Use for vertical cards:

  • menu items
  • products
  • services
  • hotel options
  • destinations
  • plans
  • events
  • support resources

Each card supports image, title, subtitle, description, attributes, price or badge, and action buttons or safe external links.

SummaryCard and ConfirmationCard

Use a summary before consequential actions. A confirmation should show what will happen, where data will go, and how the user can cancel.

StatusTracker

Use for order status, booking state, setup checklists, support ticket progress, or itinerary steps.

Built-in starter manifests

The package ships starter manifests for six verticals:

TemplateWhat it covers
docs-assistantcitations, setup guidance, open-page actions, unanswered question capture
lead-capturequalification, form capture, summary, CRM or webhook handoff
services-bookingservice selection, intake, request-to-book, status updates
restaurant-assistantmenu cards, dietary badges, recommendations, reservation request
ecommerce-conciergeproduct cards, variant selection, cart/checkout handoff
travel-plannerdestination or hotel cards, itinerary timeline, quote request

The restaurant, ecommerce, and travel templates deliberately use request or handoff language by default. Don't let them imply confirmed inventory, purchase, payment, or reservation unless a configured action result actually confirms it.

Safety model

Action templates have five risk levels:

LevelExamplesDefault posture
uiopen modal, navigate, open checkout linkclient handler is fine
readsearch menu, lookup order, check public statusserver validation and timeout
capturelead form, booking request, support ticketconfirmation or clear submit, audit redaction
mutationcreate CRM record, add to cart server-side, reserve slotrequired confirmation and idempotency
regulatedpayment card, medical/legal/financial commitmenthand off outside chat

Server-side or hosted execution should enforce:

  • verified user identity
  • schema validation
  • authorization and tenant scope
  • idempotency
  • rate limits
  • confirmation policy
  • timeouts
  • audit logs
  • redaction for sensitive fields
  • SSRF-safe webhook calls

Template strategy

Don't build one-off restaurant, ecommerce, or travel widgets. Build reusable primitives and declarative manifests, then layer verticals on top.

The docs assistant, lead capture, and services-booking templates need no live inventory, cart, or payment integration, so they're the fastest to stand up. Ecommerce and travel templates are worth reaching for once you have a stable action-execution and confirmation flow in place, since they carry more transactional risk.

Hosted execution and dashboard tooling

The primitives above cover client-side templates. Hosted, per-tenant action execution — with a dashboard template gallery, action editor, and analytics — is not yet available; server-side execution is currently something you wire up yourself, as described in the safety model above.

See AI UX extras for related follow-up chips, action-result cards, and tool approval patterns.