This file provides guidance to WARP (warp.dev) when working with code in this repository.
- The app expects Tailscale to be installed and running (the main process calls the
tailscaleCLI).
npm install
npm run dev- Runs the Vite dev server (
npm run dev:renderer) and then launches Electron (npm run dev:main). - Renderer dev server is expected at
http://localhost:5173.
- Runs the Vite dev server (
Useful sub-commands:
npm run dev:renderer(Vite only)npm run dev:main(Electron only)
-
npm run buildvite buildoutputs the renderer bundle todist/(seevite.config.js).electron-builderpackages the Electron app and writes artifacts todist-electron/.
-
npm run preview(preview the Vite build)
npx electron-builder --win --x64
- Creating/pushing a tag matching
v*triggers.github/workflows/release.yml(Windows build + GitHub Release). - There is a one-off helper script for the 4.0.4 release:
scripts/release-4.0.4.ps1.
node scripts/create-ico.js(generatesassets/icon.icofromassets/icon.png)
- There are currently no
lint/testscripts inpackage.json.
Poly-Hub is an Electron app with:
- Main process (Node/Electron): networking, file IO, persistence, auto-update, global shortcuts.
- Renderer (React + Vite): UI, routing, and calling main-process functionality via IPC.
src/main/main.js: Electron entrypoint (creates windows, registers IPC handlers, starts the peer server, manages overlay/notifications, sets up auto-updater in production).src/main/preload.js: the IPC bridge exposed aswindow.electronAPI(all renderer→main calls should go through here).src/renderer/main.jsx: renderer entrypoint; usesHashRouter.src/renderer/App.jsx: top-level app shell; routes and initial bootstrapping (profile load, Tailscale status, theme/settings application).
- Routes are defined in
src/renderer/App.jsx:#/gallery#/settings
- Onboarding (Tailscale check + profile creation) is shown when no profile exists.
- There is a standalone pairing UI in
src/renderer/pages/Discovery.jsx, but current navigation is driven from the Settings page/Sidebar.
- Renderer calls into main via
window.electronAPI.*(defined insrc/main/preload.js). - Main pushes events back to renderer with IPC events like:
peer:added,peer:updatedfile:received,file:deleted,file:progress,file:blocked,file:auto-added
When adding a new capability, the usual flow is:
- Add an
ipcMain.handle(...)(oripcMain.on(...)) handler insrc/main/main.js. - Expose it in
src/main/preload.js. - Consume it from the renderer via
window.electronAPI.
src/main/store.jswrapselectron-store.- Stores:
profile,peers,sharedFiles,settings.
- Stores:
- Default sync folder is created under the user’s Documents:
Documents/PolyHub(set/used insrc/main/main.js).
polyhub-file://is registered in the main process to allow the renderer to load thumbnails/icons from disk.- Pairing links are encoded as
polyhub://pair/<base64url(json)>(generated/parsed insrc/main/main.js).
src/main/peerServer.jsimplements TCP servers:- 47777: control messages (JSON) for pairing, delete, profile updates.
- 47778: streaming file transfer (4-byte header length + JSON header + raw bytes).
src/main/tailscale.jsshells out to the Tailscale CLI (tailscale ip -4,tailscale status --json) to detect connectivity + the100.x.x.xTailscale IP.
- UI selects files/folders → renderer calls
window.electronAPI.shareFiles(...)/shareFolder(...). - Main copies files into the configured sync folder, adds metadata to
electron-store, then sends the file to each peer over port 47778. - Receiving side writes to sync folder and emits
file:progressandfile:receivedevents back to the renderer.
src/main/main.jscreates additional windows besides the main BrowserWindow:- Overlay (
src/main/overlay.html): a global “quick drop” target toggled via a global shortcut (defaultAlt+D). - Notification overlay (
src/main/notification-overlay.html): per-file accept/decline UI when limits are exceeded.
- Overlay (
src/main/autoUpdater.jsconfigureselectron-updaterto pull releases from GitHub (Starbug10/Poly-Hub).- In production (
app.isPackaged), the updater is initialized fromsrc/main/main.js.
- Vite config (
vite.config.js):root: 'src/renderer'- build output:
dist/(relative to repo root) - alias:
@→src/renderer
- Electron production load path is
dist/index.html(seesrc/main/main.js).