Preview HTML in Electron
Create a separate, disposable Electron shell for design review. Keep the original HTML as the editable source; do not convert it to React, move it into an Electron codebase, or require designers to edit generated files.
Resolve this Skill's directory from the loaded SKILL.md. Never assume where the Skill is installed.
Keep the boundary narrow
Use a directory that already works as a browser-deliverable static site and contains its HTML entry and assets. Plain multi-page prototypes are the primary case. A built static output is acceptable, but edits must be made in the directory configured as the live source.
The shell provides only:
- a native desktop window with either a standard system title bar or a native-controls overlay;
- a loopback-only local static server;
- automatic reload when source files change;
- DevTools on startup and standard reload/inspect shortcuts;
- secure renderer defaults with no Node.js access;
- an optional local package snapshot.
Do not add IPC, filesystem access, native menus, auto-update, authentication, backend services, signing, or release infrastructure unless the user separately requests them. Do not modify the prototype merely to generate a shell. If the user asks to adapt desktop window chrome, make the smallest changes in the original HTML/CSS and keep its browser preview usable.
Choose the window chrome
Use system for ordinary pages, unknown layouts, or prototypes without a dedicated top chrome area. It preserves the operating system's complete title bar and is the compatibility default.
Use native-overlay for App-shaped prototypes that own their top title bar or safe area. It removes the extra title strip while retaining native macOS traffic lights and Windows/Linux window controls. Before selecting or adapting this mode, read references/window-chrome.md completely.
Never infer business selectors such as .sidebar or inject fixed layout rules into arbitrary pages. The Electron shell owns native window behavior; the live HTML source owns spacing, colors, drag regions, and interactive controls.
Generate the preview shell
Determine an absolute source directory, a relative entry (default index.html), a new shell output directory outside the source, a product title, optional icon, window dimensions, and window chrome mode.
Run a dry run first:
node <skill-dir>/scripts/create-electron-app.mjs \
--source <html-prototype-dir> \
--output <new-preview-shell-dir> \
--name <kebab-case-name> \
--title "<window-title>" \
--entry index.html \
--chrome <system-or-native-overlay> \
--icon <optional-relative-icon-path> \
--dry-run
Check the reported live source, entry, output, title, icon, window size, and chrome mode, then rerun without --dry-run. Enable --spa only for a history-routed SPA; leave it off for multi-page HTML. For a custom overlay, use --chrome-height, --traffic-light-x, and --traffic-light-y only when the prototype's title-bar geometry requires them.
The generator must:
- leave the source unchanged;
- refuse an existing output or an output nested inside the source;
- store the absolute live-source link in
electron-dev.json; - copy an initial packaging snapshot into
site/without making it the editing target; - reject symlinks, credentials, private keys, and environment-secret files;
- keep
contextIsolation, Chromium sandboxing, web security, and navigation guards enabled; - expose only
data-runtime,data-platform, anddata-window-chromeDOM markers through the preload script.
Start the design loop
Require Node.js 22.12 or newer. Check node --version; use an already available newer runtime or report the prerequisite rather than ignoring EBADENGINE warnings.
Install once and launch the preview:
cd <new-preview-shell-dir>
npm install
npm start
npm start must serve the original source directory, open DevTools, and reload every open preview window when HTML, CSS, JavaScript, images, or other source assets change. The first run can download the Electron binary.
Tell the designer to keep editing only the original HTML directory. Do not edit site/; it is a generated snapshot. Use Cmd/Ctrl+R for a manual hard reload and Cmd+Option+I / Ctrl+Shift+I or F12 to toggle DevTools. If the source directory moves, update the absolute source field in electron-dev.json and run npm run verify.
For native-overlay, verify all of the following in the actual Electron window:
- Native window controls appear once and do not overlap product chrome.
- The source-owned title bar reserves the platform safe area.
- Empty title-bar space drags the window.
- Buttons, links, inputs, and other controls remain clickable through
app-region: no-drag. - Browser preview still works and may show source-owned simulated controls.
Debug prototype problems in this order:
- Check the Console for JavaScript, CSP, and network errors.
- Check the Network panel for missing assets and case-sensitive paths.
- Confirm that the configured entry and live-source directory are correct.
- Confirm whether the HTML expects a backend or development server that is outside this static-shell scope.
Avoid weakening Electron security settings to hide a prototype error.
Create an optional review snapshot
Only package when the user wants a locally openable snapshot. Packaging is not the primary design loop.
npm run package
npm run smoke:package
npm run package must first synchronize the current live source into site/, then create an unpacked app for the current OS. The smoke test must print ELECTRON_WRAPPER_SMOKE_OK and confirm the runtime/chrome DOM markers. Use npm run dist only when the user explicitly asks for an installer.
Treat the result as a local review artifact, not a signed production release. Do not claim cross-platform testing, signing, notarization, or installer validation unless each was actually performed.
Handoff
Report:
- the unchanged HTML source and generated shell paths;
- the command designers use for their daily loop (
npm start); - whether live reload and DevTools were verified;
- the configured title, entry, icon, window size, and chrome mode;
- whether native controls, drag, no-drag, and safe-area behavior were visually verified;
- optional package and smoke-test results separately;
- any backend-dependent behavior the static shell cannot reproduce.