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 npmsudo dnf install gjs-devel gtk4-devel npmsudo 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 -Dconfigure
tsconfig.jsonjson{ "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
srcdirectoryshmkdir srccreate an
env.d.tsfiletsimport "@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.jsonTo 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