WebChat
Overview
Section titled “Overview”The WebChat and WebChat GUI messaging extensions let you embed a chat experience directly in your website. messaging-webchat exposes the Direct Line-compatible messaging surface, and messaging-webchat-gui adds the hosted fullpage UI and embeddable chat bubble. They support:
- Real-time messaging
- Adaptive Cards
- File uploads
- Custom theming
- Mobile responsive
- OAuth/OIDC authentication (Google, Microsoft Entra ID, GitHub, custom OIDC)
- Built-in locale picker for language selection
Architecture
Section titled “Architecture”User's Browser │ ▼ HTTP / WebSocket polling stream┌─────────────────────────────────────────┐│ WebChat Widget (React) ││ (greentic-webchat component) │└─────────────────────────────────────────┘ │ ▼ Direct Line Protocol┌─────────────────────────────────────────┐│ Direct Line-compatible surface ││ (messaging-webchat pack) │└─────────────────────────────────────────┘ │ ▼ runtime routing┌─────────────────────────────────────────┐│ Greentic Runner │└─────────────────────────────────────────┘-
Configure Provider
answers.json {"setup_answers": {"messaging-webchat-gui": {"public_base_url": "https://your-domain.com","mode": "websocket","route": "webchat","tenant_channel_id": "demo:webchat"}}}modedefaults towebsocket. You do not need to providejwt_signing_key; setup generates a 20-character signing key and stores it as a tenant secret. -
Run Setup
Terminal window gtc setup --answers answers.json ./my-bundle -
Start Runtime
Terminal window gtc start ./my-bundle -
Embed in Website
There are three ways to embed WebChat. Choose the one that fits your use case:
Link directly to the hosted fullpage chat UI:
<a href="https://your-domain.com/webchat/gui/demo/default">Open Support Chat</a>Embed the chat in a specific area of your page:
<iframesrc="https://your-domain.com/webchat/gui/demo/default"width="400"height="600"style="border: none; border-radius: 8px;"title="Support Chat"></iframe>Add a floating chat bubble to every page:
<script>window.greenticChatConfig = {tenant: 'demo',baseUrl: 'https://your-domain.com'};</script><script src="https://your-domain.com/v1/web/webchat/demo/embed.js" defer></script>
Configuration Options
Section titled “Configuration Options”| Option | Required | Description |
|---|---|---|
public_base_url | Yes | Public runtime URL used in generated links and client configuration |
mode | Yes | WebChat connection mode. Defaults to websocket for WebChat GUI |
route | No | Web route, usually webchat |
tenant_channel_id | No | Tenant/channel binding used by the generated GUI |
base_url | No | Optional Direct Line or WebChat server base URL |
oauth_enabled | No | Enable OAuth/OIDC login for WebChat (default: false) |
oauth_enable_google | No | Enable Google login in the GUI |
oauth_enable_microsoft | No | Enable Microsoft login in the GUI |
oauth_enable_github | No | Enable GitHub login in the GUI |
oauth_enable_custom | No | Enable custom OIDC login in the GUI |
skin | No | Visual skin shipped by the WebChat GUI pack |
presentation_mode | No | standalone or embed_webcomponent |
jwt_signing_key | Generated secret | Generated by setup and persisted as a tenant secret |
Network Access
Section titled “Network Access”WebChat and WebChat GUI are browser-facing providers. They do not require a third-party messaging platform to call Greentic, but the hosted UI, embed script, Direct Line-compatible HTTP endpoints, and WebSocket endpoint must be reachable by user browsers.
| Direction | Protocol and port | Purpose |
|---|---|---|
| Incoming | HTTPS 443 from browsers to Greentic | Hosted fullpage UI, embed script, static assets, Direct Line-compatible REST calls, and file upload/download routes |
| Incoming | WSS 443 from browsers to Greentic | Real-time WebChat connection when mode is websocket, which is the WebChat GUI default |
| Incoming, local development | HTTP and WS on the local runtime port, usually behind a tunnel | Local testing before the public HTTPS tunnel terminates TLS |
| Outgoing | Usually none for messaging delivery | WebChat messages route through the local Greentic runtime rather than a third-party messaging API |
| Outgoing, OAuth/OIDC enabled | HTTPS 443 to the configured identity provider | Login redirects, token exchange, and OIDC metadata or key discovery depending on the configured provider |
For production browser access, terminate TLS at the public endpoint and expose HTTPS/WSS on port 443. If you choose local_queue, browsers use HTTPS polling instead of WSS, but they still need the same public HTTPS route.
Widget Configuration
Section titled “Widget Configuration”Basic Setup
Section titled “Basic Setup”<script> window.greenticChatConfig = { tenant: 'demo', baseUrl: 'https://your-domain.com' };</script><script src="https://your-domain.com/v1/web/webchat/demo/embed.js" defer></script>With Theming
Section titled “With Theming”<script> window.greenticChatConfig = { tenant: 'demo', baseUrl: 'https://your-domain.com', theme: { primaryColor: '#0078D4', backgroundColor: '#f5f5f5', bubbleBackground: '#ffffff', bubbleFromUserBackground: '#0078D4', bubbleTextColor: '#333333', bubbleFromUserTextColor: '#ffffff', sendBoxBackground: '#ffffff', sendBoxTextColor: '#333333' } };</script><script src="https://your-domain.com/v1/web/webchat/demo/embed.js" defer></script>With User Info
Section titled “With User Info”<script> window.greenticChatConfig = { tenant: 'demo', baseUrl: 'https://your-domain.com', user: { id: 'user-123', name: 'John Doe', email: 'john@example.com' } };</script><script src="https://your-domain.com/v1/web/webchat/demo/embed.js" defer></script>Minimized Start
Section titled “Minimized Start”<script> window.greenticChatConfig = { tenant: 'demo', baseUrl: 'https://your-domain.com', openOnLoad: false };</script><script src="https://your-domain.com/v1/web/webchat/demo/embed.js" defer></script>Features
Section titled “Features”Text Messages
Section titled “Text Messages”- id: reply type: reply config: message: "Hello! How can I help you today?"Adaptive Cards
Section titled “Adaptive Cards”WebChat has full Adaptive Card support:
- id: welcome_card type: adaptive-card config: card: type: AdaptiveCard version: "1.4" body: - type: TextBlock text: "Welcome!" size: Large weight: Bolder - type: TextBlock text: "I'm your virtual assistant. How can I help?" - type: ActionSet actions: - type: Action.Submit title: "Get Help" data: action: "help" - type: Action.Submit title: "Contact Support" data: action: "support"Quick Replies (Suggested Actions)
Section titled “Quick Replies (Suggested Actions)”- id: suggestions type: reply config: message: "What would you like to do?" suggested_actions: - "Check Order Status" - "Talk to Support" - "View FAQs"File Uploads
Section titled “File Uploads”Enable file uploads:
window.greenticChatConfig = { // ... other config uploadEnabled: true, uploadAccept: '.pdf,.doc,.docx,.png,.jpg', uploadMaxSize: 10485760 // 10MB};Handle uploads in flow:
- id: handle_upload type: branch config: conditions: - expression: "attachments.length > 0" to: process_file default: normal_message
- id: process_file type: reply config: message: "Thanks! I've received your file: {{attachments[0].name}}"Typing Indicator
Section titled “Typing Indicator”- id: thinking type: reply config: typing: true typing_duration: 2000 # milliseconds to: actual_reply
- id: actual_reply type: reply config: message: "Here's what I found..."Attachment Envelope Shape
Section titled “Attachment Envelope Shape”WASM components emit outputs as JSON (serialized to CBOR). The runtime wraps each output into a ChannelMessageEnvelope before handing it to the WebChat provider, which in turn serializes the envelope to a DirectLine activity on the wire.
Structured, provider-aware data travels in the envelope’s extensions map — not at the top level of the component output. extensions is the canonical carrier: it is provider-agnostic, round-trips end-to-end, and the WebChat provider passes known keys through to DirectLine verbatim (no stripping, no normalization).
Well-known extension keys
Section titled “Well-known extension keys”The keys below are declared in greentic-types (src/messaging/extensions.rs) and are the source of truth. Downstream consumers must tolerate unknown keys and MUST round-trip them — stripping unrecognized keys is a bug.
| Key | Shape | Purpose |
|---|---|---|
adaptive_card | Object | Adaptive Card JSON. Replaces the legacy metadata["adaptive_card"] string convention. |
channel_data | Object | Bot Framework / DirectLine channelData — free-form per-channel metadata. |
entities | Array | Bot Framework entities array (mentions, structured annotations, …). |
attachments | Array | Provider-native attachments with inline content. Preferred over the URL-only envelope.attachments when inline content is required (e.g. Adaptive Cards). |
Other well-known keys — rag, suggested_actions, speak, input_hint — follow the same pass-through rule.
Accepted shapes from components
Section titled “Accepted shapes from components”The WebChat provider accepts attachments in either of two shapes. Both round-trip to the DirectLine activity identically:
- Top-level
attachmentsarray on the component output — convenient when you are already writing DirectLine-native JSON. extensions["attachments"]array on the envelope — the canonical carrier, useful when other extension keys are set alongside (channel_data,entities, …).
Each attachment entry uses the Bot Framework {contentType, content} shape. For an Adaptive Card:
{ "contentType": "application/vnd.microsoft.card.adaptive", "content": { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.5", "body": [ { "type": "TextBlock", "text": "Welcome!" } ] }}Minimal Rust component example
Section titled “Minimal Rust component example”The following component output emits an Adaptive Card attachment plus channelData and entities. All three round-trip to the DirectLine activity reaching the WebChat client.
Schematic: the snippets below illustrate the JSON output shape, not the component entrypoint. Real Greentic components expose operations through their WIT world (via wit-bindgen-generated trait impls) — see the component authoring guide for the actual entrypoint.
use serde_json::json;
fn build_output() -> serde_json::Value { let card = json!({ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.5", "body": [ { "type": "TextBlock", "text": "Welcome!", "weight": "Bolder", "size": "Medium" } ] });
json!({ "text": "Here is your card:", "attachments": [ { "contentType": "application/vnd.microsoft.card.adaptive", "content": card } ], "channelData": { "source": "my-component" }, "entities": [ { "type": "mention", "id": "user-123" } ] })}Equivalent output using the canonical extensions carrier:
// card is the same AdaptiveCard JSON as abovejson!({ "text": "Here is your card:", "extensions": { "attachments": [ { "contentType": "application/vnd.microsoft.card.adaptive", "content": card } ], "channel_data": { "source": "my-component" }, "entities": [ { "type": "mention", "id": "user-123" } ] }})API Integration
Section titled “API Integration”JavaScript API
Section titled “JavaScript API”// Get chat instancegreenticChat.open();greenticChat.close();greenticChat.toggle();greenticChat.isOpen();greenticChat.hide();greenticChat.show();greenticChat.resetBadge();REST API
Section titled “REST API”Direct Line REST API endpoints:
# Start conversationPOST /v1/messaging/webchat/{tenant}/v3/directline/conversationsAuthorization: Bearer <token>
# Send messagePOST /v1/messaging/webchat/{tenant}/v3/directline/conversations/{conversationId}/activitiesContent-Type: application/json
{ "type": "message", "text": "Hello!"}
# Get messagesGET /v1/messaging/webchat/{tenant}/v3/directline/conversations/{conversationId}/activitiesCustomization
Section titled “Customization”Custom CSS
Section titled “Custom CSS”<style> .greentic-webchat { --primary-color: #0078D4; --background-color: #ffffff; --text-color: #333333; --border-radius: 8px; --font-family: 'Segoe UI', sans-serif; }
.greentic-webchat .message-bubble { box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.greentic-webchat .send-button { background-color: var(--primary-color); }</style>Custom Avatar
Section titled “Custom Avatar”window.greenticChatConfig = { // ... other config botAvatar: 'https://example.com/bot-avatar.png', userAvatar: 'https://example.com/user-avatar.png', showAvatars: true};Custom Header
Section titled “Custom Header”The header area can display a title, subtitle, and close button. When the locale picker is enabled, it appears in the header. When OAuth is enabled, a logout button is also rendered in the header next to the locale picker.
window.greenticChatConfig = { // ... other config header: { title: 'Support Chat', subtitle: 'We usually reply within minutes', showCloseButton: true }};Bundle Assets & Skin Customization
Section titled “Bundle Assets & Skin Customization”When the greentic.cap.bundle_assets.read.v1 capability is enabled, the wizard scaffolds a per-tenant skin directory under ./assets/ in your bundle. You can edit these files to customize the WebChat appearance without rebuilding the provider pack.
How Skin Overlay Works
Section titled “How Skin Overlay Works”The runtime resolves asset files using an overlay strategy: bundle files override pack defaults on a per-file basis. If you customize skin.json in your bundle, the runtime uses your version. If you leave page.css untouched, the pack’s built-in default is used.
This means you can selectively override only the files you need to change.
File Reference
Section titled “File Reference”| File | Location | Purpose |
|---|---|---|
skin.json | assets/webchat-gui/skins/{tenant}/skin.json | Theme config: colors, title, logo, feature flags |
index.html | assets/webchat-gui/skins/{tenant}/fullpage/index.html | Fullpage chat HTML template |
page.css | assets/webchat-gui/skins/{tenant}/fullpage/page.css | Fullpage custom styles |
bubble.css | assets/webchat-gui/skins/{tenant}/embed/bubble.css | Chat bubble custom styles |
en.json | assets/webchat-gui/skins/{tenant}/i18n/en.json | English locale strings |
id.json | assets/webchat-gui/skins/{tenant}/i18n/id.json | Indonesian locale strings |
{tenant}.html | assets/webchat-gui/embed/{tenant}.html | Auto-generated embed snippets |
Example: Changing the Theme
Section titled “Example: Changing the Theme”Edit skin.json to update colors and branding:
{ "title": "Acme Support", "subtitle": "We are here to help", "logo": "/assets/webchat-gui/skins/demo/logo.png", "primaryColor": "#E63946", "backgroundColor": "#F1FAEE", "showLocalePicker": true, "showOAuthLogin": true, "embedEnabled": true}No rebuild or restart is needed — the runtime picks up the changes on the next request.
Multi-Language Support
Section titled “Multi-Language Support”The WebChat GUI includes a built-in locale picker that lets users switch languages at runtime. The locale picker appears in the chat header, allowing users to select their preferred language without reloading the page.
window.greenticChatConfig = { // ... other config locale: 'es-ES', showLocalePicker: true, availableLocales: ['en-US', 'es-ES', 'fr-FR', 'de-DE', 'ja-JP'], strings: { 'placeholder': 'Escribe un mensaje...', 'send': 'Enviar', 'connecting': 'Conectando...', 'reconnecting': 'Reconectando...' }};When showLocalePicker is enabled, a language selector appears in the header next to the close button (and logout button, if OAuth is enabled). Changing the locale updates all UI strings and notifies the flow so responses can adapt to the selected language.
OAuth/OIDC Authentication
Section titled “OAuth/OIDC Authentication”WebChat supports optional OAuth/OIDC authentication to require users to log in before accessing the chat. When enabled, a login overlay is displayed before the chat interface becomes available. The implementation uses a client-side PKCE (Proof Key for Code Exchange) flow for security.
Supported Providers
Section titled “Supported Providers”| Provider | Wizard fields | Notes |
|---|---|---|
oauth_enable_google, oauth_google_client_id, oauth_google_client_secret | Google OAuth 2.0 | |
| Microsoft (Entra ID) | oauth_enable_microsoft, oauth_microsoft_client_id, oauth_microsoft_client_secret | Microsoft identity platform |
| GitHub | oauth_enable_github, oauth_github_client_id, oauth_github_client_secret | GitHub OAuth Apps |
| Custom OIDC | oauth_enable_custom, oauth_custom_auth_url, oauth_custom_token_url, oauth_custom_client_id, oauth_custom_scopes | Any OpenID Connect-compatible provider exposed by the installed pack |
How It Works
Section titled “How It Works”- User opens the WebChat widget
- A login overlay is shown with a sign-in button for the configured provider
- The user authenticates through the provider’s login flow (client-side PKCE)
- On successful authentication, the overlay is dismissed and the chat becomes accessible
- The authenticated user’s identity is passed to the flow as user context
- A logout button appears in the header (next to the locale picker) for signing out
Provider Setup
Section titled “Provider Setup”Each provider is configured through the answers.json file or interactively via gtc setup. The wizard-generated schema is the source of truth for the exact fields supported by the installed pack.
-
Create OAuth credentials in the Google Cloud Console
- Create a new OAuth 2.0 Client ID
- Set application type to “Web application”
- Add your WebChat domain to “Authorized JavaScript origins”
- Add
https://your-domain.com/webchat/auth/callbackto “Authorized redirect URIs”
-
Configure the provider
answers.json {"setup_answers": {"messaging-webchat-gui": {"public_base_url": "https://your-domain.com","mode": "websocket","oauth_enabled": true,"oauth_enable_google": true,"oauth_google_client_id": "123456789.apps.googleusercontent.com","oauth_google_client_secret": "your-google-client-secret"}}} -
Run setup and start
Terminal window gtc setup --answers answers.json ./my-bundlegtc start ./my-bundle
Microsoft (Entra ID)
Section titled “Microsoft (Entra ID)”-
Register an application in the Azure Portal
- Register a new application under “App registrations”
- Set the redirect URI to
https://your-domain.com/webchat/auth/callback(type: SPA) - Under “Authentication”, enable “Access tokens” and “ID tokens” for implicit grant
- Note your Application (client) ID and Directory (tenant) ID
-
Configure the provider
answers.json {"setup_answers": {"messaging-webchat-gui": {"public_base_url": "https://your-domain.com","mode": "websocket","oauth_enabled": true,"oauth_enable_microsoft": true,"oauth_microsoft_client_id": "your-application-client-id","oauth_microsoft_client_secret": "your-microsoft-client-secret"}}} -
Run setup and start
Terminal window gtc setup --answers answers.json ./my-bundlegtc start ./my-bundle
GitHub
Section titled “GitHub”-
Create an OAuth App in GitHub Developer Settings
- Go to “OAuth Apps” and create a new application
- Set the “Authorization callback URL” to
https://your-domain.com/webchat/auth/callback - Note the Client ID
-
Configure the provider
answers.json {"setup_answers": {"messaging-webchat-gui": {"public_base_url": "https://your-domain.com","mode": "websocket","oauth_enabled": true,"oauth_enable_github": true,"oauth_github_client_id": "your-github-client-id","oauth_github_client_secret": "your-github-client-secret"}}} -
Run setup and start
Terminal window gtc setup --answers answers.json ./my-bundlegtc start ./my-bundle
Custom OIDC Provider
Section titled “Custom OIDC Provider”-
Register a client with your OIDC provider
- Set the redirect URI to
https://your-domain.com/webchat/auth/callback - Ensure your provider supports PKCE
- Note the client ID and the issuer/authority URL
- Set the redirect URI to
-
Configure the provider
answers.json {"setup_answers": {"messaging-webchat-gui": {"public_base_url": "https://your-domain.com","mode": "websocket","oauth_enabled": true,"oauth_enable_custom": true,"oauth_custom_auth_url": "https://your-oidc-provider.com/oauth/authorize","oauth_custom_token_url": "https://your-oidc-provider.com/oauth/token","oauth_custom_client_id": "your-client-id","oauth_custom_scopes": "openid profile email"}}}Use
gtc setupto confirm whether your pack expects explicit authorization/token URLs or an issuer URL for custom OIDC. -
Run setup and start
Terminal window gtc setup --answers answers.json ./my-bundlegtc start ./my-bundle
Widget Configuration with OAuth
Section titled “Widget Configuration with OAuth”When OAuth is enabled on the server side, the widget automatically shows the login overlay. No additional client-side configuration is needed. The authenticated user’s identity is available in flows via the user context:
window.greenticChatConfig = { tenant: 'demo', baseUrl: 'https://your-domain.com' // OAuth login overlay is shown automatically when oauth_enabled is true};After authentication, the header displays a logout button next to the locale picker. Clicking it clears the session and returns the user to the login overlay.
Interactive Setup via QA Wizard
Section titled “Interactive Setup via QA Wizard”Instead of manually writing answers.json, you can use the interactive setup wizard which guides you through provider-specific configuration with conditional logic:
gtc setup ./my-bundleThe wizard detects OAuth-related fields and asks only the follow-up questions exposed by the installed pack version.
WebChat GUI Embed
Section titled “WebChat GUI Embed”The messaging-webchat-gui provider includes a full web UI served at /v1/web/webchat/{tenant}/ and a chat bubble widget that can be embedded on any website.
Quick Start
Section titled “Quick Start”Add a floating chat bubble to any page with two script tags:
<script> window.greenticChatConfig = { tenant: 'demo', baseUrl: 'https://your-domain.com', bubble: { color: '#10B981', label: 'Chat with us' }, window: { title: 'Support Assistant' } };</script><script src="https://your-domain.com/v1/web/webchat/demo/embed.js" defer></script>The baseUrl is auto-detected from the script src if not provided.
Full Configuration Reference
Section titled “Full Configuration Reference”window.greenticChatConfig = { // ── Required ── tenant: 'demo', // tenant ID — determines skin and routes
// ── Base ── baseUrl: 'https://your-domain.com', // auto-detected from script src fontFamily: 'Inter,system-ui,sans-serif', // font for all widget UI elements locale: '', // language passed to iframe (?lang=id)
// ── Bubble ── bubble: { color: '#10B981', // bubble background color (skin brand.primary) hoverColor: '#059669', // color on hover position: 'bottom-right', // bottom-right | bottom-left size: 56, // diameter in px offset: 20, // distance from edge in px offsetBottom: 20, // distance from bottom in px icon: null, // custom icon URL (replaces default chat SVG) iconSize: 28, // icon size in px label: 'Chat with us', // tooltip text on hover borderRadius: '50%', // '50%' = circle, '12px' = rounded square badge: true, // show unread message counter badgeColor: '#ef4444', // badge background color greeting: '', // proactive message above bubble greetingDelay: 3000, // ms before greeting appears (0 = immediate) },
// ── Chat Window ── window: { width: 400, // window width in px height: 620, // window height in px borderRadius: 12, // corner radius in px header: true, // show header bar headerColor: '#064e3b', // header background color headerTextColor: '#ffffff', // header text color title: 'Greentic Assistant', // header title (skin brand.name) logo: null, // header logo URL (skin brand.logo) logoSize: 24, // logo size in px shadow: '0 8px 40px rgba(0,0,0,0.2)', },
// ── Behavior ── openOnLoad: false, // auto-open on page load openDelay: 0, // delay in ms before auto-open closeOnEscape: true, // close with Escape key mobileFullscreen: true, // fullscreen on viewports < 480px persist: false, // remember open/close state across pages zIndex: 2147483646, // z-index for all widget elements sound: false, // play sound on new bot message soundUrl: '', // custom sound URL (default: built-in beep) animation: true, // pop-in entrance animation on mount
// ── Event Callbacks ── onOpen: function () {}, // chat window opened onClose: function () {}, // chat window closed onMessage: function (data) {}, // bot message received onUserMessage: function (data) {}, // user sent a message};Priority: explicit config > skin.json defaults > hardcoded defaults. For example, if you don’t set bubble.color, it falls back to skin.json → brand.primary → #10B981.
Public API
Section titled “Public API”After the widget mounts, a global greenticChat object is available:
greenticChat.open() // open the chat windowgreenticChat.close() // close the chat windowgreenticChat.toggle() // toggle open/closegreenticChat.isOpen() // returns booleangreenticChat.hide() // completely hide bubble + windowgreenticChat.show() // show bubble againgreenticChat.resetBadge() // clear unread message counterUnread Badge
Section titled “Unread Badge”When badge: true (default), a red counter appears on the bubble when the bot sends messages while the widget is closed. The badge automatically resets when the user opens the chat.
Greeting Bubble
Section titled “Greeting Bubble”Show a proactive message above the bubble to increase engagement:
bubble: { greeting: 'Hi! Need help? Ask me anything.', greetingDelay: 2000, // show after 2 seconds}The greeting dismisses when the user clicks it (opens chat) or clicks the close button. It only appears once per page load.
Sound Notifications
Section titled “Sound Notifications”Play a notification sound when a bot message arrives while the widget is closed:
{ sound: true, // enable with built-in beep // or sound: true, soundUrl: '/assets/notify.mp3', // custom sound file}The built-in sound is a short sine-wave beep generated via the Web Audio API — no external files needed.
Locale
Section titled “Locale”Pass a language to the webchat iframe:
{ locale: 'id', // loads iframe with ?lang=id}The webchat GUI picks up the lang query parameter and loads the corresponding i18n strings.
Persist State
Section titled “Persist State”Keep the widget open across page navigation within the same session:
{ persist: true, // uses sessionStorage}Entrance Animation
Section titled “Entrance Animation”By default, the bubble appears with a pop-in animation. Disable it with:
{ animation: false,}Event Callbacks
Section titled “Event Callbacks”React to widget events on the host page:
{ onOpen: function () { analytics.track('chat_opened'); }, onClose: function () { analytics.track('chat_closed'); }, onMessage: function (data) { console.log('Bot said:', data); }, onUserMessage: function (data) { console.log('User said:', data); },}Complete Example
Section titled “Complete Example”<!DOCTYPE html><html><head><title>My Website</title></head><body> <h1>Welcome to My Website</h1>
<script> window.greenticChatConfig = { tenant: 'demo', fontFamily: "'Segoe UI', Roboto, sans-serif", locale: 'en', bubble: { color: '#059669', hoverColor: '#047857', label: 'Need help?', badge: true, greeting: 'Hi! I can help you get started.', greetingDelay: 2000, }, window: { width: 420, height: 640, headerColor: '#064e3b', title: 'Support Assistant', }, persist: true, sound: true, animation: true, zIndex: 9999, onOpen: function () { console.log('Chat opened'); }, onMessage: function (data) { console.log('Bot:', data); }, }); </script> <script src="https://your-domain.com/v1/web/webchat/demo/embed.js" defer></script></body></html>Skins control the fullpage layout and branding. Each skin is a directory under assets/webchat-gui/skins/{name}/:
skins/{name}/ skin.json # Branding, colors, logo, mode fullpage/index.html # Landing page HTML fullpage/page.css # Landing page styles webchat/styleOptions.json webchat/hostconfig.json webchat/hooks.js assets/logo.svg assets/favicon.icoBundle Assets Overlay
Section titled “Bundle Assets Overlay”When greentic.cap.bundle_assets.read.v1 capability is enabled, the runtime scaffolds webchat-gui assets into the bundle’s assets/ directory. Files placed there override the provider pack defaults — allowing custom skins without rebuilding the pack.
Token Endpoint
Section titled “Token Endpoint”The runtime provides a native JWT token endpoint at:
GET /v1/messaging/webchat/{tenant}/tokenReturns: {"token": "<jwt>", "expires_in": 1800, "conversationId": ""}
The token is signed with the jwt_signing_key secret generated during setup.
Security
Section titled “Security”Token Security
Section titled “Token Security”- Tokens are short-lived (1 hour default)
- Tokens are scoped to conversation
- Refresh tokens are not exposed to client
OAuth/OIDC Security
Section titled “OAuth/OIDC Security”When OAuth is enabled:
- Authentication uses the PKCE flow, which does not require a client secret on the frontend
- Tokens are validated server-side before granting chat access
- The login overlay blocks all chat interaction until authentication succeeds
- Session logout clears tokens from the client and invalidates the server-side session
CORS Configuration
Section titled “CORS Configuration”{ "messaging-webchat": { "allowed_origins": [ "https://www.example.com", "https://app.example.com" ] }}Troubleshooting
Section titled “Troubleshooting”Widget Not Loading
Section titled “Widget Not Loading”- Check console for JavaScript errors
- Verify script URL is correct
- Check CORS configuration
Connection Failed
Section titled “Connection Failed”- Verify Direct Line endpoint is accessible
- Check WebSocket support
- Review firewall settings
Messages Not Sending
Section titled “Messages Not Sending”- Check conversation is active
- Verify token hasn’t expired
- Review browser console for errors
Next Steps
Section titled “Next Steps”- WebChat Embedding - Embed types, chat bubble config, and public JS API
- Bundle Assets - Capability system and skin overlay mechanism
- Adaptive Cards - Create rich cards
- Components - Customize component-driven behavior
- Flows Guide - Build conversation flows