widget_chat 0.0.19 copy "widget_chat: ^0.0.19" to clipboard
widget_chat: ^0.0.19 copied to clipboard

Drop-in AI chatbot widget for Flutter, FlutterFlow & web — rich content, tools, multimodal, multi-language, dashboard-configured.

Widget Chat - AI Chatbot Widget #

pub package pub points platform

A beautiful, customizable AI chatbot widget you can drop into any Flutter, FlutterFlow, React, or web app — rich content, tools, multimodal input, and multi-language, all configured from a no-code dashboard at widget-chat.com.

[Widget-Chat AI chat widget open on a website]

💬 Try the live widget at widget-chat.com (bottom-right) — it runs this exact package.

Features #

  • 🎨 Beautiful UI: Modern, customizable design with smooth animations
  • 🚀 Easy Integration: Single widget integration with minimal setup
  • 🔒 Secure: Project-based authentication with secure keys
  • 📱 Responsive: Adaptive design for mobile and web platforms
  • Real-time: Live chat with typing indicators
  • 🎭 Customizable: Themes, colors, FAB styles, and behavior
  • 🌐 Multi-platform: Works on iOS, Android, and Web

Installation #

Add to your pubspec.yaml:

dependencies:
  widget_chat: ^0.0.10

Quick Start #

1. Import the package #

import 'package:widget_chat/widget_chat.dart';

