Genairus logoGenAI-R-Us
Genairus logoGenAI-R-Us

Flux Universal UI Modeling Language (UIML)

Version 1.0

Introduction

Flux is a high-level, declarative UI Modeling Language (UIML) designed as an AI-first modeling language that decouples UI definition from framework-specific implementation. It addresses the fundamental problem of UI fragmentation across web and mobile platforms by providing a single source of truth for interface design.

Flux allows architects to model user interfaces based on Component Composition and Semantic Intent rather than the specific constraints of React, SwiftUI, or Jetpack Compose. By defining the "What" and "Why" of your UI, Flux can be "rendered" into any target framework—generating idiomatic, native-feeling code for each platform.

AI-First Design

Flux is specifically designed to be easily generated by LLM coding agents while remaining perfectly human-readable and writable. The syntax prioritizes:

  • Unambiguous structure that LLMs can reliably produce
  • Clear semantic intent that reduces hallucination and errors
  • Self-documenting patterns that are obvious to both humans and AI
  • Consistent formatting that makes code generation predictable

This makes Flux an ideal target language for AI-assisted development workflows, where LLMs can rapidly scaffold UIs while developers maintain full control and readability.

The Generator Philosophy

Flux follows the principle of universal specification with target-specific implementation—the same philosophy used by Protocol Buffers, Smithy, and Capacitor. The language specification defines the complete UI model without framework constraints. Generators handle the reality of each framework through:

  • Native implementations where the framework supports the pattern natively
  • Composed implementations where multiple primitives combine to achieve the result
  • Compile-time warnings when features require workarounds
  • Compile-time errors when features cannot be implemented

This approach ensures your UI model remains portable and future-proof while giving you full transparency about what happens under the hood.


Language Philosophy

Flux is built on five core principles:

AI-First, Human-Friendly

Flux is designed as an AI-first modeling language - optimized for LLM code generation while maintaining exceptional human readability. The syntax is structured and predictable, making it easy for coding agents to generate correctly while keeping it intuitive for developers to read, write, and maintain. This dual optimization makes Flux ideal for modern development workflows that leverage both human expertise and AI assistance.

Component as Contract

UI components serve as a formal contract between the design system, the application code, and the data layer. They ensure that interface behavior is consistent across all platforms.

Composition Over Inheritance

Flux embraces composition as the primary mechanism for building complex UIs. Components are composed from simpler building blocks, creating a clear hierarchy that translates naturally to any framework.

Platform Independence

By abstracting the UI model, Flux eliminates framework lock-in. A component defined in Flux can render on web, iOS, Android, and desktop without rewriting your interface logic.

Flexible UX

Flux stands for "Flexible UX" - recognizing that UIs need to adapt to different screen sizes, input methods, and platform conventions while maintaining core functionality.


Core Building Blocks

Components

Components are the primary units of Flux. They represent reusable UI elements with props, state, and behavior.

component Button {
  props: {
    label: String,
    variant: "primary" | "secondary" | "danger",
    disabled: Boolean = false,
    onClick: Handler<void>
  }

  styles: {
    padding: 12 24,
    borderRadius: 8,
    fontSize: 16,
    fontWeight: 600
  }

  states: {
    hovered: Boolean = false,
    pressed: Boolean = false
  }
}

Layouts

Layouts define how components arrange their children. Flux provides semantic layout primitives that map to native implementations.

component UserProfile {
  props: {
    user: User,
    onEdit: Handler<void>
  }

  layout: VStack {
    spacing: 16,
    padding: 20,
    alignment: "center"

    children: [
      Image {
        src: props.user.avatarUrl,
        width: 80,
        height: 80,
        style: "rounded-full"
      },
      Text {
        text: props.user.name,
        style: "headline"
      },
      Text {
        text: props.user.email,
        style: "caption",
        color: "muted"
      },
      Button {
        label: "Edit Profile",
        variant: "primary",
        onClick: props.onEdit
      }
    ]
  }
}

Shapes (Data Structures)

Shapes define the structure of data passed between components. They ensure type safety across all generated implementations.

shape User {
  id: String,
  name: String,
  email: String,
  avatarUrl: String,
  role: UserRole
}

enum UserRole {
  ADMIN,
  USER,
  GUEST
}

Type System

Flux provides a comprehensive type system that maps to native types in each target framework.

