FluidUI - Zero UI Agent App

한국어 (README_KR.md) | English (README.md)

AI-driven dynamic surface assembly for Flutter.
Describe what you need in natural language, and the agent builds the UI for you.

Overview

FluidUI is a Flutter application that implements the GenUI (Generative UI) pattern with an A2UI (Agent-to-UI) protocol. Instead of pre-built screens, the app dynamically assembles native Flutter widgets based on user intent, creating a "Zero UI" experience where the interface materializes on demand.

Key Features

  • Natural Language to Native UI - Describe the screen you want, get real Flutter widgets
  • Widget Catalog - 8 pre-built widget types (ReservationCard, DatePicker, ActionSlider, etc.)
  • High-Bandwidth Feedback Loop - Widget state changes are fed back to the agent in real-time
  • Secure Architecture - All AI calls routed through a backend proxy; no API keys on the client
  • Dark Mode - Full light/dark theme support via system preference
  • Mock Mode - Works offline without a backend for demos and development

Architecture

User Intent (Natural Language)
        |
        v
+------------------+       +------------------+       +------------------+
| ChatSurfaceScreen| ----> | SurfaceController| ----> |   AgentService   |
|   (Flutter UI)   |       |  (State Manager) |       | (HTTP to Proxy)  |
+------------------+       +------------------+       +------------------+
        ^                          |                          |
        |                          v                          v
+------------------+       +------------------+       +------------------+
| SurfaceRenderer  |       |    SurfaceSpec    |       | Backend Proxy    |
| + WidgetCatalog  | <---- |  (JSON UI Spec)  | <---- | (Node.js/Express)|
+------------------+       +------------------+       +------------------+
                                                              |
                                                              v
                                                      +------------------+
                                                      |   Claude API     |
                                                      +------------------+

Feedback Loop

User interacts with widget
  -> onWidgetStateChanged(widgetId, newState)
    -> Local state updated immediately (optimistic)
    -> State sent to agent via backend proxy
      -> Agent returns updated SurfaceSpec (or no-op)
        -> UI re-rendered with new spec

Project Structure

lib/
  main.dart                           # App entry point, mode selection
  core/
    app_theme.dart                    # Light/Dark theme definitions
    data_model.dart                   # Widget state model
    surface_spec.dart                 # UI specification (layout + widgets)
    surface_controller.dart           # State management & feedback loop
  catalog/
    widget_catalog.dart               # Widget type registry
    widgets/
      reservation_card.dart           # Reservation details card
      date_picker_widget.dart         # Date selection (native DatePicker)
      action_slider_widget.dart       # Numeric slider input
      info_display.dart               # Read-only info card
      option_selector.dart            # Single/multi select chips
      text_input_widget.dart          # Text input with debounce
      confirm_button.dart             # Action/confirm button
      image_card.dart                 # Image display with loading state
  a2ui/
    a2ui_transport_adapter.dart       # JSON -> SurfaceSpec parser
    system_prompt.dart                # LLM system prompt with catalog schema
  agent/
    agent_service.dart                # Backend proxy HTTP client
    mock_agent_service.dart           # Offline mock agent
  screens/
    chat_surface_screen.dart          # Main chat + surface UI
    surface_renderer.dart             # Dynamic widget tree renderer
backend/
  server.js                           # Express proxy server
  package.json                        # Node.js dependencies
  .env.example                        # Environment variable template

Quick Start

Mock Mode (No backend required)

flutter pub get
flutter run

Try these prompts:

  • "Restaurant reservation" / "Reservation"
  • "Customer survey" / "Survey"
  • "App settings" / "Settings"

Live Mode (With AI backend)

1. Start the backend proxy:

cd backend
cp .env.example .env
# Edit .env and set your ANTHROPIC_API_KEY
npm install
npm start

2. Run the Flutter app:

flutter run --dart-define=PROXY_URL=http://localhost:8080

Backend Configuration

VariableDefaultDescription
ANTHROPIC_API_KEY(required)Your Anthropic API key
PORT8080Server port
MODELclaude-sonnet-4-6Claude model to use
ALLOWED_ORIGINS*Comma-separated CORS origins

The backend includes:

  • Request validation
  • In-memory rate limiting (30 req/min per IP)
  • Request logging
  • 30-second timeout for API calls

Widget Catalog

TypeDescriptionInteractive
ReservationCardReservation details with guest count controlsYes
DatePickerNative date picker dialogYes
ActionSliderNumeric slider with min/max/unitYes
InfoDisplayRead-only info card with icon and colorNo
OptionSelectorSingle or multi-select chip groupYes
TextInputText field with debounced state updatesYes
ConfirmButtonPrimary/danger/outline action buttonYes
ImageCardNetwork image with loading indicatorNo

How It Works

  1. User types a natural language request (e.g., "Book a restaurant for 4 people")
  2. SurfaceController sends the intent to the agent service
  3. AgentService calls the backend proxy, which forwards to Claude with a system prompt containing the widget catalog schema
  4. Claude returns a JSON UI specification instead of text
  5. A2uiTransportAdapter parses the JSON into a SurfaceSpec
  6. SurfaceRenderer maps each widget spec to a native Flutter widget via the WidgetCatalog
  7. User interacts with the generated widgets; state changes flow back to the agent

Tech Stack

  • Flutter 3.11+ / Dart 3.11+
  • flutter_animate - Widget entrance animations
  • http - Backend communication
  • provider - Dependency injection ready
  • Node.js / Express - Backend API proxy
  • Claude API - LLM for UI generation

License

MIT