G
YouTube TikTok Games

@tarve/core 0.12.0Windows x64 · Linux x64 · AndroidApache-2.0

TSX in. Pixels out. No browser between.

Tarve is a desktop UI toolkit for Bun. You write components in TSX; a Rust runtime lays them out, shapes the text and paints the window. There is no web view underneath.

Documentation Try a demo app
app.tsx
import { Button, Column, Text, Window, createApp } from "@tarve/core";

let count = 0;

function App() {
  return (
    <Window title="Counter" width={520} height={360}>
      <Column flex={1} align="center" justify="center" gap={16}>
        <Text size={42} weight={700}>{count}</Text>
        <Button onClick={() => count++}>Increase</Button>
      </Column>
    </Window>
  );
}

const app = createApp(App);
await app.ready;
await app.closed;
Fig. 1 The program on the left, running in this page

Loading Tarve's runtime (WebAssembly)…

0 frames painted — idle, 0 fps

Not a screenshot and not HTML. This is Tarve's native layout, text and paint code compiled to WebAssembly, drawing into a canvas. It paints only when you click.

01

Specification

Runtime
Bun 1.4+, Node.js 26.10+, txiki.js, GoTypeScript and TSX run directly, no build step in development
Platforms
Windows x64, Linux x64, Androiddesktop runtimes ship inside the npm package; APK and AAB from tarve build
Layout
Taffyretained Flexbox and Grid, updated incrementally
Text
Parleyshaping, selection, IME composition, Unicode editing
Rendering
D3D11 / DXGI, Vello / WGPU, vello_cpuchosen per machine, with fallbacks
Accessibility
AccessKitUI Automation on Windows, AT-SPI on Linux, TalkBack on Android
Components
97each with a reference page and a live example
Frames while idle
0nothing is presented until something changes
Output
One executableper target, runtime embedded, cross-compiled; deb, tar.gz, zip and MSIX via tarve package
Tooling
create-tarve, @tarve/router, @tarve/testscaffolding, navigation, headless tests and a visual inspector
Not included
Chromium, the DOM, a CSS engine, React
License
Apache-2.0
02

What happens on a click

Six stages between an event handler and the screen. Each one does nothing until the one before it hands over work.

  1. 01

    TSX

    Bun

    A view is a function that returns TSX, compiled against Tarve's own JSX runtime. React is not involved.

  2. 02

    Diff

    Bun

    The reconciler compares the new tree with the last one and keeps only the nodes that changed.

  3. 03

    Bridge

    Bun → Rust

    The mutations cross to the native runtime once. Nothing polls; both sides sleep between events.

  4. 04

    Layout

    Taffy

    Flexbox and Grid on a retained tree, so a changed label does not re-measure the whole window.

  5. 05

    Text

    Parley

    Shaping, line breaking, selection and IME composition for every Text, Input and TextArea.

  6. 06

    Paint

    D3D11 · Vello · CPU

    The damaged region is painted and presented. Then the window goes quiet again.

03

In the box

Text editing
Selection, clipboard with text, files and images, IME composition, undo and redo, grapheme-aware cursor movement.
Rich content
Markdown, syntax-highlighted Code and Diff are native leaves, so a 10,000-line file is one node, not 10,000.
Long lists
VirtualList with fixed, measured or externally windowed rows.
Accessibility
Every control is exposed through AccessKit to UI Automation on Windows and AT-SPI on Linux.
Desktop APIs
Global hotkeys, native file dialogs, custom title bars, window positioning, close interception.
Development
Error overlay inside the window, same-window remount under bun --hot, and a frame-time graph.
Themes
Light and dark token sets in the shape of shadcn/ui, swappable at runtime without recreating the window.
Testing
@tarve/headless renders any view to pixels or queries it by role, with no window, GPU or native binary.
04

Renderers

createApp takes renderer: "auto" | "gpu" | "cpu". Windows uses D3D11/DXGI with a Vello/WGPU fallback, Linux uses Vello/WGPU, and both have a low-memory CPU path. Pick a combination to see the order Tarve tries them in.

  1. D3D11 / DXGI in use
  2. Vello / WGPU standby
  3. vello_cpu + softbuffer standby

D3D11/DXGI with a Vello/WGPU fallback for initialization or recovery failures. If Vello cannot run on the adapter, it falls back to CPU.

05

Styling

Style objects read like CSS: gradients, boxShadow, textShadow, transform and transitions on hover, focus and updates. They are interpreted natively and look the same on D3D11, Vello and the CPU renderer.

card.tsx
<Column style={{
  background: "linear-gradient(180deg, #fbfaf6, #ece8dc)",
  borderColor: "#15140f",
  borderWidth: 1,
  radius: 4,
  boxShadow: { y: 1, blur: 2, color: "#15140f1f" },
  hover: {
    transform: "translateY(-2px)",
    boxShadow: { y: 10, blur: 24, color: "#15140f2e" },
  },
  transition: { all: { duration: 180, easing: "easeOut" } },
}} />
06

Index of components

97 components, all exported from @tarve/core. Each name opens its reference page with a live example.

07

Shipping

tarve build compiles the app into one executable with the native runtime embedded. The npm package already carries the Windows and Linux runtimes, so either target builds from either machine without a Rust toolchain.

terminal
# Windows → .exe with the native runtime embedded
bun run tarve build app.tsx --outfile dist/App.exe

# cross-compile for Linux x64, no Rust toolchain needed
bun run tarve build app.tsx --target linux-x64 --outfile dist/App