Rust first · a native UI framework for every platform

Build once,
native everywhere.

Native Shell is a Rust-first, native UI framework for every platform: one app model and one toolchain build apps for iOS, Android, macOS, Windows, Linux and the web, each built on the system’s own UI and interaction, and the same engine delivers new UI — written by your team or generated by AI — after release.

  • The system’s UI and interactionUIKit, Android views, AppKit, Win32, GTK 4 and HTML, with the system’s text, input methods and accessibility; one menu pops up on the desktop and rises as a sheet on a phone
  • Rust firstwhole apps compile to native code; TSX when you want screens fast
  • Retained viewsonly what changed is updated: 120 FPS, near-idle CPU at rest
  • AI-friendlyone app model, one nsh command line, and signed AI-generated UI delivered after release
One app, on phones, desktops and the web
  • iOS
  • Android
  • macOS
  • Windows
  • Linux
  • Web
  • GPUI
  • Open source · Apache-2.0
  • Built at Longbridge
CLInsh init my-app
Chat.tsxLive
The gallery’s AI chat, written in TSX and running live here in your browser on Native Shell’s web runtime. Replies are scripted and streamed locally; tap a suggestion or + to replay a scenario.
Native

Native, in two ways.

NSH unifies components, state, logic and API. The app owns its visual design; views and interaction build on each platform’s foundations.

01

The platform’s foundations

Each backend builds the UI from what its platform already has: UIKit views, Android views, AppKit views, GTK 4 widgets, Win32 windows drawn with Direct2D and DirectWrite, and HTML elements styled with CSS. Text input, selection, input methods and accessibility come from the platform.

02

The platform’s interaction

One component behaves as each device’s users expect. A Menu opens as a popup at its trigger with a pointer and as a sheet from the bottom on a phone; a ContextMenu opens on a right click, or when a finger holds the trigger. The app writes the menu once.

A backend per platform

  • iOSUIKit · CoreText · iOS 15+--target ios
  • AndroidAndroid View · StaticLayout · API 28+--target android
  • macOSAppKit · CoreText · macOS 14+--target macos
  • WindowsWin32 · Direct2D · DirectWrite · 10 1809+--target windows
  • LinuxGTK 4 · Pango · GTK 4.14+--target linux
  • WebHTML · CSS · modern browsers--target web
  • GPUIGPUI · embedded in GPUI and GPUI Kit apps (macOS / Windows / Linux)--target gpui
Truly cross-platform

From phone to desktop to web.

Cross-platform here means each device gets the app it expects: the layout reshapes with the window, the input follows the device, the logic stays one. One engineer can write the app once and check it on every target.

Layouts that reshape

Flexbox and grid laid out by Taffy, with Tailwind breakpoints (md:, lg:) and the window’s size in Rust: a chat app shows its sidebar, conversations and messages side by side in a wide window, and one screen at a time on a phone.

  • md:
  • window()
  • Taffy

The input each device expects

A pointer, hover, right clicks, shortcuts and focus on the desktop; touches, gestures, the software keyboard and page navigation on phones. nsh/base’s components carry both, so the app’s code stays one.

  • Menu
  • ContextMenu
  • NavStack

Checked on every target

nsh test runs the app’s tests headless, and the same tests in macOS, Windows, Linux and GPUI windows, an iOS simulator, an Android device or a browser, with the platform’s own input.

  • nsh test
  • --target ios
  • --target web
Rust first

Rust for the app, TSX where it helps.

Rust is a first-class language for whole NSH apps: UI, logic and components compile to native code, with Rust’s ownership, types, threads and crates.io. TSX is the second path, for screens written quickly, plugins and UI delivered at run time. Both run on one engine with the same primitives, base components and signals, and TSX screens import your Rust components.

Building with Rust
src/lib.rs
use nsh_core::element::prelude::*;

#[component]
pub fn App() -> impl IntoElement {
    let count = signal(0);
    view()
        .items_center()
        .gap_4()
        .child(text(move || format!("Count: {}", count.get())))
        .child(
            view()
                .rounded_lg().bg(rgb(0x2563eb)).px_5().py_3()
                .on_press(move || count.update(|n| *n += 1))
                .child(text("Tap").text_color(white())),
        )
}
Foundations

Built on what each platform does best.

Text, input, native components and the web are the hardest parts of a UI framework. NSH takes them from the platform, and puts its own work into the engine, the base components and the toolchain.

