Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bdc4707
Add an example that generates UI with local LLM
gspencergoog May 22, 2026
3f526f9
Fix copyrights
gspencergoog May 22, 2026
df0fcab
Add docs
gspencergoog May 22, 2026
b650451
Switch to <a2ui> sentinels
gspencergoog May 22, 2026
af69223
feat(express): support data model population and sentinel tags
gspencergoog May 22, 2026
941455a
feat(genui_express): initialize genui_express plugin package with com…
gspencergoog May 23, 2026
337ef2f
refactor(express_chat): migrate express_chat example to use the new g…
gspencergoog May 23, 2026
dd95445
feat(genui_express): make local HTTP completions model dynamically co…
gspencergoog May 23, 2026
552d23d
feat(genui_express): implement iOS and macOS Swift integration for Ap…
gspencergoog May 23, 2026
c8e3b66
refactor(macos): bypass legacy macOS deployment target overrides and …
gspencergoog May 23, 2026
5cf7e75
refactor(express_chat): set default local model back to http-completi…
gspencergoog May 23, 2026
7f2a3ab
refactor(express_chat): restore default local model back to apple-fou…
gspencergoog May 23, 2026
397badb
refactor(express_chat): default to local http-completions model for l…
gspencergoog May 23, 2026
5f955e6
feat(genui_express): add genkit_chrome integration with compile-safe …
gspencergoog May 23, 2026
54f34c4
feat(genui_express): register genkit_chrome via constructors and rest…
gspencergoog May 23, 2026
3e3f224
fix(express_chat): address PR code review feedback for express_chat a…
gspencergoog May 26, 2026
2217515
Fix copyright
gspencergoog May 26, 2026
ee5c186
docs(genui_express): replace README with clear usage guide and code e…
gspencergoog May 26, 2026
afe8423
refactor(express): resolve analyzer warnings and strongly type dynami…
gspencergoog May 26, 2026
b1578fe
refactor(express): encapsulate compiler internals and add type-safe m…
gspencergoog May 26, 2026
2c27ca4
fix(ci): exclude web-only files from native coverage test compilation
gspencergoog May 26, 2026
121da21
test(express_chat): enable test coverage validation for express_chat …
gspencergoog May 26, 2026
776baf1
test(simple_chat): enable test coverage validation for simple_chat ex…
gspencergoog May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions coverage_baseline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
# Monorepo Coverage High-Water Marks (Auto-generated by test_and_fix --update-baseline)
dev_tools/catalog_gallery: 52.91
dev_tools/composer: 20.49
examples/express_chat: 35.76
examples/simple_chat: 37.33
packages/a2ui_core: 76.30
packages/genai_primitives: 100.00
packages/genui: 79.71
packages/genui: 79.72
packages/genui_a2a: 91.37
packages/json_schema_builder: 79.09
tool/e2e: 100.00
tool/fix_copyright: 89.83
tool/release: 78.01
tool/test_and_fix: 94.37
packages/genui_express: 63.34
packages/json_schema_builder: 79.27
7 changes: 6 additions & 1 deletion coverage_policy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ exclude:
- "**/*.freezed.dart"
- "**/*.mocks.dart"
- "**/generated/**"
- "**/*_web.dart"

# Package-specific overrides (paths relative to monorepo root).
packages:
packages/genui:
threshold: 75.0
packages/genui_express:
threshold: 60.0
packages/a2ui_core:
threshold: 75.0
packages/json_schema_builder:
Expand All @@ -36,6 +39,8 @@ packages:
tool/release:
threshold: 75.0
examples/simple_chat:
enabled: false
threshold: 30.0
examples/express_chat:
threshold: 30.0
examples/verdure/client:
enabled: false
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
)

set(PLUGIN_BUNDLED_LIBRARIES)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ import video_player_avfoundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
VideoPlayerPlugin.register(with: registry.registrar(forPlugin: "VideoPlayerPlugin"))
}
1 change: 1 addition & 0 deletions dev_tools/composer/linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
)

set(PLUGIN_BUNDLED_LIBRARIES)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
VideoPlayerPlugin.register(with: registry.registrar(forPlugin: "VideoPlayerPlugin"))
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
}
1 change: 1 addition & 0 deletions dev_tools/composer/windows/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
)

set(PLUGIN_BUNDLED_LIBRARIES)
Expand Down
30 changes: 30 additions & 0 deletions examples/express_chat/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
channel: "stable"

project_type: app

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
- platform: linux
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
43 changes: 43 additions & 0 deletions examples/express_chat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Simple Chat Example

This application is a minimal example of how to use the `genui` package to create a simple, conversational chat application.

## Purpose

The main goal of this example is to demonstrate the fundamental concepts of `genui` in a straightforward chat context. It shows how to:
1. Initialize and use the `SurfaceController`, the core engine for the package.
2. Provide a simple system prompt to guide the AI's behavior.
3. Send user messages to the AI and receive responses.
4. Handle the creation of new UI "surfaces" generated by the AI.
5. Render these dynamic UI surfaces within a standard chat message list.
6. Manage a conversation history that interleaves user text messages with AI-generated UI responses.

Unlike more complex examples, this app does not define a custom widget catalog. Instead, it relies on the default `coreCatalog` provided by `genui`, meaning the AI can only respond with basic widgets like `Text`, `Column`, `ElevatedButton`, etc.

## How it Works

The application's logic is contained almost entirely within `lib/chat_session.dart`.

1. **Initialization**: A `SurfaceController` is created to manage the state of UI surfaces.
2. **User Input**: The user types a message into a `TextField` and hits send.
3. **Sending the Message**:
- The user's text is immediately added to the local message list.
- The request is sent to the `AiClient`.
4. **AI Response**:
- The `AiClient` streams `A2uiMessage`s back.
- These messages are piped into the `SurfaceController`.
5. **UI Rendering**:
- The UI listens to `SurfaceController.surfaceUpdates` or `A2uiTransportAdapter` streams.
- When a surface is added, a `Surface` widget is rendered, dynamically building the UI based on the `UiDefinition` managed by `SurfaceController`.

## Getting Started

Follow the instructions in [Running the app with a Gemini key](../../docs/usage/run_app_with_gemini_key.md).

## Video

https://github.com/user-attachments/assets/469fb2cf-09cf-463c-8c9c-b9c0cb39203b

This video is recorded on May 11, 2026, for [PR#905](https://github.com/flutter/genui/pull/905).

Please update the link if you have a fresher version of the demo.
14 changes: 14 additions & 0 deletions examples/express_chat/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/

# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks
47 changes: 47 additions & 0 deletions examples/express_chat/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
// START: FlutterFire Configuration
id("com.google.gms.google-services")
// END: FlutterFire Configuration
}

android {
namespace = "com.example.simple_chat"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.simple_chat"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}

flutter {
source = "../.."
}
11 changes: 11 additions & 0 deletions examples/express_chat/android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Copyright 2025 The Flutter Authors.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
49 changes: 49 additions & 0 deletions examples/express_chat/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!-- Copyright 2025 The Flutter Authors.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="simple_chat"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.

In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2025 The Flutter Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package com.example.simple_chat

import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2025 The Flutter Authors.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->

<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />

<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2025 The Flutter Authors.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->

<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />

<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2025 The Flutter Authors.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->

<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.

This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
22 changes: 22 additions & 0 deletions examples/express_chat/android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2025 The Flutter Authors.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->

<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.

This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
11 changes: 11 additions & 0 deletions examples/express_chat/android/app/src/profile/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Copyright 2025 The Flutter Authors.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Loading
Loading