A native Windows desktop application for the Phlix Media Server, built with Electron, Vue 3, and TypeScript. The user interface is provided by the shared @phlix/ui Vue app; this repo is a thin Electron shell + consumer.
Phlix Windows provides a full-featured media server client for Windows, enabling users to browse, stream, and manage their media library with native desktop integration including system tray, media keys, and native menus. The entire renderer UI is the shared @phlix/ui app booted via createPhlixApp(config), so screens and theming stay in sync with the other Phlix clients.
- Media Library Browser - Browse and search your media collection (provided by
@phlix/ui) - Video Player - Full-featured video playback with controls
- System Tray Integration - Minimize to tray with media controls
- Native Menus - Full application menu with keyboard shortcuts
- Media Key Support - Play/Pause, Stop, and Rewind/Fast-Forward (±10s) are bridged from the tray/menu into the player (Open File is temporarily a no-op, pending local-file support in the shared player)
- Authentication - Secure login with session persistence (handled by
@phlix/ui) - Shared UI - Modern Vue 3 interface from
@phlix/uiwith the Nocturne theme - Settings Management - Configurable preferences including minimize-to-tray behavior
- Hub Mode - Connect to a Phlix Hub to manage multiple servers, with support for direct-LAN and relay connection modes
Temporarily dropped in the Vue migration: the offline Downloads and realtime SyncPlay UIs were removed and will be re-added later as shared
@phlix/uiseams.
Before setting up the project, ensure you have the following installed:
- Node.js v18.x or later (LTS recommended)
- npm v9.x or later (comes with Node.js)
- Git for version control
- Windows 10/11 as the target platform
For development:
- Visual Studio Code (recommended) with extensions:
- ESLint
- Prettier
- TypeScript and related tools
-
Clone the repository
git clone https://github.com/phlix/phlix-windows.git cd phlix-windows -
Install dependencies
npm install
-
Configure environment (optional)
Create a
.envfile in the root directory if you need a custom default server URL (used as the build-time fallback when no server URL is persisted and Hub mode is not configured):VITE_PHLIX_SERVER_URL=http://localhost:8096
The application stores configuration in the user's app data directory:
- Windows:
%APPDATA%\phlix-windows
| Setting (electron-store key) | Default | Description |
|---|---|---|
minimizeToTray |
true |
Minimize to system tray instead of closing |
serverUrl |
(none) | Persisted direct media server URL (app:get/set-server-url) |
deviceId |
Auto-generated | Stable per-install device id windows-<uuid> (app:get-device-id) |
| Variable | Default | Description |
|---|---|---|
VITE_PHLIX_SERVER_URL |
http://localhost:8096 |
Build-time fallback media server URL (used when no serverUrl is persisted and Hub mode is off) |
NODE_ENV |
development |
Runtime environment |
Hub mode is configured at runtime (persisted via hub:set-config in electron-store), not via an environment variable — see the Hub Mode section below.
Run the application in development mode with hot reload:
npm run devThis starts:
- Vite dev server on
http://localhost:5173 - Electron app with automatic reload on changes
Build both renderer and main process:
npm run buildBuild only the renderer (Vue app):
npm run build:viteBuild only the main process (Electron):
npm run build:electronPackage the app for Windows distribution:
NSIS Installer (recommended):
npm run packageWindows Store (APPX):
npm run package:storeThe packaged output will be in the release/ directory.
# Run all tests
npm test
# Run tests in watch mode
npm test -- --watch
# Run tests with coverage
npm test -- --coverage- Unit tests located in
tests/unit/(22 tests):resolveConfig.test.ts,electronBridge.test.ts,main.test.ts - Test files use Vitest (
jsdom,@vitejs/plugin-vue) with TypeScript - Coverage via
@vitest/coverage-v8; the Electronsrc/main/**andsrc/preload/**glue is excluded
# Run ESLint (flat config: eslint.config.mjs)
npm run lint
# Fix auto-fixable issues
npm run lint:fix
# Typecheck the renderer (Vue) and the Electron main/preload
npx vue-tsc --noEmit
npx tsc -p tsconfig.main.json --noEmitphlix-windows/
├── src/
│ ├── main/ # Electron main process
│ │ └── index.ts # Main entry point, window management, IPC, tray
│ ├── preload/ # Preload script (context bridge)
│ │ └── index.ts # Secure IPC exposure to renderer
│ └── renderer/ # Thin @phlix/ui consumer (no local pages/components/stores)
│ ├── main.ts # Entry: boot() → createPhlixApp() → mount → installElectronBridge
│ ├── resolveConfig.ts # Pure app-mode + apiBase resolution (hub vs direct server)
│ ├── electronBridge.ts # Maps Electron media/window IPC → @phlix/ui player store + router
│ ├── index.html # Mounts #phlix-app
│ ├── test-setup.ts # jsdom localStorage mock
│ ├── vite-env.d.ts
│ └── types/electron.d.ts
├── tests/
│ └── unit/ # resolveConfig.test.ts · electronBridge.test.ts · main.test.ts (22 tests)
├── build/ # Build resources (icons)
├── release/ # Packaged application output (gitignored)
├── package.json
├── vite.config.mts
├── vitest.config.mts
├── eslint.config.mjs
└── tsconfig.json
-
Main Process (
src/main/index.ts)- Creates BrowserWindow
- Manages system tray and menus
- Handles IPC from renderer (incl.
app:get-server-url/app:set-server-url/app:get-device-id) - Manages app lifecycle
-
Preload Script (
src/preload/index.ts)- Exposes safe APIs via contextBridge (incl.
getServerUrl/setServerUrl/getDeviceId) - Provides IPC invoke/send methods
- Relays media control events to the renderer
- Exposes safe APIs via contextBridge (incl.
-
Renderer Process (
src/renderer/)- A thin consumer of the shared
@phlix/uiVue app, booted viacreatePhlixApp(config) - Vue 3 + Pinia + vue-router (peer deps of
@phlix/ui) - Pinned to
@phlix/ui#v0.51.0and@phlix/contracts#v0.1.1 - Vite (
@vitejs/plugin-vue) for development and bundling
- A thin consumer of the shared
All screens, navigation, theming, and state live in the shared @phlix/ui app (Pinia stores + vue-router). This repo does not define its own pages, components, or stores. Configuration passed to createPhlixApp (app-mode, apiBase, deviceHeaders, theme, branding) is resolved at boot from Electron config; device headers are built with @phlix/contracts buildPhlixHeaders. Electron tray/menu events are bridged into @phlix/ui's player store and router by src/renderer/electronBridge.ts.
The project uses GitHub Actions for continuous integration:
- test.yml - Runs on every push/PR to validate code
- build.yml - Creates releases on tags and publishes packages
- Update version in
package.json - Create git tag:
git tag -a v1.0.0 -m "Release v1.0.0" git push origin v1.0.0 - GitHub Actions will automatically:
- Run tests
- Build the application
- Create GitHub Release
- Upload artifacts
The build workflow produces:
- NSIS Installer - Traditional
.exeinstaller - APPX Package - For Windows Store distribution
Hub Mode allows you to connect to a Phlix Hub to manage and access multiple Phlix servers through a single interface. This is useful for users with servers in different locations or network environments.
- Hub Authentication - Sign in to your Phlix Hub account
- Server Switcher - Quickly switch between your claimed servers
- Connection Modes:
- Direct - Connect directly to servers via LAN for lowest latency
- Relay - Route traffic through the hub for remote access
- Session Persistence - Hub session persists across app restarts
Hub configuration is persisted at runtime in electron-store (via the hub:set-config IPC) — there is
no environment variable for it. At boot, resolveAppConfig runs the app in hub mode (against
hub.hubUrl) whenever a Hub URL is configured and the connection mode is not explicitly direct;
otherwise it runs in server mode against the persisted direct server URL.
- Open Settings
- Navigate to Hub Mode section
- Enter your Hub URL
- Sign in with your Hub credentials
- Select a server from your claimed servers list
- Choose connection mode (Direct or Relay)
- User configures Hub URL and signs in; the choice is persisted via
hub:set-config - On next boot,
resolveAppConfigselects hub vs direct server mode and theapiBase - App fetches the list of claimed servers from the Hub (via
@phlix/ui) - API calls route through direct-LAN or hub-relay based on the chosen mode
- Active server and connection mode persist across sessions
App doesn't start:
- Ensure Node.js 18+ is installed
- Run
npm installto install dependencies - Check console for error messages
Vite server port conflict:
- Kill processes using port 5173
- Modify
vite.config.tsto use a different port
Build fails with native modules:
- Run
npm rebuildto rebuild native dependencies - Ensure electron-builder is up to date
Application logs are stored in:
- Windows:
%APPDATA%\phlix-windows\logs\
Use electron-log for runtime logging:
import log from 'electron-log';
log.info('Application started');MIT License - see project repository for details.
For issues and feature requests, please use the GitHub issue tracker.