// React · Linux · TypeScript · GLib · Rust
The React framework for Linux
Write declarative React apps like you're used to. Ship native Linux apps, with first-class GTK4 and Adwaita support.
import {GtkApplication, GtkApplicationWindow, GtkLabel,} from "@gtkx/jsx/gtk";import { createRoot } from "@gtkx/react"; const App = () => (<GtkApplication><GtkApplicationWindow title="My App"><GtkLabel>Hello from GTKX 👋</GtkLabel></GtkApplicationWindow></GtkApplication>); createRoot().render(<App />);``npm create gtkx@rcBuilt on the GNOME stack and standard web tooling
- GObject
- GTK4
- Adwaita
- GNOME
- React
- TypeScript
- Vite
- Rust
Why GTKX
Native. Declarative. Typed.
GTK4 widgets, driven by React. What you ship is a GNOME app.
Native widgets
Every element is a GObject: a GtkButton, an AdwHeaderBar. Your app is built from the same widgets GNOME ships.
Powered by Rust
A native Rust core built on libffi calls into GTK4 and Adwaita directly, with your widgets living in native memory.
Hot reload, for desktop
Fast Refresh patches the running window as you save. Changes it cannot patch trigger an automatic, supervised restart.
Typed end to end
Every class, signal, and property is generated from GObject-Introspection. Autocomplete any GObject-Introspection library on your system.
Testing, built in
Query and drive GTK4 widgets in your tests. Every worker gets its own headless Wayland display, started and torn down for you. It runs on Vitest.
Agentic MCP server
A Model Context Protocol (MCP) server exposes your live app to AI agents. Register it once with your agent, and gtkx dev connects your running app to it automatically.
JSX to GObject, typed from your system
How GTKX works
Your app config drives the codegen
Name the GObject-Introspection libraries you want and codegen reads them off your system, emitting typed bindings for exactly those namespaces.
import { defineConfig } from "@gtkx/config";export default defineConfig({ libraries: ["Gtk-4.0", "Adw-1", "WebKit-6.0"], applicationId: "com.example.myapp",});### If it is a GObject, you can write it in JSX
Element types are GObject type names. Nested GObjects go in props, so a header bar or an adjustment is an element too, not an object you build on the side.
<AdwToolbarView topBar={<AdwHeaderBar />}> <GtkScale adjustment={<GtkAdjustment upper={100} />} drawValue /></AdwToolbarView>### Harness the full power of the Node ecosystem
GTKX runs on vanilla Node. So all npm packages work, and so does React. Styling is Emotion.
import { css } from "@gtkx/css";import { readFile } from "node:fs/promises";import { useState } from "react";A unified CLI for development
Scaffold, develop, ship: one tool
Scaffold a typed app.
npm create gtkx@rc◇ Project structure created◇ Dependencies installed◇ Git repository initializedA rich and detailed tutorial
Meet Tasks, GTKX's reference app
The docs walk you through creating Tasks, a complete GNOME app: adaptive split view, GSettings, notifications, and shipped as a Flatpak.
Free and open source
Built in the open, on the GNOME stack
GTKX is MPL-2.0-licensed and developed in public. We're open to contributions, and we welcome feedback and questions on GitHub.