Skip to content

romgrk/node-gtk

Repository files navigation

NODE-GTK

node-gtk

GTK bindings for NodeJS
Package Version

node-gtk is a gobject-introspection library for nodejs. It makes it possible to use any introspected C library, such as GTK, usable. It is similar in essence to GJS or PyGObject. Please note this project is currently in a alpha state.

Supported Node.js versions: 20, 22, 24 (other versions may work but are untested)
Supported platforms:

  • Linux — prebuilt binaries available
  • macOS — prebuilt binaries available
  • Windows — prebuilt binaries available (but read Windows)

Table of contents

Usage

Below is a minimal example of how to use node-gtk:

const gi = require('node-gtk');
const GLib = gi.require('GLib', '2.0');
const Gtk = gi.require('Gtk', '4.0');
const Adw = gi.require('Adw', '1');

const loop = GLib.MainLoop.new(null, false);
const app = new Adw.Application('com.github.romgrk.node-gtk.hello', 0);

app.on('activate', () => {
  const content = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
  content.append(new Adw.HeaderBar());
  content.append(new Gtk.Label({ label: 'Hello Adwaita!', vexpand: true }));

  const window = new Adw.ApplicationWindow(app);
  window.setTitle('node-gtk');
  window.setDefaultSize(300, 120);
  window.setContent(content);
  window.on('close-request', () => (loop.quit(), app.quit(), false));
  window.present();

  gi.startLoop();
  loop.run();
});

process.exit(app.run([]));

You can also easily create custom applications:

A web browser (using WebKit2GTK)

A system monitor

ES modules

The Usage example above is CommonJS. node-gtk also works under ESM, but the blocking main-loop calls (GLib.MainLoop.run, Gio/Gtk.Application.run, Gtk.main) return immediately instead of blocking and don't return a value — so make the run call the last statement and exit from your handler:

app.on('activate', () => {
  // ...build the window...
  window.on('close-request', () => (loop.quit(), app.quit(), false));
  window.present();

  gi.startLoop();
  loop.run();      // returns immediately under ESM; do cleanup/exit in the handler
});

app.run([]);       // not `process.exit(app.run([]))` — the return value is unavailable

CommonJS (and signal callbacks) are unaffected. For the why and the design trade-off, see #449.

Documentation

Read our documentation here

TypeScript

node-gtk can generate TypeScript declarations for the libraries you use, straight from the GObject-Introspection typelibs installed on your machine — so the types always match your actual library versions and node-gtk's own runtime shape (camelCase methods, signal callbacks, nullability, etc.).

# generates ./node_modules/.node-gtk-types (a hidden, git-ignored cache)
npx node-gtk generate-types Gtk-4.0 Adw-1

The command emits one declaration file per namespace (plus the full dependency closure) and a node-gtk.d.ts shim. Point your tsconfig.json at it:

{
  "compilerOptions": {
    "moduleResolution": "node16",
    "paths": { "node-gtk": ["./node_modules/.node-gtk-types/node-gtk.d.ts"] }
  }
}

Then gi.require is fully typed — the namespace is inferred from the string arguments:

import * as gi from 'node-gtk'

const Gtk = gi.require('Gtk', '4.0')   // typed as the Gtk-4.0 namespace
const win = new Gtk.ApplicationWindow({ title: 'Hello', defaultWidth: 400 })
win.on('close-request', () => false)   // signal name + callback are typed

You get typed constructor properties (including inherited and interface ones), camelCase methods with real return types, GI nullability, typed signal overloads, enums, bigint for 64-bit integers, out-parameters surfaced as the return value, and cross-namespace types. GNOME's API documentation is included as JSDoc (with @param/@returns), so editors show it on hover — this reads the .gir files installed by the libraries' -dev/-devel packages; pass --no-docs for leaner output if they aren't installed or you don't want them.

Because the output is a generated cache under node_modules, add a postinstall script so it regenerates on install:

{ "scripts": { "postinstall": "node-gtk generate-types Gtk-4.0 Adw-1" } }

Run npx node-gtk generate-types --help for options.

Installing

  1. Install node-gtk itself
  2. Install the native libraries you use (see examples per platform below)
npm install node-gtk

# This installs a prebuilt binary when one is available for your platform and
# Node.js version, otherwise it falls back to building from source.

Linux

# archlinux
pacman -S gtk4

# ubuntu
apt install libgtk-4-1

macOS

brew install gtk4

Windows

Windows doesn't have the dependencies we need in a package manager, therefore node-gtk ships prebuilt versions of GTK 4 / Adwaita runtime (DLLs, typelibs, icons), so npm install node-gtk is all you need if your dependency is in our list of prebuilt libraries.

build from source

Building from source, or contributing? See Building from source.

Contributing

If you'd like to help, we'd be more than happy to have support. To setup your development environment, you can run npm run configure. You can then build the project with npm run build. To generate the compile_commands.json for LSP to work nicely, you can use bear as bear -- npm run build.

About

GTK bindings for NodeJS (via GObject introspection)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors