Use Webwin in your project
Everything the demos are built on ships as a standalone library beside them. No package registry, no build step required, and no runtime dependencies — copy the files, or load them straight off this site.
The files
| File | What it is |
|---|---|
| webwin.js | ES module — the main entry: desktop, windows, all the controls, themes, flares |
| webwin-gaming.js | ES module — the HUD widget set (webwin/gaming) |
| webwin-engine2d.js | ES module — the 2D scene graph and sprite renderer |
| webwin-engine3d.js | ES module — the 3D scene graph and mesh pipeline |
webwin-shared-*.js |
Code the entries above share. Not imported directly — but copy them |
| webwin.global.js | Classic script — defines window.Webwin. Core only |
| types/ | TypeScript declarations, mirroring the source tree |
webwin-shared-*.js chunks, which they import by relative path. That
sharing is what makes a gaming widget and a core control the same class at
runtime, so instanceof tells the truth.
As ES modules
<canvas id="desktop"></canvas>
<script type="module">
import { Desktop, ModernTheme, Window, Button }
from "https://jetsonsoft.com/Webwin/lib/webwin.js";
const desktop = await Desktop.create(document.getElementById("desktop"), {
theme: new ModernTheme("light"),
});
const win = new Window({ title: "Hello", x: 40, y: 40, width: 320, height: 180 });
win.controls.add(new Button({ x: 16, y: 16, width: 88, height: 30, text: "OK" }));
desktop.addWindow(win);
</script>
A bundler-based project imports the same files by path. If you re-bundle, do not
mark the package sideEffects: false — the flare and glyph registries
are populated at import time, and dropping those modules would leave nothing to
look up.
As a script tag
<canvas id="desktop"></canvas>
<script src="https://jetsonsoft.com/Webwin/lib/webwin.global.js"></script>
<script>
const desktop = await Webwin.Desktop.create(
document.getElementById("desktop"),
{ theme: new Webwin.ModernTheme("dark") },
);
</script>
The global build is core only, deliberately. A classic script cannot share code across files, so shipping one per entry would give each its own copy of the shared core — and a page loading two would end up with duplicate classes and forked registries. If you need the HUD or an engine, use the ES modules.
TypeScript
Copy lib/types/ alongside the bundles and point at it:
{
"compilerOptions": {
"paths": {
"webwin": ["./vendor/webwin/types/index.d.ts"],
"webwin/gaming": ["./vendor/webwin/types/gaming/index.d.ts"],
"webwin/engine2d": ["./vendor/webwin/types/engine2d/index.d.ts"],
"webwin/engine3d": ["./vendor/webwin/types/engine3d/index.d.ts"]
}
}
}
Before you start
Webwin requires WebGPU. That is the main thing to plan for:
Desktop.create rejects with GpuUnavailableError where the
browser or machine cannot supply a device, and your app is expected to catch it and
show its own fallback — the same way every page here does.
Two smaller things. The canvas owns its own input and text rendering, so do not try
to overlay DOM widgets on it. And glyph rasterisation caches by font face, so
await document.fonts.ready before the first frame if your page uses a
webfont — otherwise the atlas caches the fallback.