Install
The Swift package ExponentialUI (iOS 17, macOS 14) carries the painter and the Rust core as an xcframework, so your app never builds Rust. Published, it is a SwiftPM dependency on github.com/Niach/exponential-ui-swift.
ui-v* tag. Until then, build the xcframework once from a checkout and depend on the package by path.bash apps/desktop/crates/exponential-ui-ffi/build-ios.sh # → packages/exponential-ui-swift/Binaries/// swift-tools-version: 5.10
// A fresh SwiftUI app on the Exponential UI SDK. Published, the dependency is
// .package(url: "https://github.com/Niach/exponential-ui-swift", from: "0.1.0")
// with `package: "exponential-ui-swift"` below; until then it is the
// monorepo's package by path (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
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 SwiftUI
import 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
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
Every file on this page is a real file in apps/ui-site/guides/swift. CI copies it into an empty directory and builds it from scratch, the way you would, so the example cannot drift from the SDK:
bun apps/ui-site/guides/check.ts swiftFor a complete app on this platform, see the samples: four hosts rendering the same surface from a local A2UI server, in a third-party theme, with a custom extension component.