Scalar Types

Flux TypeDescriptionReactSwiftUIJetpack Compose
StringText contentstringStringString
IntegerWhole numbersnumberIntint
FloatDecimal numbersnumberDoubledouble
BooleanTrue/falsebooleanBoolbool
ColorColor valuestringColorColor
ImageImage sourcestring | ImageSourcePropTypeImageImage

Collection Types

  • List<T>: Ordered collection
  • Map<K, V>: Key-value pairs
  • Set<T>: Unique values

Nullable Types

By default, all props are required. Use ? suffix to make optional.

component UserCard {
  props: {
    name: String,        // Required
    bio: String?,        // Optional
    website: String?     // Optional
  }
}

Handler Types

Handlers represent callbacks and event handlers:

type Handler<T> = (value: T) -> void
type AsyncHandler<T> = (value: T) -> Promise<void>

Layout System

Flux provides semantic layout primitives that work consistently across platforms.

Stack Layouts

VStack (Vertical Stack):

layout: VStack {
  spacing: 16,
  padding: 20,
  alignment: "center" | "leading" | "trailing",

  children: [...]
}

HStack (Horizontal Stack):

layout: HStack {
  spacing: 12,
  padding: 16,
  alignment: "top" | "center" | "bottom",

  children: [...]
}

ZStack (Depth Stack / Overlay):

layout: ZStack {
  alignment: "center",

  children: [
    // Background
    Image { src: "background.jpg" },
    // Foreground
    VStack { children: [...] }
  ]
}

Flexible Layouts

Grid:

layout: Grid {
  columns: 3,
  spacing: 16,
  padding: 20,

  children: [...]
}

List (Scrollable):

layout: List {
  direction: "vertical" | "horizontal",
  spacing: 8,

  children: [...]
}

Conditional Rendering

component Dashboard {
  props: {
    isLoggedIn: Boolean,
    user: User?
  }

  layout: VStack {
    children: [
      if (props.isLoggedIn) {
        UserProfile { user: props.user }
      } else {
        LoginForm {}
      }
    ]
  }
}

Styling System

Flux uses a semantic styling system that maps to native styling approaches.

Inline Styles

component Card {
  styles: {
    backgroundColor: "#FFFFFF",
    borderRadius: 8,
    padding: 16,
    shadowColor: "#000000",
    shadowOpacity: 0.1,
    shadowRadius: 8
  }
}

Style Variants

component Button {
  props: {
    variant: "primary" | "secondary" | "danger"
  }

  styles: {
    base: {
      padding: 12 24,
      borderRadius: 8,
      fontSize: 16
    },

    variants: {
      primary: {
        backgroundColor: "#0066CC",
        color: "#FFFFFF"
      },
      secondary: {
        backgroundColor: "#F0F0F0",
        color: "#333333"
      },
      danger: {
        backgroundColor: "#CC0000",
        color: "#FFFFFF"
      }
    }
  }
}

Responsive Styles

component ResponsiveCard {
  styles: {
    base: {
      padding: 16,
      width: "100%"
    },

    breakpoints: {
      mobile: { maxWidth: 640 },
      tablet: { maxWidth: 1024 },
      desktop: { maxWidth: null }
    }

    responsive: {
      mobile: {
        padding: 12
      },
      tablet: {
        padding: 20,
        width: "50%"
      },
      desktop: {
        padding: 24,
        width: "33%"
      }
    }
  }
}

Design Tokens

tokens {
  colors: {
    primary: "#0066CC",
    secondary: "#6C757D",
    success: "#28A745",
    danger: "#DC3545",
    warning: "#FFC107",

    text: {
      primary: "#212529",
      secondary: "#6C757D",
      muted: "#ADB5BD"
    },

    background: {
      default: "#FFFFFF",
      surface: "#F8F9FA",
      elevated: "#FFFFFF"
    }
  },

  spacing: {
    xs: 4,
    sm: 8,
    md: 16,
    lg: 24,
    xl: 32
  },

  typography: {
    headline: {
      fontSize: 24,
      fontWeight: 700,
      lineHeight: 1.2
    },
    body: {
      fontSize: 16,
      fontWeight: 400,
      lineHeight: 1.5
    },
    caption: {
      fontSize: 14,
      fontWeight: 400,
      lineHeight: 1.4,
      color: "text.secondary"
    }
  }
}

