# Generating Flutter UI

> Generative UI (GenUI) for Flutter using AI models like Google Gemini, Anthropic Claude, or OpenAI via the genui package. Use this skill when building dynamic AI-driven interfaces, conversational UI flows, server-rendered screen layouts, LLM-powered dashboards, chat-based UI generation, or implementing prompt-to-UI systems. Supports AI-generated widgets, reactive data binding, ContentGenerator integration, and A2uiMessageProcessor for real-time UI updates from AI responses. Ideal for apps where UI structure is determined by AI/LLM output rather than hardcoded layouts.

- Skill: `poorgramer-zack/generating-flutter-ui` (Agent Skill)
- Install (CLI): `npx skillmds@latest add poorgramer-zack/generating-flutter-ui`
- Raw SKILL.md: https://api.skillmd.com/api/skills/poorgramer-zack/generating-flutter-ui/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: Poorgramer-Zack (https://skillmd.com/u/poorgramer-zack)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/poorgramer-zack/generating-flutter-ui

---


# Flutter Generative UI (GenUI) Best Practices

## Goal
Implement a dynamic user interface generated by AI using the [genui](https://pub.dev/packages/genui) package. This is the recommended approach when an application needs to build reactive screens or components directly from AI responses without hardcoding the layout.

## Instructions

The `genui` package orchestrates a conversational loop between the user, the AI (via `ContentGenerator`), and the Flutter UI (via `A2uiMessageProcessor` and `DataModel`).

### 1. Project Setup
Add the necessary packages to your `pubspec.yaml`:
```bash
flutter pub add genui
# For Gemini integration via Firebase:
flutter pub add genui_firebase_ai
```

If targeting macOS/iOS, enable outbound network requests in entitlements:
```xml
<key>com.apple.security.network.client</key>
<true/>
```

### 2. Core Integration Structure

To connect your Flutter application to the AI agent, you need to instantiate three main components:

1.  **`A2uiMessageProcessor`**: Handles the UI side, translating AI messages into UI actions. Supply it with a `Catalog` of widgets the AI is allowed to use.
2.  **`ContentGenerator`**: Handles communication with the AI. Supply it with system instructions and tools.
3.  **`GenUiConversation`**: The facade coordinating the processor and generator.

**Example Setup in a StatefulWidget:**

```dart
import 'package:flutter/material.dart';
import 'package:genui/genui.dart';
import 'package:genui_firebase_ai/genui_firebase_ai.dart';

class GenUIPage extends StatefulWidget {
  const GenUIPage({super.key});

  @override
  State<GenUIPage> createState() => _GenUIPageState();
}

class _GenUIPageState extends State<GenUIPage> {
  late final A2uiMessageProcessor _a2uiMessageProcessor;
  late final GenUiConversation _genUiConversation;

  @override
  void initState() {
    super.initState();

    // 1. Initialize Message Processor with predefined catalog widgets
    _a2uiMessageProcessor = A2uiMessageProcessor(
      catalogs: [CoreCatalogItems.asCatalog()],
    );

    // 2. Initialize Content Generator (e.g., Firebase AI / Gemini)
    final contentGenerator = FirebaseAiContentGenerator(
      catalog: CoreCatalogItems.asCatalog(),
      systemInstruction: '''
        You are an AI assistant. You must generate UI by responding with JSON
        matching the provided widget schemas. Always output valid UI structures.
      ''',
      tools: _a2uiMessageProcessor.getTools(),
    );

    // 3. Orchestrate the Conversation
    _genUiConversation = GenUiConversation(
      a2uiMessageProcessor: _a2uiMessageProcessor,
      contentGenerator: contentGenerator,
      // Implement your handlers for rendering generated surfaces
      onSurfaceAdded: (surfaceId) { /* Handle surface creation */ },
      onSurfaceDeleted: (surfaceId) { /* Handle surface deletion */ },
      onTextResponse: (text) { /* Optional: show text explicitly */ },
      onError: (error) { /* Handle generation errors */ },
    );
  }

  @override
  void dispose() {
    _genUiConversation.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // UI Implementation interacting with _genUiConversation.sendRequest()
    return const Scaffold();
  }
}
```

### 3. Data Model & Data Binding

A core philosophy of `genui` is utilizing a central `DataModel`. Widgets don't manage their own dynamic state; instead, they bind to paths within the `DataModel`.

When creating custom widgets to add to your `Catalog`, ensure they react to the data context:

```dart
// The AI will generate JSON like:
// { "Text": { "text": { "literalString": "Hello" } } }
// OR
// { "Text": { "text": { "path": "/user/welcome_message" } } }
```
*   **literalString**: Static data directly from the AI.
*   **path**: A reference to a location in the `DataModel`. Updates to this path automatically rebuild any widgets bound to it. Input widgets (like `TextField`) should directly update this `DataModel`.

### 4. Customizing the Catalog

To extend GenUI beyond the `CoreCatalogItems`, define your own `CatalogItem`s and provide them to both the `A2uiMessageProcessor` and the `ContentGenerator`. This tells the AI what Custom Widgets are available and what parameters they accept.

## Constraints

*   **Architecture Scope**: Do not use `genui` for static screens or standard layouts. It should be reserved exclusively for features needing generative or highly dynamic, AI-driven UI presentation.
*   **State Management**: Within GenUI components, prefer the unified `DataModel` reactivity over local `setState` for data shared with the AI.
*   **Error Handling**: Always ensure `onError` in `GenUiConversation` is handled appropriately, as AI responses can sometimes fail parsing or violate catalog schemas.

