Your web app, drawn natively on the GPU.
gpuijs runs React, Vue and Solid apps as native desktop apps through GPUI, the UI framework behind the Zed editor. Keep your components and your CSS. Ship no browser engine and no WebView.
import { render } from "@gpuijs/core/react"
import { useState } from "react"
function App() {
const [todos, setTodos] = useState(initial)
return (
<main className="flex flex-col gap-3 p-6">
<h1 className="title">Todos</h1>
{todos.map((todo) => (
<Todo key={todo.id} todo={todo} />
))}
</main>
)
}
render(<App />)
<script setup>
import { ref } from "vue"
const todos = ref(initial)
</script>
<template>
<main class="flex flex-col gap-3 p-6">
<h1 class="title">Todos</h1>
<Todo
v-for="todo in todos"
:key="todo.id"
:todo="todo"
/>
</main>
</template>
import { render } from "@gpuijs/core/solid"
import { createSignal, For } from "solid-js"
function App() {
const [todos, setTodos] = createSignal(initial)
return (
<main class="flex flex-col gap-3 p-6">
<h1 class="title">Todos</h1>
<For each={todos()}>
{(todo) => <Todo todo={todo} />}
</For>
</main>
)
}
render(() => <App />)
One app, three frameworks. Try the window: it's the todo list from the Vue and Solid examples.
Runs the libraries you already use
No browser inside
Not Chromium. Not a WebView.
Electron ships a browser with every app, and Tauri borrows the system's. gpuijs ships neither: your CSS is cascaded, laid out and drawn by a native host.
Bundles Chromium
Your UI is a web page, rendered by a full browser engine packaged into the app.
Uses the system WebView
Your UI is a web page, rendered by the operating system's web engine (WKWebView on macOS).
No web engine at all
Your framework runs under Bun. A Rust host built on GPUI runs your CSS and draws every frame with Metal.
How it works
From component to pixel
Two processes and a pipe. Events take the same path back, with browser-like capture and bubbling.
The app
BunYour components
React, Vue or Solid, unchanged.
Host nodes
Lightweight nodes stand in for the DOM.
Commit
Each batch of changes is encoded as compact binary ops.
The host
RustCSS cascade
Your stylesheet, run over a mirror of the tree.
Layout
Flexbox, grid and block layout.
Pixels
Drawn with Metal through GPUI.
What you get
The web platform your app uses, made native
Real CSS
Selectors, cascade layers, custom properties, calc(), media and container queries, :has(), transitions and keyframes. Tailwind v4 is compiled for you.
Native text fields
Inputs are native GPUI fields with IME and dead keys, so typing never waits on JavaScript.
Electron-style shell
Window, Menu, app and dialog, with Electron's names. Custom title bars with app-region.
Your libraries
Enough of window and document for Radix, MUI, Recharts, ApexCharts, react-router and more.
One-command packaging
gpuijs build writes a signed .app, ready to notarize.
Charts and SVG
Inline SVG is rasterized sharp at any scale, and hit-tested by shape for chart tooltips.
Native shell
The desktop APIs you know from Electron
Windows, menus, dialogs and the Dock use Electron's names and shapes, carried out with native AppKit through GPUI.
- Hidden title bars with placed traffic lights
- Application, Dock and context menus with accelerators
- Open, save and message dialogs
import { Menu, Window, dialog } from "@gpuijs/core"
const win = new Window({
width: 1200,
height: 800,
titleBarStyle: "hidden",
trafficLightPosition: { x: 16, y: 18 },
})
Menu.setApplicationMenu(
Menu.buildFromTemplate([
{ role: "appMenu" },
{ label: "File", submenu: [
{ label: "Open…", accelerator: "CmdOrCtrl+O",
click: () => dialog.showOpenDialog(win) },
] },
{ role: "editMenu" },
]),
)
Platforms
macOS today. Windows and Linux next.
gpuijs is early software. It runs on macOS now, and support for Windows and Linux is in progress.
macOS
Windows
Linux
An app has one window for now, and gpuijs is not a browser: iframes and native drag and drop don't work. See the known gaps.
Build your first native app
Start from an example, or bring the app you already have.