Skip to content
wcposPublic

About

Electron Desktop App for WooCommerce POS

Topics

Resources

Security policy

Stars

18 stars

Watchers

1 watching

Forks

Repository files navigation

WCPOS

WCPOS Desktop

The WooCommerce POS desktop client for Windows, macOS and Linux.

Build & Publish Tests Latest release License: MIT Discord Chat

About  —  How it works  —  Development  —  Building  —  Download

💡 About

WCPOS Desktop is the Electron shell that packages the cross-platform WooCommerce POS client as a native desktop app. It wraps the shared React Native / Expo web app (@wcpos/main) and adds the native capabilities a point-of-sale terminal needs but a browser cannot provide:

  • Receipt printing to USB, serial and network (ESC/POS) printers, plus the system print dialog.
  • Printer discovery on the local network via Bonjour/mDNS.
  • Local-first data stored on disk by RxDB's filesystem-node storage in the main process, exposed to the renderer over an IPC storage bridge.
  • OAuth deep-linking via a custom wcpos:// protocol handler.
  • Auto-updates delivered straight from GitHub releases.

WCPOS requires WooCommerce and the WooCommerce POS plugin for WordPress as its backend. This repository builds and ships the desktop installers — see the latest release to download.

🛠 How it works

The app is split across Electron's three process types. The renderer is the WCPOS Expo web build — in development it points at the local Expo dev server, and in production it serves the static expo export bundle from disk via electron-serve under the wcpos:// scheme. The main process owns all native integrations and talks to the renderer over a tightly whitelisted preload bridge.

flowchart LR
    subgraph Renderer["Renderer — @wcpos/main (Expo web)"]
      UI["POS UI"]
    end
    subgraph Preload["Preload (context-isolated bridge)"]
      IPC["whitelisted ipcRenderer\nsend / invoke / on"]
    end
    subgraph Main["Main process (src/index.ts)"]
      DB["RxDB storage bridge\n(filesystem-node)"]
      PRINT["Printing\nUSB · Serial · TCP/ESC-POS · system"]
      DISCO["Printer discovery\n(Bonjour / mDNS)"]
      PROTO["wcpos:// protocol\n(OAuth deep links)"]
      UPD["Auto-updater"]
      HTTP["HTTP bridge (net.fetch)\n+ image cache"]
    end
    UI <--> IPC
    IPC <--> DB & PRINT & DISCO & PROTO & UPD & HTTP
Loading

Communication is locked down for security: contextIsolation is on, nodeIntegration is off, and src/preload.ts only forwards an explicit allow-list of IPC channels (e.g. rxStorage, http-request, print-raw-tcp, printer-discovery, auth:prompt).

Key native services

