Skip to content

GJSify

Node.js & Web APIs,
running on GJS

Bring the full TypeScript ecosystem to GJS: fs, net, http, fetch, WebSocket, Canvas2D, WebGL and more, all running natively on Linux.

Terminal
$ gjs -m express-webserver.js
Express.js blog running on GJS
Local: http://localhost:3000/
API: http://localhost:3000/api/posts
Press Ctrl+C to stop
[12:34:56] GET /
[12:34:56] GET /style.css
[12:34:56] GET /app.js
[12:34:56] GET /api/runtime
[12:34:56] GET /api/posts
express-webserver.ts
import '@gjsify/node-globals';
import express from 'express';
import { posts } from './data/posts.js';
const app = express();
app.use(express.json());
app.get('/api/posts', (_req, res) => {
res.json({ count: posts.length, posts });
});
app.get('/api/posts/:slug', (req, res) => {
const post = posts.find((p) => p.slug === req.params.slug);
if (!post) return res.status(404).json({ error: 'Not found' });
res.json(post);
});
app.use(express.static('public'));
app.listen(3000, () => {
console.log('Express server running at http://localhost:3000');
});
Full example →
Terminal
npx @gjsify/cli showcase express-webserver
pixel-demo.ts
import Adw from 'gi://Adw?version=1';
import { WebGLBridge } from '@gjsify/webgl';
import * as THREE from 'three';
import { RenderPixelatedPass } from 'three/addons/postprocessing/RenderPixelatedPass.js';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
const app = new Adw.Application({ application_id: 'gjsify.examples.pixel' });
app.connect('activate', () => {
const glArea = new WebGLBridge();
glArea.onReady((canvas) => {
const renderer = new THREE.WebGLRenderer({ canvas });
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera();
const composer = new EffectComposer(renderer);
composer.addPass(new RenderPixelatedPass(6, scene, camera));
});
});
Full example →
Terminal
npx @gjsify/cli showcase three-postprocessing-pixel
teapot-demo.ts
import Adw from 'gi://Adw?version=1';
import { WebGLBridge } from '@gjsify/webgl';
import * as THREE from 'three';
import { TeapotGeometry } from 'three/addons/geometries/TeapotGeometry.js';
const app = new Adw.Application({ application_id: 'gjsify.examples.teapot' });
app.connect('activate', () => {
const glArea = new WebGLBridge();
glArea.onReady((canvas) => {
const renderer = new THREE.WebGLRenderer({ canvas });
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45);
scene.add(new THREE.Mesh(
new TeapotGeometry(50, 20),
new THREE.MeshPhongMaterial({ color: 0xc0c0c0 })
));
});
});
Full example →
Terminal
npx @gjsify/cli showcase three-geometry-teapot
jelly-jumper.ts
import Adw from 'gi://Adw?version=1';
import { WebGLBridge } from '@gjsify/webgl';
import * as ex from 'excalibur';
import { startGame } from './game.js';
const app = new Adw.Application({
application_id: 'gjsify.examples.jelly-jumper',
});
app.connect('activate', () => {
const glArea = new WebGLBridge();
glArea.onReady(async (canvas) => {
const game = await startGame(canvas);
// game.mute(); // toggle audio
// game.pause(); // toggle pause
});
});
Full example →
Terminal
npx @gjsify/cli showcase excalibur-jelly-jumper
fireworks.ts
import Adw from 'gi://Adw?version=1';
import { Canvas2DBridge } from '@gjsify/canvas2d';
import { start } from './fireworks.js';
const app = new Adw.Application({ application_id: 'gjsify.examples.fireworks' });
app.connect('activate', () => {
const canvasWidget = new Canvas2DBridge();
canvasWidget.installGlobals();
canvasWidget.onReady((canvas) => {
const demo = start(canvas);
// demo.effectController.particleCount = 60;
// demo.effectController.autoInterval = 150;
});
});
Full example →
Terminal
npx @gjsify/cli showcase canvas2d-fireworks

Get started in seconds

Terminal
$ npx @gjsify/cli create my-app

or run npx @gjsify/cli --help to explore all commands