A modern, React-based in-app support widget for Marketrix that provides Show, Tell, and Do modes with AI-powered assistance. Designed for easy integration into any website using a simple script tag.
- 🎯 Three Interaction Modes: Show, Tell, and Do
- 🎨 Modern UI: Built with React 19 and Tailwind CSS v4
- 🌙 Theme Support: Dark theme with customizable colors and appearance
- 📱 Responsive Design: Works on desktop, tablet, and mobile
- ⚙️ API-Driven Configuration: Dynamic settings from integration service
- 🔌 Easy Integration: Simple script tag integration
- 🚀 TypeScript: Full TypeScript support with comprehensive type definitions
- 📦 Standalone: Single file bundle with no external dependencies
- 🎥 Session Recording: Built-in RRWeb session recording with start/stop control
- 🔒 Shadow DOM Isolation: CSS isolation prevents conflicts with host app
- 🎛️ Widget Chips: Quick action chips for common tasks
- 🔄 WebSocket Communication: Real-time AI agent communication
- 🖥️ Screen Sharing: Screen access modals and video stream display
Add the widget to your HTML page using a script tag:
<script
src="https://cdn.marketrix.io/widget/index.mjs"
mtx-ai-host="https://agent.marketrix.ai"
mtx-api-host="https://api.marketrix.ai"
mtx-id="your-marketrix-id"
mtx-key="your-marketrix-key"
></script>For development/testing with direct agent and connection IDs:
<script
src="https://cdn.marketrix.io/widget/dev/index.mjs"
mtx-ai-host="https://agent.marketrix.ai"
mtx-api-host="https://api.marketrix.ai"
mtx-app="YOUR_CONNECTION_ID"
mtx-agent="YOUR_AGENT_ID"
></script>| Attribute | Type | Required | Description |
|---|---|---|---|
mtx-id |
string | ✅* | Your Marketrix ID (production mode) |
mtx-key |
string | ✅* | Your Marketrix API key (production mode) |
mtx-app |
number | ✅* | Connection/App ID (dev mode) |
mtx-agent |
number | ✅* | Agent ID (dev mode) |
mtx-api-host |
string | ✅ | API server URL (e.g., https://api.marketrix.ai) |
mtx-ai-host |
string | ✅ | AI/Agent server URL for WebSocket connection |
*Either mtx-id + mtx-key (production) OR mtx-app + mtx-agent (dev) must
be provided.
Widget appearance and behavior are configured through the API. Settings include:
- Appearance: Position, colors, border radius, shadows, dimensions
- Features: Enable/disable Tell, Show, Do modes, human handoff
- Device Visibility: Desktop, mobile, or both
- Text: Header, body, greeting messages
- Chips: Quick action buttons with predefined questions
The agent explains concepts, provides information, or answers questions with detailed explanations.
The agent demonstrates how to perform a task with step-by-step guidance and visual highlighting of UI elements.
The agent performs actions on your behalf using browser automation tools, including clicking, typing, scrolling, and navigating.
import {
initWidget,
unmountWidget,
mountWidget,
MarketrixWidget,
getCurrentConfig,
updateMarketrixConfig,
startRecording,
stopRecording,
getRecordingState,
} from '@marketrix.ai/widget';
// Initialize with production credentials
await initWidget({
mtxId: 'your-marketrix-id',
mtxKey: 'your-marketrix-key',
mtxApiHost: 'https://api.marketrix.ai',
mtxAiHost: 'https://agent.marketrix.ai',
});
// Or initialize with dev credentials
await initWidget({
mtxApp: 123,
mtxAgent: 456,
mtxApiHost: 'https://api.marketrix.ai',
mtxAiHost: 'https://agent.marketrix.ai',
});
// Initialize into a specific container element
await initWidget(config, document.getElementById('my-container')!);
// Update config at runtime (unmounts and reinitializes)
await updateMarketrixConfig({ mtxAiHost: 'https://new-agent.marketrix.ai' });
// Session recording controls
await startRecording();
stopRecording();
const isRecording = getRecordingState();
// Destroy widget
unmountWidget();import { MarketrixWidget } from '@marketrix.ai/widget';
function App() {
return (
<MarketrixWidget
settings={{
widget_enabled: true,
widget_appearance: 'default',
widget_position: 'bottom_right',
widget_device: 'desktop_mobile',
widget_header: 'AI Assistant',
widget_body: 'How can I help you today?',
widget_greeting: 'Hello! Ask me anything.',
widget_feature_tell: true,
widget_feature_show: true,
widget_feature_do: true,
widget_feature_human: false,
widget_background_color: '#ffffff',
widget_text_color: '#1f2937',
widget_border_color: '#e5e7eb',
widget_accent_color: '#3b82f6',
widget_secondary_color: '#6b7280',
widget_border_radius: '16px',
widget_font_size: '14px',
widget_width: '400px',
widget_height: '600px',
widget_shadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
widget_animation_duration: '300ms',
widget_fade_duration: '200ms',
widget_bounce_effect: true,
widget_chips: [],
}}
mtxApiHost="https://api.marketrix.ai"
mtxAiHost="https://agent.marketrix.ai"
/>
);
}import { mountWidget } from '@marketrix.ai/widget';
// Production mode
await mountWidget({
mtxId: 'your-id',
mtxKey: 'your-key',
mtxApiHost: 'https://api.marketrix.ai',
mtxAiHost: 'https://agent.marketrix.ai',
});
// Dev mode
await mountWidget({
mtxApp: 123,
mtxAgent: 456,
mtxApiHost: 'https://api.marketrix.ai',
mtxAiHost: 'https://agent.marketrix.ai',
});
// Preview mode (with settings directly)
await mountWidget({
settings: widgetSettings,
mtxApiHost: 'https://api.marketrix.ai',
mtxAiHost: 'https://agent.marketrix.ai',
});- Node.js 18+
- npm
- Clone the repository:
git clone <repository-url>
cd widget- Install dependencies (git hooks auto-installed via lefthook):
npm install- Start development server:
npm start- Build for production:
npm run buildBuild and serve the widget locally:
npm run build
npx serve dist -l 5174 --corsCreate a bookmark with this URL:
javascript: (function () {
var s = document.createElement('script');
s.src = 'http://localhost:5174/index.mjs';
s.setAttribute('mtx-ai-host', 'https://agent.marketrix.ai');
s.setAttribute('mtx-api-host', 'https://api.marketrix.ai');
s.setAttribute('mtx-app', 'YOUR_CONNECTION_ID');
s.setAttribute('mtx-agent', 'YOUR_AGENT_ID');
document.head.appendChild(s);
})();npm startThe dev server runs on port 5174 by default (configurable via PORT or
VITE_PORT env vars). Visit https://localhost:5174 and accept the
certificate, then use:
javascript: (function () {
var s = document.createElement('script');
s.src = 'https://localhost:5174/index.mjs';
s.setAttribute('mtx-ai-host', 'https://agent.marketrix.ai');
s.setAttribute('mtx-api-host', 'https://api.marketrix.ai');
s.setAttribute('mtx-app', 'YOUR_CONNECTION_ID');
s.setAttribute('mtx-agent', 'YOUR_AGENT_ID');
document.head.appendChild(s);
})();See chrome-extension/README.md for persistent widget injection across page navigations.
Build the debug panel using the dedicated Vite config:
npx vite build --config vite.config.debug.ts
npx serve dist -l 5174 --corsThen use this bookmarklet on any website:
javascript: (function () {
var s = document.createElement('script');
s.src = 'http://localhost:5174/debug.js';
document.body.appendChild(s);
})();Press Ctrl+Shift+D to toggle the debug panel.
widget/
├── src/
│ ├── components/ # React components
│ │ ├── chat/ # Chat UI components
│ │ │ ├── ChatWindow.tsx
│ │ │ ├── MessageContent.tsx
│ │ │ ├── MessageItem.tsx
│ │ │ ├── MessageList.tsx
│ │ │ ├── ProgressLine.tsx
│ │ │ ├── SuggestedActions.tsx
│ │ │ ├── TaskStatusIcon.tsx
│ │ │ ├── ThinkingIndicator.tsx
│ │ │ ├── VideoStreamDisplay.tsx
│ │ │ └── WelcomeMessage.tsx
│ │ ├── debug/ # Debug panel (dev only)
│ │ │ └── DebugPanel.tsx
│ │ ├── dev/ # Dev testing components
│ │ │ └── DomTestPanel.tsx
│ │ ├── input/ # Input components
│ │ │ ├── MessageInput.tsx
│ │ │ └── ModeSelector.tsx
│ │ ├── layout/ # Layout components
│ │ │ └── WidgetButton.tsx
│ │ ├── ui/ # UI utility components
│ │ │ ├── DiagnosticModal.tsx
│ │ │ ├── ErrorDisplay.tsx
│ │ │ ├── ScreenAccessModal.tsx
│ │ │ └── WidgetSettingsLoader.tsx
│ │ ├── BrowserTools.tsx
│ │ └── MarketrixWidget.tsx
│ ├── context/ # React context
│ │ └── WidgetContext.tsx
│ ├── hooks/ # Custom React hooks
│ │ ├── usePageLifecycle.ts
│ │ ├── useResize.ts
│ │ ├── useTaskState.ts
│ │ └── useWidget.ts
│ ├── services/ # Core services
│ │ ├── ApiService.ts
│ │ ├── ChatService.ts
│ │ ├── ConfigManager.ts
│ │ ├── DevTestService.ts
│ │ ├── DomService.ts
│ │ ├── IntegrationService.ts
│ │ ├── ScreenShareService.ts
│ │ ├── SessionManager.ts
│ │ ├── SessionRecorder.ts
│ │ ├── ShowModeService.ts
│ │ ├── StorageService.ts
│ │ ├── ToolService.ts
│ │ ├── ValidationService.ts
│ │ └── WebSocketClient.ts
│ ├── sdk/ # API SDK (oRPC client + contract)
│ │ ├── index.ts # Client setup and exports
│ │ ├── routes.ts # oRPC contract/route definitions
│ │ └── schema.ts # Zod schemas for API types
│ ├── types/ # TypeScript types
│ │ ├── assets.d.ts
│ │ ├── browserTools.ts
│ │ ├── global.d.ts
│ │ ├── index.ts
│ │ └── toolMessages.ts
│ ├── utils/ # Utility functions
│ │ ├── apiUtils.ts
│ │ ├── bootstrap.tsx
│ │ ├── chat.ts
│ │ ├── cleanupUtils.ts
│ │ ├── common.ts
│ │ ├── devTools.ts
│ │ ├── dom.ts
│ │ ├── format.ts
│ │ ├── persistence.ts
│ │ ├── stateUtils.ts
│ │ ├── validation.ts
│ │ └── widgetPositioning.ts
│ ├── lib/ # Shared utility library
│ │ └── utils.ts # Class name helper (cn)
│ ├── constants/ # Configuration constants
│ │ ├── config.ts # App configuration (URLs, defaults)
│ │ └── theme.ts # Dark theme classes and color tokens
│ ├── assets/ # Static assets (icons, logos)
│ ├── debug.tsx # Debug panel entry point
│ ├── index.css # Global styles
│ └── index.tsx # Main entry point
├── chrome-extension/ # Chrome extension for persistent injection
├── scripts/ # Build & release scripts
│ └── release.sh
├── vite.config.ts # Vite configuration (dev + production)
├── vite.config.debug.ts # Debug panel build configuration
├── tailwind.config.js # Tailwind configuration
├── tsconfig.json # TypeScript configuration
├── tsconfig.build.json # TypeScript config for declaration generation
└── package.json
Initializes the widget with the provided configuration. Validates credentials, fetches settings from the API, and mounts the widget to the DOM. Optionally accepts a container element to mount within. Safe to call multiple times — concurrent and duplicate calls are deduplicated.
Destroys the widget and removes it from the DOM. Also stops session recording and cleans up all resources including the WebSocket connection.
Auto-detects mode (preview, production, or dev) and initializes the widget.
Returns the current widget configuration, or null if not initialized.
Updates the widget configuration at runtime. Unmounts the current widget and reinitializes with the merged config.
Starts RRWeb session recording. Safe to call while a previous start is
in-flight. Throws if the widget was not initialized with mtxApiHost and
mtxApp.
Stops RRWeb session recording without unmounting the widget. Recording can be
resumed later with startRecording().
Returns whether RRWeb session recording is currently active.
React component for preview mode rendering. Accepts settings, container,
mtxId, mtxKey, mtxApiHost, and mtxAiHost props.
The module also provides a default export object bundling all functions:
import widget from '@marketrix.ai/widget';
widget.initWidget(config);
widget.unmountWidget();
widget.mountWidget(config);
widget.getCurrentConfig();
widget.updateMarketrixConfig(newConfig);
widget.startRecording();
widget.stopRecording();
widget.getRecordingState();
// widget.MarketrixWidget — React component// Core configuration
interface MarketrixConfig {
// Production mode credentials
mtxId?: string;
mtxKey?: string;
// Dev mode credentials
mtxApp?: number;
mtxAgent?: number;
// API configuration
mtxApiHost?: string;
mtxAiHost?: string;
// Optional user ID
userId?: number;
// Widget position overrides
widget_position_offset?: { x?: number; y?: number };
widget_position_z_index?: number;
// Preview mode flag
isPreviewMode?: boolean;
// All WidgetSettingsData fields (optional)
// ...
}
// Chat message
interface ChatMessage {
id: string;
content: string;
sender: 'user' | 'agent';
timestamp: Date;
mode?: InstructionType;
videoStream?: MediaStream;
isScreenAccessRequest?: boolean;
screenShareStatus?: 'allowed' | 'denied';
isSystemMessage?: boolean;
isPlaceholder?: boolean;
placeholderState?: 'thinking' | 'waiting-for-user';
parts?: MessagePart[];
taskStatus?: 'ongoing' | 'done' | 'failed' | 'stopped';
}
// Message part (text or progress indicator)
interface MessagePart {
type: 'text' | 'progress';
content: string;
status?: 'running' | 'completed' | 'failed' | 'canceled';
toolName?: string;
hideIcon?: boolean;
textStyle?: 'default' | 'muted';
}
// Widget state
interface WidgetState {
isOpen: boolean;
isMinimized: boolean;
isLoading: boolean;
messages: ChatMessage[];
currentMode: InstructionType;
agentAvailable: boolean;
error?: string;
activeTaskId: string | null;
isTaskRunning: boolean;
taskProgress: TaskProgress[];
}
// Task progress tracking
interface TaskProgress {
tool_name: string;
tool_params: Record<string, unknown>;
step: number;
explanation: string;
mode: string;
timestamp: number;
}
// Instruction types
type InstructionType = 'tell' | 'show' | 'do';GitHub Actions workflows in .github/workflows/. All build and deploy jobs
are delegated to base.yml as a reusable workflow:
| Workflow | Trigger | Action |
|---|---|---|
base.yml |
Called by others | Reusable workflow: build (sanity) or deploy (full) |
dev-build.yml |
Push to dev |
Sanity check via base.yml (npm ci + build, no upload) |
prod-build.yml |
Release created | Sanity check via base.yml (npm ci + build, no upload) |
deploy.yml |
Manual dispatch | Build + upload to Azure Blob Storage + purge CDN cache |
Deploy options:
- Environment:
devorprod - Version (required for prod): Git tag to checkout and build from (e.g.
v1.2.0).
Dev builds are uploaded to widget/dev/ and prod builds to widget/latest/ on Azure CDN.
The widget uses Vite with:
- CSS injection plugin for single-file bundles
- Shadow DOM isolation for CSS
- ESM format for both library and standalone builds
- TypeScript declaration generation (
tsconfig.build.json) - Source maps for debugging
- Terser minification with console/debugger stripping in production
- Hot-reload dev server that rebuilds the production bundle on file changes
Output files:
dist/index.mjs- Library build (React as peer dependency)dist/standalone.mjs- Standalone build (all dependencies bundled)dist/debug.js- Debug panel bundle (IIFE format, unminified)
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
react/react-domv19 (peer dependency)@rrweb/record- Session recording@orpc/client/@orpc/contractv1 - Type-safe API client (oRPC)react-icons- Iconszod- Schema validation
- Vite 6
- Tailwind CSS v4 (via
@tailwindcss/viteplugin) - TypeScript 5
- ESLint + Prettier
- Lefthook for git hooks
- Terser for production minification
MIT License - see LICENSE file for details.
For support and questions, please contact the Marketrix team or create an issue in the repository.