Render A2UI in SwiftUI
Install
Section titled “Install”The Swift package ExponentialUI (iOS 17, macOS 14) carries the painter and the Rust core as an xcframework, so your app builds no Rust. It is a SwiftPM dependency on github.com/Niach/exponential-ui-swift, whose tag 0.12.0 pins the xcframework of that release by checksum:
dependencies: [ .package(url: "https://github.com/Niach/exponential-ui-swift", from: "0.12.0"),],targets: [ .executableTarget(name: "App", dependencies: [.product(name: "ExponentialUI", package: "exponential-ui-swift")]),]The guide’s own manifest builds the monorepo’s package by path, so CI checks it without a download:
// swift-tools-version: 5.10// A fresh SwiftUI app on the Exponential UI SDK. An app depends on the release:// .package(url: "https://github.com/Niach/exponential-ui-swift", from: "0.12.0")// with `package: "exponential-ui-swift"` below. This guide builds the// monorepo's package by path so CI checks it without a download (its// Binaries/ExponentialUIFFI.xcframework comes from// `bash apps/desktop/crates/exponential-ui-ffi/build-ios.sh`).import PackageDescription
let package = Package( name: "GuideApp", platforms: [.iOS(.v17), .macOS(.v14)], dependencies: [ .package(path: "../../../../packages/exponential-ui-swift"), ], targets: [ .executableTarget( name: "GuideApp", dependencies: [.product(name: "ExponentialUI", package: "exponential-ui-swift")] ), ])Paint a surface
Section titled “Paint a surface”The same shape as on the web: one ExponentialHost with a transport, a theme and a mode, and a HostSurface per surface id. The surface is as tall as its content, so you choose the scroller.
import SwiftUIimport ExponentialUI
struct ContentView: View { // One host per app: A2UI messages in over a transport, actions back out. @State private var host = ExponentialHost(HostOptions( transport: JSONLStreamTransport( url: URL(string: "http://localhost:4300/a2ui.jsonl")!, postUrl: URL(string: "http://localhost:4300/action")! ), theme: ThemeHandle.builtin("exponential"), mode: .dark ))
var body: some View { // The surface the agent creates, as tall as its content: you own the scroller. ScrollView { HostSurface(host: host, surfaceId: "main") { ProgressView("Waiting for the agent…") } .padding(16) } .task { host.connect() } }}Host plugin
Section titled “Host plugin”For lower-level use, SurfaceModel + ExponentialSurface take a HostPlugin; every method has a default and ClosureHost builds one from closures:
icon(name, size): the catalog’s icon names to your views.onActiongets every A2UI action.onInputgets text edits (debouncedchangewith a revision,commiton blur or Return).openUrl,resolveUrl,fontFamily,markdown.
Register the font files a theme names with ExponentialUI.registerFont(at:); switch themes with ThemeHandle.load(json:) and setTheme. Details in the Swift package’s README.
Compiled in CI
Section titled “Compiled in CI”bun packages/exponential-ui/guides/check.ts swift builds guides/swift in an empty directory against the monorepo’s Swift package.