Electron desktop app (system tray agent) built with Vue 2 + Vuetify 2 + Vuex + webpack. Pending migration: Vue 2 → Vue 3, Vuetify 2 → Vuetify 3, Vuex → Pinia, webpack → electron-vite.
The Vue 2 build is crusty — deprecation warnings are expected. Don't try to get a clean reference build from the old codebase. Instead treat the configs below as the source of truth for what the new build must produce.
| Platform | Format | Architectures |
|---|---|---|
| Linux | .deb |
x64, arm64, armv7l |
| Linux | .rpm |
x64, arm64 |
| Windows | NSIS installer (.exe) |
x64 |
| macOS | .pkg |
(built separately) |
Build commands (from build.sh):
npm run electron:build # x64 deb + rpm + win
npm run electron:build -- --linux rpm --arm64 --dir # arm64 rpm
npm run electron:build -- --linux deb --arm64 --dir # arm64 deb
npm run electron:build -- --linux deb --armv7l --dir # armv7l deb (Pi)- Signing is done via a custom
sign.js(not electron-builder's built-in signing) - Tool:
signtool.exeatC:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe - Certificate: subject name
"Nettica Corporation", thumbprintCBB53B9D617593941E91E50AD9E51A9FD3700838 - Timestamp server:
http://ts.ssl.com(RFC 3161) - Config in
electron-builder.json:"sign": "sign.js" - Windows build must be done on a Windows machine —
sign.jscallssigntool.exe sign.jshandles both string and objectexecutablePath(Electron passes an object)
| Old | New |
|---|---|
vue@^2.6.14 |
vue@^3.x |
vuetify@^2.6.0 |
vuetify@^3.x |
vuex@^3.6.2 + vuex-electron |
pinia |
vue-router@^3.5.1 |
vue-router@^4.x |
vue-cli-service |
electron-vite |
vue-cli-plugin-electron-builder@^2.1.1 |
electron-vite or vite-plugin-electron |
vue-cli-plugin-vuetify~2.5.8 |
vite-plugin-vuetify |
vue-template-compiler |
(removed — not needed in Vue 3) |
vuetify-loader@^1 |
vuetify-loader@^2 or vite-plugin-vuetify |
webpack / webpack-cli etc. |
(removed — handled by vite) |
Other notable deps to evaluate:
vuex-electron— handles Vuex state persistence across main/renderer; replace with Pinia +pinia-plugin-persistedstateorelectron-store@electron/remote— check usage; modern Electron preferscontextBridge/ipcRenderervue-d3-network— Vue 2 only; check for Vue 3 fork or replace (nettica-admin used a direct D3 component)vue-apexcharts— has a Vue 3 version (vue3-apexcharts)electron@^27— check if upgrade needed alongside vite tooling
hidden-xs-only→d-none d-sm-flexhidden-sm-and-up→d-flex d-sm-none- Nav drawer: add
temporaryprop to prevent auto-opening at lg breakpoint - Theme:
theme.global.name.value = 'dark'→theme.change('dark') - Breakpoints: use
useDisplay()composable instead of$vuetify.breakpoint
- Delete
src/store/directory, createsrc/stores/*.jsindividual store files - Use
storeToRefs(store)to destructure reactive refs vuex-electronstate sync across processes needs a Pinia equivalent
<tr>must be child of<tbody>, not direct child of<table>
// WRONG — shared counter skips indices
let child = 0
items[i].children[child++] = { ... } // child keeps incrementing across parents!
// RIGHT
items[i].children.push({ ... })Replace <table><tr><td><v-switch></td></tr></table> with:
<div style="display:flex; flex-wrap:wrap; gap:0 16px;">
<div style="display:flex; flex-direction:column; flex:1 1 180px; min-width:0;">
<v-switch ... />
</div>
<div style="display:flex; flex-direction:column; flex:1 1 180px; min-width:0;">
<v-switch ... />
</div>
</div>- Route
"/"with no component: usecomponent: { render: () => null } router.beforeEachguard: checkmeta.requiresAuth, storeintendedRoute
The NSIS installer (build/installer.nsh) bundles and installs two additional components:
extra/wireguard-amd64-0.6.1.msi— installed silently viaMsiExec.exe /i ... DO_NOT_LAUNCH=1 /qnextra/wireguard-amd64-0.5.3.msi— old version, kept only to detect and uninstall it if present- Already signed by the WireGuard team — no action needed
extra/nettica-client.exe— the WireGuard tunnel manager service- Must be signed with the Nettica certificate (same
sign.js/ signtool process as the main installer) - Installed as a Windows service:
nettica-client.exe installthennettica-client.exe start - Uninstall:
nettica-client.exe stopthennettica-client.exe remove - On install, creates
%APPDATA%\Nettica\and%APPDATA%\Nettica\WireGuard\directories
If old WireGuard v1.0.20210914 is detected, the installer:
- Stops and removes nettica-client service
- Uninstalls old WireGuard MSI
- Sets reboot flag
- Proceeds with fresh install
This part of the process is unlikely to change during the Vue 2 → 3 migration — it lives entirely in build/installer.nsh and electron-builder.json (nsis.include), independent of the Vue/Electron tooling.
Currently only x64 is shipped for Windows. arm64 Windows (Surface Pro X, Snapdragon laptops) is a growing target.
- Electron ships pre-built arm64 binaries for Windows
electron-buildercan target--win --arm64from a Linux build machine — no Windows arm64 hardware needed- The main Electron app itself should cross-compile cleanly
- Go cross-compilation to
windows/arm64is fully supported:GOOS=windows GOARCH=arm64 go build -o nettica-client-arm64.exe . - No special toolchain needed beyond standard Go
- WireGuard does ship arm64 MSIs — check https://download.wireguard.com/windows-client/ for
wireguard-arm64-x.x.x.msi - Would need a separate
extra/set for arm64:wireguard-arm64-x.x.x.msi+nettica-client-arm64.exe
sign.jsusessigntool.exewhich requires the Windows machine — arm64.exefiles still need to be signed there- Both
nettica-client-arm64.exeand the arm64 Electron executable would need signing - This is the main blocker for fully automated arm64 Windows builds from Linux
- NSIS itself is x64 but generates installers that can install arm64 binaries
- Would need a separate installer target in
electron-builder.jsonfor arm64 Windows, or a fat installer that detects arch at install time
Cross-compilation from Linux is feasible for the app and nettica-client. The signing step still requires the Windows machine regardless of architecture. Treat Windows arm64 as a post-migration stretch goal once x64 is stable.
- main/renderer split: Vue runs in renderer; verify IPC patterns still work after tooling change
- contextBridge: audit use of
@electron/remote— consider migrating tocontextBridge+ preload - electron-vite config: must explicitly list all Linux cross-compile targets (x64, arm64, armv7l)
- Code signing:
sign.jsmust be re-wired into the new build config; test on Windows machine electron-settings: persists app settings to disk — verify it still works with new renderer setupauto-launch: OS-level startup registration — test on each platform after migration