On the desktop
Real Libadwaita widgets, typed by @girs/adw-1:
Adw.SwitchRow, Adw.HeaderBar, Adw.NavigationSplitView. This is the
reference the other two ports follow, and the code runs unchanged on GJS,
Node.js, Bun and Deno.
Adwaita is GNOME’s design system for GTK 4: the rows, buttons, header bars and dialogs a GNOME app is made of. GJSify gives you the whole set from TypeScript, and the same widget renders as a real Libadwaita widget on the desktop and as a custom element in the browser.
Pick a category below. Every widget on those pages runs live in your browser, in a
window whose second tab holds the markup that paints it, followed by one window per
kind of implementation: Native TypeScript, the @girs program that runs
unchanged on GJS, Node, Bun and Deno, with a Blueprint declaration beside it, UI
frameworks, the same widget written in Solid, Vue and React through
@gjsify/gtk-host, and NativeScript, the port that runs on a phone, whose XML
template holds the tree with the TypeScript beside it as the loader. Choose a tab once
and every widget block on the site follows it.
Adwaita is one design system GJSify supports, not a requirement. Your app is an
ordinary GTK 4 program, so you can mix in plain Gtk.* widgets or style your
own, and the browser components live in a package you opt into. Libadwaita ships
no entry, drop down, plain button or menu button, and those GTK widgets are
documented under Gtk.
On the desktop the widgets come from the Libadwaita library already installed on
the machine. @girs/adw-1 is the type package for it, and nothing else is
needed:
import Adw from 'gi://Adw?version=1';
const row = new Adw.SwitchRow({ title: 'Automatic updates', active: true });For the browser, install the port and import it once. That registers every element and applies the stylesheet, so from there you write HTML:
gjsify install @gjsify/adwaita-webimport '@gjsify/adwaita-web';<adw-preferences-group title="Updates"> <adw-switch-row title="Automatic updates" active></adw-switch-row></adw-preferences-group>The package entry is TypeScript, so it goes through your bundler like any other
dependency: gjsify build --app browser, the
gjsifyBrowser() Vite preset, or whatever you
already use.
To change how any of it looks, set the design tokens.
On the desktop
Real Libadwaita widgets, typed by @girs/adw-1:
Adw.SwitchRow, Adw.HeaderBar, Adw.NavigationSplitView. This is the
reference the other two ports follow, and the code runs unchanged on GJS,
Node.js, Bun and Deno.
In the browser
@gjsify/adwaita-web
gives you the same widgets as custom elements: <adw-switch-row>,
<adw-header-bar>. There is no runtime framework to learn: one import
registers everything, and then you write HTML.
On Android and iOS
@gjsify/adwaita-nativescript
reproduces the Adwaita look with real NativeScript views rather than a
webview: AdwSwitchRow, AdwHeaderBar. Some widgets are simplified, and
each page says where.
The web and NativeScript ports share one behaviour layer, so a fix to a toast queue or a spin-button clamp lands in both at once. If you want the mechanics, see How It Works.
The Adwaita Storybook is a component
browser: pick a widget, change its properties from a controls panel, and watch it
update. Run it as a native window with gjsify storybook, or use the version
embedded on that page.
Ready to assemble a whole app out of these? Start with Native Adwaita Apps.