Skip to content

Flow UI is an open-source Flutter UI library to build production-grade Chat & AI assistant interfaces — a plain Flutter package, no codegen, and nothing in its dependency tree that Flutter’s own team doesn’t publish. Its components draw the conversation state you hand them and report what the user did through callbacks; everything model-shaped stays in your app.

One line in your pubspec:

pubspec.yaml
dependencies:
flow_ui: ^0.3.0

That brings in the Flutter SDK, material_ui, file_selector — the flutter.dev plugin behind the composer’s attach button — and google_fonts, which fetches Google Sans and Google Sans Code at runtime. Nothing else.

The design tokens — colors and typography — install as a ThemeExtension:

main.dart
MaterialApp(
theme: ThemeData(extensions: [FlowTheme.light()]),
darkTheme: ThemeData(
brightness: Brightness.dark,
extensions: [FlowTheme.dark()],
),
)

Google Sans — the face the design system is set in — is fetched through google_fonts on first use, so there is nothing to add to your pubspec.yaml fonts section. The fetch needs network access: android.permission.INTERNET in the main Android manifest (Flutter grants it only to debug and profile) and the com.apple.security.network.client entitlement in a sandboxed macOS app. To render offline on first launch, ship the files under google_fonts/.

Messages are plain data; FlowThread draws them:

A three-role conversation
FlowThread(
messages: [
FlowMessageData.text(
id: '1',
role: FlowMessageRole.user,
text: 'What is flow_ui?',
),
FlowMessageData.text(
id: '2',
role: FlowMessageRole.assistant,
text: 'An open-source Flutter UI library to build production-grade Chat & AI assistant interfaces...',
),
FlowMessageData.text(
id: '3',
role: FlowMessageRole.system,
text: 'Model changed to Sonnet',
),
],
)

Streaming is data, not streams: as chunks arrive, rebuild with the updated message list and a status of FlowMessageStatus.streaming — the thread animates the reveal.

Every component has a live stage in the hosted playground — variant pills and code snippets included. It is also in the repo to run locally:

Terminal window
cd playground && flutter run -d chrome

For a minimal starting point, the repo’s example/ is the full chat screen from the README as a single-file app: generate platform runners once with flutter create . --platforms=web, then flutter run -d chrome.