From the platformwhat the system already does well, used as it is

The system’s text and input

Text fields are the platform’s editors — UITextView, EditText, NSTextView, GTK’s TextView, the browser’s — with its input methods, selection handles, editing menus and shortcuts; on Windows, NSH’s editor works with DirectWrite and IMM32. What a new OS release brings to text and input reaches the app with it.

  • UITextView
  • EditText
  • NSTextView
  • GtkTextView
  • DirectWrite

Native components that layer in

Maps, web views, video players and any native view the host registers are one more subview in the same hierarchy: NSH lays them out with the rest of the app, and they clip, scroll and take touches like any view.

  • WebView
  • Video
  • nativeComponent

A web app made of HTML

On the web, NSH renders HTML elements styled with CSS; the browser scrolls, selects text and handles input. nsh package --target web publishes a static site whose files are named by content, ready for any CDN cache.

  • HTML
  • CSS
  • --target web

Built by NSHNSH’s own work, on top of the platform

Retained views: 120 FPS, low CPU

Every element is a view the platform keeps. A change runs only the expressions that read the changed signal and sends only the views it touched, in one batch per frame; the other views stay as they are, and native animations run without JS per frame. Everyday screens — chats, forms, lists — sit near idle at rest, and scrolling and animation hold 120 FPS on ProMotion displays.

  • signal
  • MountBatch
  • Taffy
  • 120 FPS

Behavior from NSH, the look from you

nsh/base holds unstyled base components — navigation, dialogs, menus, popovers, tabs, checkboxes, sheets — that own state, focus, keyboard and accessibility. The app styles every part, with Tailwind classes or typed styles.

  • nsh/base
  • Menu
  • Dialog
  • Tailwind

One toolchain, for people and agents

A single nsh executable creates, builds, type-checks, runs with hot reload, tests, packages and signs apps for every target, with its own TSX bundler and TypeScript checker. Every API has declarations generated from the Rust sources and the docs are served as llms.txt, so an AI agent runs the whole loop — generate, run, test, fix, package — with the same commands.

  • nsh run
  • nsh test
  • nsh package
  • llms.txt
Ways to ship

A whole app, or UI delivered after release.

Standalone apps are where NSH starts. On the same engine, apps can also take new UI at run time — written by your team or generated by a model — as signed modules, in a sandbox the host sets.

Standalone appsStart here

Ship to six platforms

Write the app in Rust, TSX or both, and nsh package makes an installable iOS, Android, macOS, Windows or Linux app, or a static website.

$ nsh init my-app --template rust
$ nsh run my-app --target macos
$ nsh package my-app --target windows
# --template ts for TSX
# ios · android · macos · windows · linux · gpui · web
  • Rust apps compile entirely to native code
  • One command per target
  • Rebuilds for Rust, hot updates for TSX
Getting started
Dynamic UI and plugins

Extend the app after release

Embed an NshAppView (iOS), NshView (Android), AppView (desktop and GPUI apps) or createPlayer (a web page) on any screen, and load signed TSX modules into it at run time.

let app = NshAppView()
try app.grantCapabilities(grants)
let info = try await app
  .loadPackage(at: file, trust: trust)
// verified, sandboxed, running
// NshView on Android, AppView elsewhere
  • Several modules on one screen
  • The host’s own native components
  • Updates on your schedule
Embedding, per platform
AI-generated UI

Answer with an interface

A model writes a module per request, your server checks and signs it, and the app shows it natively, in a sandbox.

import { mount, signal, View } from "nsh";

function Answer() {
  const range = signal("1W");
  return <View class="gap-3 p-4">…</View>;
}
mount(Answer);
  • One TSX file per answer
  • Type-checked and traced before it ships
  • Only the capabilities the host grants
Signing and sandboxing
Dynamic delivery

Generated on the server, trusted on the device.

Modules arrive as Ed25519-signed .nshpkg files, release keys are certified by an offline root and revocations are checked on the device; each view runs its module in a QuickJS VM with memory, call-time and node limits, reaching only the capabilities the host grants.

Generated on the server, trusted on the device.Generated on the server, trusted on the device.
Principle

Native views and interaction,
your visual design.

The same app has the same features everywhere: one model of components, state and logic. How it feels under a finger or a pointer, how its text is edited, how its menus open — that belongs to each platform.

Start building