js-gnome-apps
GNOME JavaScript (GJS) Application Development
Technology Stack
| Component | Purpose |
|---|---|
| GJS | JavaScript runtime (SpiderMonkey) with GObject Introspection bindings |
| GTK 4 | UI toolkit |
| Libadwaita (Adw) 1.x | GNOME-specific widgets, adaptive layouts, styling |
| GLib / GIO | Core utilities, async I/O, settings, D-Bus, file operations |
| Meson | Build system |
| Flatpak | App packaging and distribution |
| Blueprint (optional) | Declarative UI markup that compiles to GTK XML |
Imports (ES Modules — required for new code)
// Built-in GJS modules
import Cairo from "cairo";
import Gettext from "gettext";
import System from "system";
// Platform libraries via gi:// URI
import GLib from "gi://GLib";
import GObject from "gi://GObject";
import Gio from "gi://Gio";
// Versioned imports (required when multiple API versions exist)
import Gtk from "gi://Gtk?version=4.0";
import Adw from "gi://Adw?version=1";
// Relative user modules (include .js extension)
import * as Utils from "./lib/utils.js";
Keep imports grouped: built-in → platform (gi://) → local, separated by blank lines. Use PascalCase for imported modules.
GObject Subclassing
Register every GObject subclass with GObject.registerClass(). Use constructor() (not _init(), which is legacy pre-GNOME 42).
const MyWidget = GObject.registerClass(
{
GTypeName: "MyWidget",
Template: "resource:///com/example/MyApp/my-widget.ui",
InternalChildren: ["title_label", "action_button"],
Properties: {
"example-prop": GObject.ParamSpec.string(
"example-prop",
"",
"",
GObject.ParamFlags.READWRITE,
null,
),
},
Signals: {
"item-selected": {
param_types: [GObject.TYPE_STRING],
},
},
},
class MyWidget extends Gtk.Box {
constructor(params = {}) {
super(params);
// Template children: this._title_label, this._action_button
}
get example_prop() {
return this._example_prop ?? null;
}
set example_prop(value) {
if (this.example_prop === value) return;
this._example_prop = value;
this.notify("example-prop");
}
},
);
Key rules:
- Property names:
kebab-casein GObject declarations,snake_casein JS accessors - Always call
this.notify('prop-name')in setters to emit change notifications GTypeNameis optional unless the type is referenced in UI XML<template class="...">InternalChildrenmapsidattrs in UI XML →this._childId;Children→this.childId
Application Entry Point
import GLib from "gi://GLib";
import GObject from "gi://GObject";
import Gio from "gi://Gio";
import Gtk from "gi://Gtk?version=4.0";
import Adw from "gi://Adw?version=1";
import { MyAppWindow } from "./window.js";
const MyApp = GObject.registerClass(
class MyApp extends Adw.Application {
constructor() {
super({
application_id: "com.example.MyApp",
flags: Gio.ApplicationFlags.DEFAULT_FLAGS,
});
const quitAction = new Gio.SimpleAction({ name: "quit" });
quitAction.connect("activate", () => this.quit());
this.add_action(quitAction);
this.set_accels_for_action("app.quit", ["<Primary>q"]);
}
vfunc_activate() {
let win = this.active_window;
if (!win) win = new MyAppWindow(this);
win.present();
}
},
);
const app = new MyApp();
app.run([System.programInvocationName, ...ARGV]);
Async with Gio._promisify
Wrap *_async/*_finish pairs once at module level for async/await usage:
Gio._promisify(
Gio.File.prototype,
"load_contents_async",
"load_contents_finish",
);
const file = Gio.File.new_for_path("/tmp/example.txt");
try {
const [contents] = await file.load_contents_async(null);
const text = new TextDecoder().decode(contents);
} catch (e) {
logError(e, "Failed to load file");
}
Code Style (GJS conventions)
- 4-space indentation, single quotes, semicolons
constby default,letwhen mutation needed, nevervar- File names:
lowerCamelCase.js; directories:lowercase - Arrow functions for inline callbacks;
.bind(this)for method references exportfor public API, nevervar
Reference Files
Consult these based on the task at hand:
- Project setup & packaging: references/project-setup.md — Meson build, Flatpak manifests, GResource, application ID, desktop files, GSettings schemas, directory layout
- UI design (GTK4 + Libadwaita): references/ui-patterns.md — Widget templates (UI XML), adaptive layouts (breakpoints, split views, view switcher), boxed lists, style classes, header bars, GNOME HIG patterns
- GIO & platform patterns: references/gio-patterns.md — File I/O, GSettings, actions & menus, D-Bus, subprocesses, list models, GVariant
More from padparadscho/skills
rs-ratatui-crate
Build terminal user interfaces (TUIs) in Rust with Ratatui (v0.30). Use this skill whenever working with the ratatui crate for creating interactive terminal applications, including: (1) Setting up a new Ratatui project, (2) Creating or modifying terminal UI layouts, (3) Implementing widgets (lists, tables, charts, text, gauges, etc.), (4) Handling keyboard/mouse input and events, (5) Structuring TUI application architecture (TEA, component-based, or monolithic patterns), (6) Writing custom widgets, (7) Managing application state in a TUI context, (8) Terminal setup/teardown and panic handling, (9) Testing TUI rendering with TestBackend. Also triggers for questions about crossterm event handling in a Ratatui context, tui-input, tui-textarea, or any ratatui-* ecosystem crate.
22js-gnome-extensions
Build, debug, and maintain GNOME Shell extensions using GJS (GNOME JavaScript). Covers extension anatomy (metadata.json, extension.js, prefs.js, stylesheet.css), ESModule imports, GSettings preferences, popup menus, quick settings, panel indicators, dialogs, notifications, search providers, translations, and session modes. Use when the user wants to: (1) Create a new GNOME Shell extension, (2) Add UI elements like panel buttons, popup menus, quick settings toggles/sliders, or modal dialogs, (3) Implement extension preferences with GTK4/Adwaita, (4) Debug or test an extension, (5) Port an extension to a newer GNOME Shell version (45-49+), (6) Prepare an extension for submission to extensions.gnome.org, (7) Work with GNOME Shell internal APIs (Clutter, St, Meta, Shell, Main).
7js-stellar-sdk
Guide for building applications with the Stellar JS SDK (@stellar/stellar-sdk). Use when working with the Stellar blockchain in JavaScript/TypeScript — including sending payments, creating accounts, issuing assets, managing trustlines, trading on the DEX, querying Horizon, interacting with Stellar RPC, streaming events, building and signing transactions, multisig, claimable balances, sponsored reserves, SEP-10 auth, federation, fee-bump transactions, and interacting with Soroban smart contracts via the JS SDK. Covers all @stellar/stellar-sdk usage patterns (Horizon module, rpc module, contract module, TransactionBuilder, Keypair, Operation, Asset, etc.).
5rs-soroban-sdk
Expert guidance for building smart contracts on Stellar using the Soroban Rust SDK. Use this skill when working with Soroban smart contracts for tasks including (1) creating new contracts with [contract] and [contractimpl] attributes, (2) implementing storage with Persistent, Temporary, or Instance storage types, (3) working with auth contexts and authorization, (4) handling tokens and Stellar Asset Contracts, (5) writing tests with testutils, (6) deploying contracts, (7) working with events and logging, (8) using crypto functions, (9) debugging contract errors, (10) security best practices and vulnerability prevention, (11) avoiding common security pitfalls like missing authorization, integer overflow, or reinitialization attacks.
5js-stronghold-sdk
Guide for integrating and building with the Stronghold Pay JS SDK and REST API for payment processing. Use when working with Stronghold Pay payment integration, accepting ACH/bank debit payments, linking bank accounts, creating charges/tips, generating PayLinks, or building checkout flows — in sandbox or live environments. Covers Stronghold.Pay.JS drop-in UI, REST API v2 endpoints, PayLink hosted payment pages, customer token management, and payment source handling.
3rs-yew-crate
Expert guidance for building Rust + WebAssembly frontend web applications using the Yew framework (v0.22). Use when creating, modifying, debugging, or architecting Yew applications — including function components, hooks, props, routing, contexts, events, server-side rendering, agents, and Suspense. Covers project setup with Trunk, the html! macro, state management, data fetching, and integration with the broader Yew/WASM ecosystem (yew-router, gloo, wasm-bindgen, web-sys, stylist, yewdux).
2