Skip to content

Platforms#

A leptoskit app is one tree of components. The web renders it as HTML through leptos. Every other platform renders it with that platform's own widgets, laid out by leptoskit's layout engine. This page lists the platforms, how to build for each, and what each one doesn't do yet.

PlatformDrawn withBuild commandComponents in the app leptoskit new generates
WebHTML and CSS, through leptosleptoskit build --platform webAll
WindowsWin32 common controlsleptoskit build --platform windowsAll
LinuxGTK 4 widgetsleptoskit build --platform linuxAll
macOSAppKit (NSView, NSButton, …)leptoskit build --platform macosTen (see below)
iOSUIKit (UIView, UIButton, …)leptoskit build --platform iosAll built-in controls (see below)
AndroidAndroid views (View, Button, …)leptoskit build --platform androidTen (see below)
HarmonyOSArkUI componentsleptoskit native build harmonyosEight, experimental
TerminalCharacters in the terminal's cellsleptoskit build --platform tuiAll except Rive
Browser extensionsHTML and CSS, through leptosleptoskit build --platform extensionAll

macOS and iOS apps build on a Mac, the Windows app on Windows, and the Linux app on Linux. leptoskit native build takes the same platforms plus simulator and architecture variants: ios-simulator, android-x86_64 for x86-64 emulators, and harmonyos-x86_64. Host projects lists the tools each platform needs.

Generated apps and backend crates#

leptoskit draws native widgets in two places, and today they don't cover the same components.

Generated macOS, iOS, and Android apps use the Swift or Kotlin renderers in leptoskit_bridge_ffi. They support View, Text, Button, Pressable, TextInput, PasswordInput, ScrollView, Image, Vector, and Rive. Other control kinds fail with an unsupported-widget error. Accessible names are forwarded; a labelled Vector is an accessible image and Rive can be decorative. Most other roles and states are not forwarded. The Rust backend crates support a wider control set. Generated Windows and Linux apps use the full Rust backends, but currently omit runtime plugin registration. Automatic code push update checks currently run only in generated iOS and Android hosts.

The backend crates, leptoskit_appkit, leptoskit_uikit, leptoskit_android, leptoskit_gtk, and leptoskit_windows, draw every built-in component. They are what the screenshots on this site, the examples, and leptoskit's own widget tests use. You use them directly when you put a NativeSurface in your own native Rust app, for example with UIKitHost on iOS. Your screens are then compiled into the app rather than run as WebAssembly, so code push doesn't apply.

What each platform doesn't do yet#

The macOS backend crate is the reference. Compared with it:

PlatformDifferences
macOSThe generated app draws the built-in controls. Keyboard and VoiceOver activation don't show a button's pressed style.
iOSThe generated app draws the built-in controls. iOS has no native checkbox or radio button, so Checkbox and Radio are drawn with UIButton, and VoiceOver gets fewer roles than on macOS, with no expanded or collapsed state. Keyboard and VoiceOver activation don't show a button's pressed style.
AndroidThe generated app draws the built-in controls. In the backend, a Custom widget kind with no registered native implementation stops the app instead of rendering an empty container, and TalkBack gets a smaller set of roles than macOS. Italic text and per-edge borders paint.
LinuxLive regions update their text but aren't announced: announcements need GTK 4.14, and leptoskit supports GTK 4.6 and newer. Italic text and per-edge borders paint through GTK.
WindowsSwitch is drawn as a checkbox. Rounded corners are cut with a window region, so their edges aren't smoothed, and borders stay rectangular inside them. Accessibility has no expanded or collapsed state. A Vector with no background takes clicks only where it has ink.
HarmonyOSOnly View, Text, Button, TextInput, PasswordInput, ScrollView, Image, and Rive; other components, including Vector, stop with an error. Italic text and per-edge borders paint through ArkUI the same way as on Android and GTK. No code push, dark mode, right-to-left layout, horizontal scrolling, public scroll events, native text measurement, or active: pressed styles. See HarmonyOS.
TerminalThe font is the user's terminal font: sizes and weights draw as attributes and colors, not different metrics. Image and Vector draw a placeholder texture, Rive playback is unsupported, and right-to-left text is not reordered. See Terminal.

Some limits apply to every native platform:

  • Image loads local files, not URLs. iOS also accepts resource:// names and Android android.resource:// URIs.
  • Rive supports vector scenes. Native text, images, layout, scripts, audio, view models, and some draw features are rejected. HarmonyOS uses an application-supplied reduced-motion preference and still needs device playback validation.
  • Shadows, transforms, gradients, custom fonts, line height, and letter spacing aren't supported yet. The CSS coverage reference lists what is.
  • Links (href) only work on the web.
  • A scroll view's scroll_offset moves it on the web and in the generated macOS, iOS, and Android apps. The backend crates, and so the generated Windows and Linux apps, HarmonyOS, and the terminal don't apply it yet.
  • The generated macOS, Windows, and Linux apps don't check for code push updates yet; only the iOS and Android apps do. Ship a new build to update a desktop app.

How a native app is put together#

your app's screens, compiled to WebAssembly   ◀── replaced over the air by code push
        │ a tree of components
leptoskit renderer: diffs the tree, lays it out with flexbox and grid
        │ create, update, move, and remove widgets
platform backend: AppKit, UIKit, Android views, GTK 4, Win32, or ArkUI
        │
the platform's real widgets

Your screens run as WebAssembly inside a small interpreter that ships in the app. That is what lets code push replace them without an app store release: the interpreter, the renderer, and the widgets stay in the installed app, and only the WebAssembly changes. The interpreter is wasmi, which does not generate machine code at runtime. Distributing an interpreter or an interface update still requires compliance with the target store’s policies.

Pages in this section#

  • Code reuse: what you write once, what you write per platform, and where the seams are.
  • Web: server rendering, hydration, and serving.
  • iOS, Android, macOS, and Windows and Linux: each platform's build, run, and release steps.
  • HarmonyOS: the experimental target and its limits.
  • Terminal: the same screens in an interactive terminal, for long-lived apps.
  • Host projects: the platform folders in your project, their requirements, and plugin registration.
  • Runtime plugins and the plugin support matrix: operating-system services such as the clipboard, location, and notifications.
esc