Streaming Generative UI

The Streaming Generative UI Engine for Flutter

Render widgets progressively as LLM streams flow in character-by-character without waiting for a complete JSON response.

pub.dev License: MIT

streaming_gen_ui in action

Widget Catalog ยท AI Chat Demo

NOTE:

This package only renders text streams from LLMs into Flutter widgets/text. It does not manage conversations, pipelines, or tooling.

Just Stream<String> in โ†’ Widget out.

Why streaming_gen_ui?

Features

Generative UI

No more walls of text. Mix in some visuals.

Walls of text vs mixed with Widgets

Elevate standard text-based conversational interfaces. Instead of presenting a long wall of static text, seamlessly mix in rich, interactive components (like profile cards, charts, accordion carousels, or metric tiles) that bring your application to life.

Streaming Support

No waiting for full schema to generate. We've got incremental parsers, just render immediately!

Streaming in action

Most generative UI packages require you to wait for the complete JSON payload before decoding and popping the final widget tree onto the screen. streaming_gen_ui progressively parses and renders widgets character-by-character as the tokens arrive. Buttons start disabled and transition to active instantly with organic spring animations once their handlers load.

Render Anywhere

Rendering in a different view

Direct the LLM to render specific layouts or controls in custom areas of your screen (e.g., a dedicated full-screen Canvas or tool panel) rather than the standard sequential chat thread. Simply define a mapping of custom view IDs and watch them update reactively.

Easy Display

Both the LLM's markdown and generated widgets can render in order easily, progressively displayed.

streaming_gen_ui in action

Seamlessly blend markdown responses and interfaces. The streaming engine parses <interface> tags out of the stream automatically, keeping the response clean and displaying markdown blocks alongside active widgets in chronological order.

Simple & Flexible APIs

Easy developer experience designed for minimal friction with maximum flexibility.

Simple how? Four steps:

  1. Initialize your StreamingGenerativeUi class and include registries
  2. Include generated prompt to LLM via systemPrompt
  3. Feed LLM response to your class via .stream(stream, viewId: 'id').
  4. Display the view via .view(id) from your class.

Flexible how?

  1. It's just Stream<String> --> Text + Widgets.
  2. Place views anywhere, instruct LLM to render somewhere.
  3. Easy custom streaming widget creation.
  4. You handle your conversations, persistence, and everything else. This handles the rendering.

Platform/Framework Agnostic

No vendor lock-in. Whether you are using Gemini, Claude, OpenRouter, or local models via Ollama/llama.cpp, the engine works entirely on standard inputs. Simply feed a Stream<String> of raw tokens in, and get streaming Flutter Widget outputs out.

Use whichever framework, state management, or orchestrator you like.

Batteries Included

A good starting set of widgets are included, covering layouts, displays, cards, and dashboards for different design themes.

Widget Catalog Demo

Pre-Built Themes

Comes packed with built-in and themed widget registries: Themes Demo

Core registries:

Registry Description
Registries.primitives 10 core primitive building blocks โ€” low token footprint, high flexibility
Registries.extended Stateful extended interaction widgets: progression bars, circles, steppers

Aesthetic theme registries - each includes a full set of themed UI cards (card, user profile, carousel, weather, graph, web result, product result, location, list results, todo list, note, comparison):

Registry Aesthetic
Registries.material Material 3
Registries.fluent Windows 11 Fluent
Registries.apple Apple iOS/macOS Squircle
Registries.glassmorphic Frost-blurred Glassmorphism
Registries.neumorphic Soft tactile shadow Neumorphism
Registries.skeumorphic Realistic texture Skeuomorphism
Registries.brutalist Flat high-contrast Pop-Art Brutalist

Composition helpers:

Registries.all                          // Everything
Registries.forThemes({'material', 'fluent'}, includePrimitives: true)

Easy Composition

Define individual custom widgets inline using WidgetRegistry.fromDefinition or bundle them into custom registries. The package automatically computes the LLM's system prompt instructions (systemPrompt) and even auto-generates compliant mock JSON examples if they are omitted, leaving you with zero boilerplate to maintain!

Quick Setup

import 'package:streaming_gen_ui/streaming_gen_ui.dart';

// 1. Create instance, use registries (or custom widgets)
final streamingGenUi = StreamingGenerativeUi(
  registries: [Registries.material],
);

// 2. Include generated prompt in instructions
final responseStream = Llm.sendMessageStream(
  message: 'Most durable laptops on the market?',
  systemPrompt:
      'You are a helpful assistant.\n${streamingGenUi.systemPrompt}',
);

// 3. Stream response to target view
streamingGenUi.stream(responseStream, viewId: 'msg-box-1');

// 4. Render response + widgets in view
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      const Text('AI Assistant'),
      streamingGenUi.view('msg-box-1'),
    ],
  );
}

Contributing

Contributions are welcome (even new widgets on the catalog).


License

MIT โ€” see LICENSE for details.

Libraries

streaming_gen_ui