chatbotify

pub package License: MIT

A plug-and-play AI chatbot for Flutter. Initialize once, drop in AiChatScreen(), done. Supports Google Gemini and OpenAI, with streaming responses, Markdown rendering, theming, and pluggable storage.

Features

  • πŸ”Œ Plug-and-play β€” one initialize() call, then AiChatScreen()
  • πŸ€– Multi-provider β€” Gemini and OpenAI today, extensible for more
  • ⚑ Streaming responses β€” tokens render as they arrive
  • πŸ“ Markdown rendering for assistant replies (code blocks, lists, etc.)
  • 🎨 Fully themeable β€” bubble colors, fonts, border radius, send button
  • πŸŒ“ Light & dark mode aware by default
  • πŸ’Ύ Pluggable storage β€” ships with in-memory, bring your own Hive / SharedPreferences / Firebase backend via the ChatStorage interface
  • πŸ” Retry, clear chat, typing indicator, scroll-to-bottom
  • 🧯 Structured error handling β€” invalid key, rate limit, no internet, timeout, provider unavailable β€” each with a reusable error widget
  • 🧱 Built on Riverpod, following SOLID architecture

Installation

dependencies:
  chatbotify: ^0.1.0
  flutter_riverpod: ^2.5.1

Then:

flutter pub get

Quick start

Wrap your app in a ProviderScope and initialize the package before runApp:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:chatbotify/chatbotify.dart';

void main() {
  AiChatbot.initialize(
    provider: AIProvider.gemini,
    apiKey: 'YOUR_API_KEY',
    systemPrompt: 'You are a helpful assistant.',
  );

  runApp(const ProviderScope(child: MyApp()));
}

Then drop the ready-made screen in anywhere:

Navigator.push(
  context,
  MaterialPageRoute(builder: (_) => const AiChatScreen()),
);

That's it β€” chat bubbles, streaming, Markdown, typing indicator, and error handling all work out of the box.

⚠️ Never ship a real API key inside a compiled client app. Use --dart-define=AI_API_KEY=... for demos, or proxy requests through your own backend for production.

Switching providers

AiChatbot.initialize(
  provider: AIProvider.openai,   // was AIProvider.gemini
  apiKey: 'YOUR_OPENAI_KEY',
  model: 'gpt-4o-mini',          // optional, has a sane default per provider
);

Nothing else in your app changes β€” the UI and controller talk to AIProviderInterface, not to a specific vendor.

Theming

AiChatScreen(
  theme: ChatTheme(
    userBubbleColor: Colors.deepPurple,
    assistantBubbleColor: Colors.grey.shade200,
    borderRadius: 24,
    sendButtonColor: Colors.deepPurple,
  ),
)

Any field you omit falls back to a value derived from your app's ThemeData and current Brightness, so ChatTheme() alone already looks good in both light and dark mode.

Custom storage

Chat history defaults to in-memory (lost on restart). Implement ChatStorage to persist it:

class HiveChatStorage implements ChatStorage {
  @override
  Future<List<ChatMessage>> loadMessages(String sessionId) async { ... }

  @override
  Future<void> saveMessages(String sessionId, List<ChatMessage> messages) async { ... }

  @override
  Future<void> clear(String sessionId) async { ... }
}

AiChatbot.initialize(
  provider: AIProvider.gemini,
  apiKey: 'YOUR_API_KEY',
  storage: HiveChatStorage(),
);

Error handling

All failures surface as ChatbotException with a ChatbotErrorCode (invalidApiKey, rateLimited, noInternet, timeout, providerUnavailable, notInitialized, unknown). AiChatScreen renders these via the built-in ChatErrorWidget; use it standalone if you build a custom UI on top of ChatController.

Advanced: building your own UI

Everything above AIProviderInterface is optional. If you want custom UI, use the same controller the built-in screen uses:

final state = ref.watch(chatControllerProvider);
final controller = ref.read(chatControllerProvider.notifier);

controller.sendMessage('Hello!');
controller.retryLastMessage();
controller.clearChat();

Architecture

lib/
  chatbotify.dart              # public barrel export
  src/
    core/                      # enums, exceptions, constants (no Flutter deps)
    models/                    # ChatMessage, ChatTheme, ChatbotConfig
    providers/                 # AIProviderInterface + Gemini/OpenAI + factory
    services/                  # ChatStorage abstraction, HTTP client
    controllers/                # ChatController (Riverpod StateNotifier), ChatState
    ui/                        # AiChatScreen
    widgets/                   # ChatBubble, TypingIndicator, MessageInput, ...

Each layer depends only on the one below it (Dependency Inversion), and the provider layer is a Strategy pattern β€” adding a new AI backend means one new class implementing AIProviderInterface, registered in ProviderFactory.

Example app

See example/ for a runnable app. From the package root:

cd example
flutter run --dart-define=AI_API_KEY=your_key_here

Contributing

Issues and PRs welcome. Run flutter test before submitting.

License

MIT β€” see LICENSE.

Libraries

chatbotify
Plug-and-play AI chatbot UI + logic for Flutter apps.