# Fabric.Desktop A **self-contained** Electron desktop app for Fabric. It bundles the `Fabric.Frontend` SPA inside the package and loads it locally over `file://` — no separate frontend web server is needed. It still talks to the Center/Guild **backends** over HTTP (the Center base is set on the login screen, so the desktop app points at whatever host runs the backends). ## How it works - `npm run build:renderer` builds `Fabric.Frontend` with a relative asset base (`build:desktop`) and copies the bundle into `renderer/`. - `main.js` loads `renderer/index.html` in production (falls back to `offline.html` if the bundle is missing); dev mode loads `FABRIC_DESKTOP_URL` (default `http://localhost:5173`). - Security baseline: `contextIsolation` + `sandbox`, no arbitrary new windows/navigation; `preload` exposes a small IPC allowlist (`fabric:config:get|set`, `fabric:notify`). - System tray (show/hide window, quit) with the Fabric tray icon; app/window icons use the Fabric mark. ## Develop ```bash npm install npm run start:dev # expects Fabric.Frontend dev server at :5173 # or, against the bundled renderer: npm run build:renderer && npm start ``` ## Build / package ```bash npm install npm run pack # unpacked dir (no installer) npm run dist:linux # AppImage, deb, tar.gz -> dist/ npm run dist:mac # dmg, zip npm run dist:win # nsis, zip ``` Each `dist:*`/`pack` runs `build:renderer` first (so `Fabric.Frontend` must be present beside this submodule, which it is in the `Fabric` checkout). Output goes to `dist/` (git-ignored). `productName` is **Fabric** so the app installs to `/opt/Fabric/` (a space there breaks Electron's sandbox); the launcher is still labelled "Fabric Desktop". Linux icons are generated from `build/icons/`. ## Notes - The bundled SPA uses `HashRouter` under `file://` (no server for the History API). The Center/Guild backends are HTTP and CORS-allow the Electron `file://` origin (`null`).