State Management

Flux provides built-in state management patterns that translate to framework-native solutions.

Local State

component Counter {
  props: {
    initialValue: Integer = 0
  }

  state: {
    count: Integer = props.initialValue
  }

  methods: {
    increment(): void {
      this.state.count += 1
    },

    decrement(): void {
      this.state.count -= 1
    }
  }

  layout: VStack {
    spacing: 16,
    alignment: "center",

    children: [
      Text {
        text: `Count: ${state.count}`,
        style: "headline"
      },
      HStack {
        spacing: 8,
        children: [
          Button {
            label: "-",
            onClick: methods.decrement
          },
          Button {
            label: "+",
            onClick: methods.increment
          }
        ]
      }
    ]
  }
}

Computed Properties

component ProductCard {
  props: {
    product: Product
  }

  computed: {
    discountedPrice(): Float {
      return props.product.price * (1 - props.product.discount)
    },

    isOnSale(): Boolean {
      return props.product.discount > 0
    }
  }

  layout: VStack {
    children: [
      Text { text: props.product.name },
      if (computed.isOnSale) {
        Text {
          text: `$${computed.discountedPrice}`,
          style: "price-sale"
        }
      } else {
        Text {
          text: `$${props.product.price}`,
          style: "price"
        }
      }
    ]
  }
}

Effects and Lifecycle

component UserProfile {
  props: {
    userId: String
  }

  state: {
    user: User? = null,
    loading: Boolean = false,
    error: String? = null
  }

  effects: {
    onMount() {
      this.methods.loadUser()
    },

    onUpdate(changes: { userId: String }) {
      if (changes.userId !== props.userId) {
        this.methods.loadUser()
      }
    }
  }

  methods: {
    async loadUser(): void {
      this.state.loading = true
      try {
        const user = await api.fetchUser(props.userId)
        this.state.user = user
      } catch (error) {
        this.state.error = error.message
      } finally {
        this.state.loading = false
      }
    }
  }
}

Backend Integration

Flux provides plugin points for connecting to backend services.

API Integration

@backend(
  type: "rest",
  baseUrl: "https://api.example.com"
)
component UserList {
  props: {
    onUserClick: Handler<User>
  }

  state: {
    users: List<User> = [],
    loading: Boolean = false
  }

  backend: {
    endpoints: {
      fetchUsers: {
        method: "GET",
        path: "/users",
        response: List<User>
      }
    }
  }

  effects: {
    onMount() {
      this.methods.loadUsers()
    }
  }

  methods: {
    async loadUsers(): void {
      this.state.loading = true
      const users = await this.backend.fetchUsers()
      this.state.users = users
      this.state.loading = false
    }
  }
}

Capacitor Integration

@backend(
  type: "capacitor",
  schema: "./schema.capacitor",
  generator: "typescript"
)
component ProductList {
  props: {
    categoryId: String
  }

  state: {
    products: List<Product> = []
  }

  // Automatically generated from Capacitor schema
  backend: {
    queries: {
      products: capacitor.product.findByCategory(props.categoryId)
    }
  }

  effects: {
    onMount() {
      this.state.products = await this.backend.queries.products
    }
  }
}

Flux provides declarative navigation that works across platforms.

Route Definition

routes {
  home: {
    path: "/",
    component: HomePage
  },

  userProfile: {
    path: "/users/:userId",
    component: UserProfile,
    params: {
      userId: String
    }
  },

  settings: {
    path: "/settings",
    component: SettingsPage,
    auth: required
  }
}
component UserCard {
  props: {
    user: User
  }

  methods: {
    goToProfile(): void {
      navigate.to("userProfile", { userId: props.user.id })
    }
  }

  layout: HStack {
    onClick: methods.goToProfile,
    children: [...]
  }
}

Platform-Specific Code

When needed, Flux allows platform-specific implementations.

Conditional Platform Code

component CameraButton {
  layout: Button {
    label: "Take Photo",
    onClick: methods.openCamera
  }

  methods: {
    openCamera(): void {
      @platform(web) {
        // Web implementation using getUserMedia
        navigator.mediaDevices.getUserMedia({ video: true })
      }

      @platform(ios) {
        // iOS implementation using UIImagePickerController
        UIImagePickerController.show({ sourceType: "camera" })
      }

      @platform(android) {
        // Android implementation using CameraX
        CameraX.startCamera()
      }
    }
  }
}

