This guide walks you through creating a node-with-window app from scratch using nww-forge.
- Node.js 18+
- PowerShell 5.1 and .NET Framework 4.8 (pre-installed on Windows 10/11)
- WebView2 runtime (pre-installed on Windows 11; download for Windows 10)
- Node.js 18+
- GJS, GTK 4, WebKitGTK 6.0
sudo apt install gjs gir1.2-gtk-4.0 gir1.2-webkit-6.0npx @devscholar/nww-forge init my-app
cd my-appThis creates the project directory, installs dependencies, and downloads WebView2 DLLs on Windows.
To use TypeScript instead:
npx @devscholar/nww-forge init my-app --template=vanilla-tsmy-app/
├── forge.config.js # nww-forge configuration
├── main.js # main process entry point
├── preload.js # preload script (contextBridge)
├── renderer.js # renderer-side JavaScript
├── index.html # app UI
├── style.css
└── package.json
npm startThis runs nww-forge start, which executes main.js directly with Node.js.
main.js — the main process, runs in Node.js:
import { app, BrowserWindow, ipcMain } from '@devscholar/node-with-window';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
app.on('ready', () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
contextIsolation: true,
preload: path.join(__dirname, 'preload.js'),
},
});
win.loadFile(path.join(__dirname, 'index.html'));
});preload.js — runs before the renderer, has access to ipcRenderer:
const { contextBridge, ipcRenderer } = require('@devscholar/node-with-window');
contextBridge.exposeInMainWorld('api', {
send: (channel, ...args) => ipcRenderer.send(channel, ...args),
invoke: (channel, ...args) => ipcRenderer.invoke(channel, ...args),
on: (channel, listener) => ipcRenderer.on(channel, listener),
});renderer.js — runs in the browser context, uses only what preload.js exposed:
window.api.send('ping', 'hello');npm run makeOutput: out/make/my-app-<version>-<platform>-<arch>.zip
The zip contains a folder bundle with a launch.bat (Windows) or launch.sh (Linux) that runs the app with Node.js. The target machine must have Node.js installed.
- Edit
index.htmlandrenderer.jsto build your UI - Add
ipcMain.on/ipcMain.handlehandlers inmain.js - See the Electron IPC docs — the API is the same
- See node-with-window-examples for more complete examples