Skip to content

One leptos tree. Real native widgets.#

leptoskit is a Rust toolkit for building an app's interface once, with leptos components and built-in Tailwind styles, and shipping it to the browser and as real native widgets on the desktop and on phones.

Get startedSource on GitHub

What leptoskit is for#

Most cross-platform toolkits make you pick: render to a web view everywhere, or write each platform twice. leptoskit takes a third path.

You describe a screen once, in Rust, as a tree of components: View, Text, Button, TextInput, ScrollView, and the rest. On the web, the same tree renders through leptos to the DOM, with server rendering and hydration. On native platforms, leptoskit's own layout engine lays the tree out with flexbox and CSS grid, and a platform backend commits it as the platform's real controls: AppKit views on macOS, UIKit on iOS, Android views, GTK 4 on Linux, Win32 controls on Windows, and, experimentally, ArkUI on HarmonyOS. In a terminal, the same tree draws as characters in the cell grid. Nothing runs in a web view.

A screen in leptoskit#

A screen is a function returning an Element. Tailwind classes style it on every platform:

use leptoskit::prelude::*;

#[component]
pub fn Welcome(name: &str, on_start: impl Fn() + Send + Sync + 'static) -> Element {
	view! {
		<View class="gap-4 rounded-2xl bg-white p-6 dark:bg-slate-900">
			<Text class="text-2xl font-bold">{format!("Hello, {name}")}</Text>
			<Text class="text-slate-500">"Your interface, everywhere."</Text>
			<Button class="rounded-lg bg-rose-500 px-4 py-2 text-white" on:press=on_start>
				"Start"
			</Button>
		</View>
	}
}

The same function renders as DOM elements in a browser, and through a platform backend as NSViews, UIViews, Android views, GTK widgets, Win32 controls, or ArkUI components. The shared components guide walks through it, and the component catalog lists every component.

See it render#

These screens are leptoskit element trees committed as real AppKit views and rendered offscreen. They are not mockups. See all of them.

How the pieces fit#

The logo is the architecture. The ember boxes are layout: elements placed by the layout engine and committed as native widgets. The mint piece is the next version of your interface arriving over the air and dropping into place. Hover over it at the top of this page.

CrateWhat it does
leptoskitThe crate your app depends on. It re-exports the components, styles, and runtime, with a feature per optional part.
leptoskit_cliThe leptoskit command, also installed as lk, which scaffolds, builds, serves, tests, formats, and ships apps.
leptoskit_nativeThe components, Tailwind support, and the renderer that diffs element trees into mutation batches for a platform backend.
leptoskit_yogaThe layout engine behind native rendering: flexbox and CSS grid, gaps, aspect ratio, and right-to-left layout.
leptoskit_appkitThe macOS backend. leptoskit_uikit, leptoskit_android, leptoskit_gtk, and leptoskit_windows do the same for their platforms.
leptoskit_wasmThe on-device runtime. It runs the interface bundle in wasmi, an interpreter that needs no JIT.
leptoskit_codepushOver-the-air updates: signed, content-hashed releases, binary deltas, and a client that verifies everything before it stages.
leptoskit_axumThe server toolkit: static files with precompressed copies, SPA fallback, health checks, and the code push registry, on Axum.
leptoskit_routerFile-based routing. src/routes/ becomes one typed Route enum.
leptoskit_queryCached, deduplicated, retrying async data in the style of TanStack Query.
leptoskit_l10nTyped translations in the style of Flutter's gen_l10n: ARB files become a Messages trait, with plurals for every language.
leptoskit_testingWidget tests with semantic finders, plus a driver that runs the same journeys against real native apps.
leptoskit_docsMarkdown with leptos components, and the generator that builds this site. See writing docs.

Over the air updates#

An installed native app is a small host that runs your interface as a WebAssembly bundle. Code push ships a new bundle over the air: signed, content-hashed releases, binary deltas, and a client that verifies every byte before it stages the update. A trial release replaces the working one only after it renders, so a release that fails to start is rejected and the app keeps running. The generated iOS and Android apps install these releases today; the generated macOS, Windows, and Linux apps don't check for updates yet. A release must match the installed host's interface contract and signing policy, and store rules still apply to what a download changes. Code push covers keys, channels, publishing, and rollback.

Where things stand#

leptoskit is young, and these docs say plainly what works today.

Native filesystem, SQLite, and secure-store plugins enforce aggregate storage budgets in addition to operation limits. See storage and networking for defaults and upgrade behavior.

Axum is the one supported server.

To work on leptoskit itself, start with CONTRIBUTING.md.

esc