English · 简体中文
A high-performance desktop shell for webapps — turn any webapp into a real desktop app.
Once loaded, your webapp feels like a desktop application, not a remote-controlled browser: every browser artifact is stripped away, while frame timing, VRAM usage and GPU state are measured continuously and reported the moment they cross a threshold.
- Feels like an app, not a browser — no address bar, no tabs, no context menu. Window identity (title, icon, size, background) is declared by your webapp itself; no white flash, no URL in the title
- Performance you can see — a custom title bar shows live
FPS / MS / CPU / MEM;F12opens a standalone Inspector with frame timing, VRAM accounting, draw calls, per-process resources and GPU state - Built for demanding apps — GPU profiles (
balanced/max-perf/compat), full frame rate even when unfocused, one-shot renderer teardown/rebuild (purge), and detection of silent fallback to software rendering - One protocol, three shapes — a single
deskapp.jsonmanifest drives local projects, exported standalone apps, and purpose-built bundles through the same code path - Managed backend processes — starts your dev server, polls until it's ready, and tears down the whole process tree on exit; an already-running service is reused, never killed
- Secure by default — local content is served over the
app://scheme; manifest commands require native confirmation before their first run; CORS is opened only for origins the project declared - Built-in benchmark + CI gate —
--smokequantifies frame rate, VRAM and long frames, then sets the exit code from your thresholds - Packaging for all three platforms — macOS (
dmg), Windows (nsis), Linux (AppImage/deb)
All three platforms share one code path. The table below reflects what has actually been tested on real hardware, not what is intended to work:
| macOS | Windows | Linux | |
|---|---|---|---|
| Loading · metrics · Inspector | ✅ verified | ✅ verified | |
| Custom title bar (icon + live metrics + blur) | ✅ vibrancy | ✅ acrylic | ➖ always native title bar |
| Managed backend · process-tree teardown | ✅ process-group signals | ✅ taskkill /T |
|
--export standalone app |
✅ verified | ✅ verified | |
| Adopting the page icon as the app icon | ✅ rewrites .icns |
➖ runtime window icon only | ➖ runtime window icon only |
| Installers | dmg · zip | nsis · zip | AppImage · deb |
Linux always uses the native title bar. titleBarStyle has no effect there, so a custom bar
would stack underneath the native one and produce a double title bar. The cost is that
FPS / MS / CPU / MEM are not visible in the title bar — press F12 and read them in the
Inspector instead. The metrics themselves are unaffected.
pnpm install
pnpm buildDo not put the repository on an exFAT volume. Two things break there:
pnpm installfails withERR_PNPM_EISDIR(the default layout needs symlinks, which exFAT does not support), andpnpm dist:*fails withEPERM: rename 'win-unpacked.tmp' -> 'win-unpacked'. Use NTFS / APFS / ext4. If you only need dependencies installed,pnpm install --node-linker=hoistedalso works.
Load a local build output:
pnpm start -- /path/to/your/webapp/distLoad a dev server:
pnpm start -- http://localhost:5173Start with no argument to open the project picker:
pnpm startAny directory containing an index.html just works. Add a deskapp.json to declare the window
and any services it needs:
Export a project as a double-clickable standalone app (without --out it lands in the project's
own apps/<device>/):
electron . --export <project-dir> --out <output-dir>The documents below are written in Chinese.
- docs/PROTOCOL.md — the project protocol and API in full (complete manifest, the
window.deskappsurface, CLI flags, packaging) - docs/ARCHITECTURE.md — architecture and design decisions (accounting semantics, frame-rate statistics, performance profiles, security posture)
pnpm typecheck # type-check both tsconfigs
pnpm selftest # build, then run the bundled benchmark and assert frame rateBuilding installers: see docs/PROTOCOL.md → 出安装包
This is a personal project with a single maintainer and limited time, so external pull requests aren't being accepted for now. That's not a lack of interest — I simply can't promise timely reviews, or commit to maintaining someone else's code long-term.
If you want to build something on top of it, please do fork it. The MIT license lets you use it however you need, including commercially and in closed-source work, with no need to ask.
{ "version": 1, "name": "My Project", "entry": "index.html", "window": { "width": 1280, "height": 720, "minWidth": 720, "minHeight": 480, "background": "#0a0d12", "resizable": true }, "runtime": { "profile": "balanced", "vramLimitMB": 400 }, "command": { "run": "npm run serve", // long-running service, started for you "readyUrl": "http://127.0.0.1:5173/", // page loads only once this responds "readyTimeoutMs": 90000 }, "hooks": { "startup": "pnpm install", // runs before loading "shutdown": "./scripts/cleanup.sh" // runs on exit } }