Area Files Notes
App bootstrap src/index.ts Window lifecycle, power-monitor events, startup sequence
Storage src/main/rxdb-storage.ts RxDB v17 over getRxStorageFilesystemNode, served to the renderer via the RxDB remote IPC bridge (with attachment serialization and targeted corruption recovery)
Printing src/main/print-raw-tcp.ts, src/main/usb-printer.ts, src/main/serial-printer.ts, src/main/winspool-printer.ts, src/main/print-external-url.ts Raw ESC/POS over TCP, USB and serial; Windows USB routes through the print spooler
Discovery src/main/printer-discovery.ts, src/main/bluetooth-select.ts mDNS network printer discovery and Bluetooth device selection
Networking src/main/http-bridge.ts, src/main/image-cache.ts The http-request IPC channel over Chromium net.fetch (axios-shaped payloads — the renderer's client library is axios) and image caching
Auth src/main/auth-handler.ts, src/main/protocol.ts wcpos:// deep-link handling for OAuth flows
Updates src/main/update.ts Checks https://updates.wcpos.com and applies GitHub release assets
Shell src/main/window.ts, src/main/menu/ Browser window and native application menus

📁 Project structure

src/
  index.ts            # Main-process entry point
  preload.ts          # Context-isolated IPC bridge (renderer <-> main)
  renderer.ts         # Renderer entry (loads the Expo web bundle)
  main/               # Main-process services (storage, printing, auth, update, …)
    menu/             # Native application menu definitions
    translations/     # Bundled i18n strings for native chrome (menus, dialogs)
forge.config.ts       # Electron Forge: packaging, makers, publishers, signing
webpack.*.config.ts   # Webpack config for the main & renderer bundles
icons/                # App icons per platform (.ico / .icns / .png / .svg)
flathub/              # Flathub manifest & metadata for the Linux Flatpak

👩‍💻 Development

This repo is standalone, no longer a submodule. The renderer (@wcpos/main) is built in a separate WCPOS monorepo checkout; this repo only consumes its prebuilt export in dist/ for packaging.

Prerequisites

  • Node.js 22+
  • pnpm (the version is pinned via packageManager in package.json)
  • Platform build tools for native modules (usb, serialport) — Xcode CLT on macOS, build-essential/libudev on Linux, the relevant MSVC toolchain on Windows
  • An RxDB Premium license token (the app depends on rxdb-premium). CI injects it into package.json under accessTokens["rxdb-premium"]; do the same locally for installs to succeed.

Run the app

In the monorepo checkout, start the renderer (port 8088, with ELECTRON=true):

pnpm dev:electron-renderer

In this repo, in a separate terminal:

pnpm install
pnpm rebuild:all
pnpm dev

Electron loads http://localhost:8088; override its port with EXPO_PORT to match the renderer server.

Useful scripts

Script Description
pnpm dev Launch Electron against the separately running renderer
pnpm lint / pnpm lint:fix Lint the src/ tree
pnpm ts:check Type-check with tsc --noEmit
pnpm test Run the main/preload test suite (see below)
pnpm rebuild:all Rebuild usb for Electron
pnpm package Package the app without producing installers
pnpm make Build platform installers
pnpm publish-app Build and publish a release to GitHub

🧪 Testing

Tests are lightweight ts-node scripts that exercise the main-process and preload logic without a full Electron runtime. pnpm test runs them all:

  • test:preload — IPC channel allow-listing
  • test:rxdb-ipc-attachments — RxDB attachment serialization over IPC
  • test:image-cache — image cache behaviour
  • test:printer-discovery / test:bluetooth-select — discovery and device selection
  • test:winspool-printer / test:serial-printer — Windows spooler and serial printing
  • test:package-runtime-externals — verifies runtime-external native deps are bundled

CI (.github/workflows/test.yml) runs pnpm lint, tsc, and pnpm test on every push and PR to main.

📦 Building & packaging

Packaging is driven by Electron Forge (forge.config.ts). Because the UI is built separately, a production build is a two-step process:

  1. Build the renderer in the monorepo, then import its export into this repo's dist/:
    # In the monorepo checkout
    pnpm --filter @wcpos/main build:electron
    # In this repo (replace <monorepo> with your checkout path)
    pnpm renderer:import <monorepo>/apps/main/electron-build
    Forge bundles dist/ into the app via extraResource, and electron-serve serves it under wcpos://.
  2. Make the installers:
    pnpm make

Targets

Platform Maker Output
Windows Squirrel .exe installer
macOS DMG + ZIP signed & notarized .dmg / .zip
Linux Deb / Rpm .deb, .rpm
Linux Flatpak Flatpak bundle / Flathub (opt-in via WCPOS_FLATPAK=1)

🚀 Releases & auto-update

The desktop build's renderer comes from wcpos/monorepo at the ref in .monorepo-ref; bump it in the same PR as the version bump.

Pushes to main trigger the Publish workflow: it builds the Expo renderer, then builds, signs and publishes platform installers to GitHub Releases. Installed apps check for updates against https://updates.wcpos.com and apply new release assets in place. Changes are tracked in CHANGELOG.md.

🤝 Contributing

Issues and pull requests are welcome. Please run pnpm lint, pnpm ts:check and pnpm test before opening a PR. Project-specific agent and review guidelines live in AGENTS.md.

🔗 Links

📄 License

MIT © Paul Kilmurray

About

Electron Desktop App for WooCommerce POS

Topics

Resources

Security policy

Stars

18 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages