Intro
This tutorial will walk you through creating a Gtk4 application from scratch using Gnim. Before jumping in, you are expected to know TypeScript or at least JavaScript.
JavaScript Runtime
The JavaScript runtime Gnim uses is GJS. It is built on Firefox's SpiderMonkey JavaScript engine and the GNOME platform libraries.
IMPORTANT
GJS is not Node, not Deno, and not Bun. GJS does not implement some common Web APIs you might be used to from these other runtimes such as fetch
. The standard library of GJS comes from GLib
, Gio
and GObject
which are libraries written in C and exposed to GJS through FFI using GObject Introspection
Development Environment
For setting up a development environment you will need the following dependencies installed:
- gjs
- gtk4
- JavaScript package manager of your choice
sudo pacman -Syu gjs gtk4 npm
sudo dnf install gjs-devel gtk4-devel npm
sudo apt install libgjs-dev libgtk-3-dev npm
# flake.nix
{
inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
outputs = {
self,
nixpkgs,
}: let
forAllSystems = nixpkgs.lib.genAttrs ["x86_64-linux" "aarch64-linux"];
in {
devShells = forAllSystems (system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
# enter this shell using `nix develop`
default = pkgs.mkShell {
packages = with pkgs; [
gobject-introspection
glib
nodePackages.npm
gtk4
gjs
];
};
});
};
}
Since GJS does not support node_modules
we have to use a bundler. For this tutorial we will use esbuild
which you can either install using your system package manager or npm
. You also have to configure tsconfig.json
which will tell the bundler about the environment and JSX runtime.
init a directory
shmkdir gnim-app cd gnim-app npm install gnim npm install typescript esbuild @girs/gtk-4.0 @girs/gjs -D
configure
tsconfig.json
json{ "compilerOptions": { "target": "ES2020", "module": "ES2022", "lib": ["ES2024"], "outDir": "dist", "strict": true, "moduleResolution": "Bundler", "skipLibCheck": true, "jsx": "react-jsx", "jsxImportSource": "gnim/gtk4" } }
by convention, source files go in the
src
directoryshmkdir src
create an
env.d.ts
filetsimport "@girs/gtk-4.0" import "@girs/gjs" import "@girs/gjs/dom"
create the entry point
tsconsole.log("hello world")
write a build script
sh# scripts/build.sh esbuild --bundle src/main.ts \ --outdir=dist \ --external:gi://* \ --external:resource://* \ --external:system \ --external:gettext \ --format=esm \ --sourcemap=inline
Finally, your project structure should like like this:
.
├── node_modules
├── package-lock.json
├── package.json
├── scripts
│ └── build.sh
├── src
│ ├── env.d.ts
│ └── main.ts
└── tsconfig.json
To make running the project easier you can add a dev
script in package.json
.
{
"scripts": {
"dev": "bash scripts/build.sh ; gjs -m dist/main.js"
},
"dependencies": {},
"devDependencies": {}
}
Running the project then will consist of this short command:
npm run dev