CLI and Workflow

Commands

flux check

Validates the Flux model and checks target compatibility.

flux check --target react

# Output:
# ✓ components/Button.flux - Valid
# ✓ components/UserProfile.flux - Valid
# ⚠ components/CameraButton.flux - Platform-specific code detected
# ✓ 12 components checked
# ⚠ 1 warning

flux generate

Generates framework-specific implementations.

# Generate React components
flux generate --target react --output ./src/components

# Generate SwiftUI views
flux generate --target swiftui --output ./iOS/Views

# Generate multiple targets
flux generate --target react,vue,swiftui,compose --output ./gen

flux watch

Watch mode for hot reload during development.

flux watch --target react --output ./src/components

flux preview

Preview components in a live environment.

flux preview --component Button --target react

Generator Architecture

Flux uses a generator architecture similar to Capacitor and Smithy.

How Generators Work

  1. Parse Flux models into an abstract syntax tree (AST)
  2. Validate semantic rules (e.g., all props must have types)
  3. Check target compatibility and emit warnings
  4. Generate target-specific code:
    • Framework components (React, Vue, SwiftUI, Jetpack Compose)
    • Type definitions
    • Style sheets
    • Navigation boilerplate

Supported Targets

Web Frameworks

  • React - Functional components with hooks
  • Vue - Vue 3 composition API
  • Next.js - Server and client components
  • Svelte - Svelte 4+ components

Mobile Frameworks

  • SwiftUI - Native iOS/macOS views
  • Jetpack Compose - Modern Android UI
  • Jetpack Compose - Modern Android UI toolkit
  • React Native - JavaScript-based mobile

Desktop

  • Electron - Web technologies for desktop
  • Tauri - Rust-based desktop apps

Example: Complete Application

// Design tokens
tokens {
  colors: {
    primary: "#0066CC",
    background: "#FFFFFF"
  },
  spacing: {
    md: 16
  }
}

// Data shapes
shape User {
  id: String,
  name: String,
  email: String,
  avatar: String
}

shape Post {
  id: String,
  title: String,
  content: String,
  author: User,
  createdAt: Date
}

// Components
component Avatar {
  props: {
    src: String,
    size: Integer = 40
  }

  layout: Image {
    src: props.src,
    width: props.size,
    height: props.size,
    style: "rounded-full"
  }
}

component PostCard {
  props: {
    post: Post,
    onLike: Handler<String>
  }

  state: {
    liked: Boolean = false
  }

  methods: {
    handleLike(): void {
      this.state.liked = !this.state.liked
      props.onLike(props.post.id)
    }
  }

  layout: VStack {
    spacing: 12,
    padding: 16,
    backgroundColor: tokens.colors.background,
    borderRadius: 8,

    children: [
      HStack {
        spacing: 12,
        children: [
          Avatar {
            src: props.post.author.avatar,
            size: 40
          },
          VStack {
            spacing: 4,
            children: [
              Text {
                text: props.post.author.name,
                style: "headline"
              },
              Text {
                text: formatDate(props.post.createdAt),
                style: "caption"
              }
            ]
          }
        ]
      },
      Text {
        text: props.post.title,
        style: "title"
      },
      Text {
        text: props.post.content,
        style: "body"
      },
      HStack {
        spacing: 8,
        children: [
          Button {
            label: state.liked ? "Liked" : "Like",
            variant: state.liked ? "primary" : "secondary",
            onClick: methods.handleLike
          }
        ]
      }
    ]
  }
}

// Routes
routes {
  home: {
    path: "/",
    component: HomePage
  },
  post: {
    path: "/posts/:postId",
    component: PostDetail,
    params: { postId: String }
  }
}

Getting Started

1. Installation

The Flux CLI is distributed as self-contained native binaries for each platform. Releases are available on the Genairus GitHub releases page.

macOS

Homebrew (Recommended)

brew tap genairus/tap && brew install flux-cli

Manual (x86_64 and ARM)

mkdir -p flux-install/flux && \
curl -L https://github.com/genairus/flux/releases/latest/download/flux-cli-darwin-$(uname -m).zip \
-o flux-install/flux-cli.zip && \
unzip -qo flux-install/flux-cli.zip -d flux-install && \
mv flux-install/flux-cli-darwin-*/* flux-install/flux
sudo flux-install/flux/install

Linux

Manual (x86_64 and ARM)

mkdir -p flux-install/flux && \
curl -L https://github.com/genairus/flux/releases/latest/download/flux-cli-linux-$(uname -m).zip \
-o flux-install/flux-cli.zip && \
unzip -qo flux-install/flux-cli.zip -d flux-install && \
mv flux-install/flux-cli-linux-*/* flux-install/flux
sudo flux-install/flux/install

Windows

Scoop (Recommended)

scoop bucket add genairus https://github.com/genairus/scoop-bucket; `
scoop install genairus/flux-cli

Manual (x64)

Download flux-cli-windows-x86_64.zip from the releases page, extract it, then run install.bat as Administrator.

Verify Installation

flux --version

2. Initialize Project

mkdir my-app && cd my-app
flux init

# Output:
# ✓ Created flux.config.yaml
# ✓ Created components/ directory
# ✓ Created tokens.flux

3. Define Your First Component

Create components/Button.flux:

component Button {
  props: {
    label: String,
    onClick: Handler<void>
  }

  layout: Button {
    text: props.label,
    onClick: props.onClick
  }
}

4. Generate Code

flux generate --target react --output ./src/components

5. Use in Your App

import { Button } from './src/components';

function App() {
  return (
    <Button
      label="Click me"
      onClick={() => console.log('Clicked!')}
    />
  );
}

Integration with Other Languages

Flux is part of the Genairus Software Factory ecosystem. It integrates seamlessly with all other generative domain languages:

With Chronos (Requirements)

Define user journeys in Chronos; Flux components can reference those journeys for traceability:

namespace com.acme.ui.checkout

use com.acme.requirements.checkout#GuestCheckout

@journey("GuestCheckout")
component CheckoutForm {
    // This component implements the GuestCheckout journey
    props: {
        onComplete: Function
    }
}

Benefit: Every UI component traces back to the business requirement it fulfills.

With Capacitor (Data Models)

Import Capacitor entities as prop types for type-safe UI components:

namespace com.acme.ui.orders

use com.acme.data.orders#Order
use com.acme.data.orders#OrderStatus

component OrderSummary {
    props: {
        order: Order  // Type from Capacitor
    }

    layout: column {
        text("Order #${order.id}")
        text("Status: ${order.status}")
    }
}

Benefit: UI components automatically typed against your data model. Refactor the entity, and all components update.

With Smithy (API Contracts)

Reference Smithy operations for backend integration:

namespace com.acme.ui.checkout

@backend(operation: "com.acme.api.orders#PlaceOrder")
async function submitOrder(input: PlaceOrderInput) {
    const result = await PlaceOrderAPI.call(input)
    return result
}

component CheckoutForm {
    async function handleSubmit() {
        const result = await submitOrder({
            shippingAddress: this.state.address,
            paymentMethod: this.state.payment
        })
        // Handle result
    }
}

Benefit: Type-safe API calls with generated client SDKs.

With Fusion (Infrastructure)

Flux components are deployed as part of Fusion services:

// In Fusion
service CheckoutUI {
    frontend: {
        source: "../ui/checkout",
        framework: flux,
        target: react
    }
}

Benefit: Complete deployment configuration from infrastructure to frontend.

Standalone Mode

Flux works perfectly without other languages. Define shapes inline:

namespace com.acme.ui.checkout

shape Order {
    id: String
    total: Money
    status: String
}

component OrderSummary {
    props: {
        order: Order  // Inline definition
    }
}

Configuration for Integration

Enable integrations in flux.config.yaml:

version: "1.0"

targets:
  react:
    output: "./src/components"

  swiftui:
    output: "./iOS/Views"

integrations:
  chronos:
    requirements: "./requirements"
  capacitor:
    schema: "./data"
    generator: "typescript"
  smithy:
    spec: "./api"
    client: "typescript"
  fusion:
    infra: "./infrastructure"

For complete integration guide, see Languages Overview.


Best Practices

  1. Component Composition: Build complex UIs from simple, reusable components
  2. Design Tokens: Define your design system once, use everywhere
  3. Type Safety: Always define prop types and data shapes
  4. Platform Awareness: Use platform-specific code only when necessary
  5. Backend Integration: Leverage Capacitor and Smithy for type-safe data access

Further Reading