2. Add the ChatWidget to your app #

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          // Your app content here
          YourMainContent(),
          
          // Add the chatbot
          Positioned(
            bottom: 20,
            right: 20,
            child: ChatWidget(
              configuration: BotConfiguration(
                projectSecretKey: 'your-project-secret-key',
                userID: 'unique-user-id',
                name: 'Support Bot',
                welcomeMessage: 'Hello! How can I help you today?',
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Configuration Options #

Basic Configuration #

BotConfiguration(
  // Required
  projectSecretKey: 'your-secret-key',  // Get from your dashboard
  userID: 'user-123',                   // Unique identifier for the user
  
  // Optional
  name: 'Assistant',                    // Bot display name
  welcomeMessage: 'How can I help?',    // Initial greeting
  fontFamily: 'Roboto',                 // Chat font (default: Roboto)
  color: '#3B82F6',                     // Primary color in hex
  systemInstructions: 'Be helpful',     // Bot behavior instructions
  isPreviewMode: false,                 // Preview mode flag
)

FAB Customization #

BotConfiguration(
  projectSecretKey: 'your-key',
  userID: 'user-123',
  fabConfiguration: FabConfiguration(
    icon: 'chat_bubble',           // Icon name
    iconSize: 24.0,                // Icon size
    iconColor: '#FFFFFF',          // Icon color in hex
    backgroundColor: '#3B82F6',     // Background color in hex
    buttonSize: 56.0,              // FAB size
    borderRadius: 28.0,            // Corner radius
    useAvatarAsIcon: false,        // Use avatar image as icon
  ),
)

Advanced Usage #

Responsive Design #

// Mobile (default) - full-screen chat experience
ChatWidget(
  configuration: BotConfiguration(
    projectSecretKey: 'your-key',
    userID: 'user-123',
  ),
)

// Web/Desktop - fixed 400x700 chat window
ChatWidget(
  configuration: BotConfiguration(
    projectSecretKey: 'your-key',
    userID: 'user-123',
  ),
  mobile: false,
)

Custom FAB Widget #

ChatWidget(
  configuration: BotConfiguration(
    projectSecretKey: 'your-key',
    userID: 'user-123',
  ),
  fabWidget: CustomFABWidget(),  // Your custom FAB
)

Chat State Callbacks #

ChatWidget(
  configuration: BotConfiguration(
    projectSecretKey: 'your-key',
    userID: 'user-123',
  ),
  onOpen: ({required bool isOpen}) {
    print('Chat is ${isOpen ? "open" : "closed"}');
    // Track analytics, update UI, etc.
  },
)

Host App Integration #

The bot can drive your app — and your app can feed the bot — through four channels. All of them are optional; wire only what your product needs.

Rich-content action callbacks #

Backend tools and the model can emit buttons/cards whose taps land in YOUR code. Declare the callback ids your app handles in the dashboard project's callback registry (so the model can't invent ids you don't dispatch), then:

ChatWidget(
  configuration: BotConfiguration(projectSecretKey: '...', userID: 'user-123'),
  onRichContentCallback: (callbackId, payload) {
    switch (callbackId) {
      case 'open_item':    navigateToItem(payload?['item']);
      case 'open_paywall': showPaywall();
      case 'open_login':   showSignIn();
    }
  },
)

Tip — for navigation, prefer ONE generic id over per-feature ids: declare a single open_screen callback whose payload['screen'] selects the destination, and keep a {screenKey: route} map host-side. New destinations then need no new callback ids — just a new key in the map and in the registry description (which is also what tells the model the allowed keys):

case 'open_screen':
  final route = screenRoutes[payload?['screen']]; // {'studio': StudioPage.route, ...}
  if (route != null) Navigator.of(context).push(route());

Authenticated tool calls (authToken) #

Pass the END USER's JWT and the backend forwards it as a Bearer header to every tool call, so your API attributes actions to the right account:

BotConfiguration(
  userID: user.id.toString(),
  authToken: session.jwt, // re-read on EVERY send — refresh it proactively
)

authToken is re-read per message: rotate it mid-session with updateConfiguration/a rebuild and the next tool call uses the fresh token. Refresh BEFORE expiry (e.g. a 5-minute periodic check) — an expired token makes every gated tool 401 and degrades the conversation.

Guest / anonymous sessions #

userID is any non-empty string — no account required. The recommended pattern for apps with optional sign-in:

  • Guests get a device-persistent id (anon-<random>, stored in prefs) and NO authToken.
  • Tell the bot who it's talking to via userContext ({'authenticated': false}), and gate account-bound tools in your system prompt AND in each tool's description ("SIGNED-IN USERS ONLY … emit the open_login button instead"). A required boolean parameter on gated tools (e.g. user_is_signed_in, "copy user_context.authenticated exactly") makes small models respect the gate far more reliably than prose alone.
  • On login, remount the chat keyed to the real user id — history scopes per userID, so the guest thread stays behind and the account thread loads.
  • Disable attachments for guests (enableFileAttach: false) when your upload endpoint needs auth.

User context (userContext) #

A free-form map injected into the system prompt on every send — entitlement flags, profile ids, supported callback vocabulary. Keep it small (tokenised each turn, 8 KB cap):

userContext: {
  'authenticated': true,
  'pro': user.isPro,
  'supported_callbacks': ['open_item', 'open_paywall'],
}

Host slots #

Backend tools with execution_target: host_render reserve a spot in the bubble that YOUR widget fills — the tool's arguments arrive as the payload:

hostSlotBuilder: (slotId, payload) =>
    slotId == 'item_preview' ? ItemPreview(payload) : null,

Slot builders must be pure functions of the payload — history reloads re-render them from stored JSON.

Image uploads #

Wire imageUploader to your own storage and the chat sends compact URLs instead of inlining base64 into the conversation:

imageUploader: (bytes, mimeType) async => myCdn.upload(bytes, mimeType),

Attached photos are forwarded by the backend to image-bearing tools (analysis, extraction, try-on style flows) — the model never handles raw bytes.

Theming that stays on brand #

Since 0.0.18 the chat pins its accent to your configured brand color in BOTH light and dark mode (filled buttons, send icon, focus rings render the exact color instead of a Material tonal derivative). Per-mode surfaces and bubble colors come from the dashboard (chat_appearance / chat_appearance_dark), with defaultThemeMode and an optional in-chat theme switcher (showThemeToggle). Prefer configuring colors on the dashboard over hard-coding them host-side — config survives app releases.

Platform-Specific Setup #

Mobile (Default) #

The mobile parameter defaults to true, so the chat opens in full-screen mode out of the box - ideal for iOS and Android apps.

Web / Desktop #

For web or desktop applications, set mobile: false to use a fixed-size (400x700) chat window:

ChatWidget(
  configuration: config,
  mobile: false,
)

The embedded iframe version (web_embed) already handles this automatically via URL parameters.

Available Icons #

The FAB supports these icon options:

  • chat_bubble (default)
  • chat
  • message
  • support_agent
  • help
  • question_answer
  • forum
  • contact_support
  • headset_mic

Security Best Practices #

  1. Never expose your project secret key in client-side code
  2. Use unique user IDs to maintain conversation history
  3. Configure allowed origins for web deployments
  4. Keep your SDK updated for security patches

Example App #

Check out the complete example in the /example folder:

import 'package:flutter/material.dart';
import 'package:widget_chat/widget_chat.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Widget Chat Example',
      home: Scaffold(
        body: Stack(
          children: [
            Center(
              child: Text('Your App Content'),
            ),
            Positioned(
              bottom: 20,
              right: 20,
              child: ChatWidget(
                configuration: BotConfiguration(
                  projectSecretKey: 'your-project-secret-key',
                  userID: 'demo-user',
                  name: 'AI Assistant',
                  welcomeMessage: 'Hi! How can I help you today?',
                  color: '#6366F1',
                  fabConfiguration: FabConfiguration(
                    icon: 'support_agent',
                    backgroundColor: '#6366F1',
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Troubleshooting #

Chat doesn't open #

  • Verify your project secret key is correct
  • Check console for any error messages
  • Ensure the widget is properly positioned in your widget tree

Styling issues #

  • Make sure hex colors include the # symbol
  • Use supported Google Fonts for fontFamily
  • Check that size values are reasonable (e.g., buttonSize: 56.0)

Support #

License #

This project is licensed under the Proprietary License - see the LICENSE file for details.