Skip to main content
LynxHub extensions are dynamic plugins designed to integrate with the core application. They allow you to customize the shell UI, add routes, inject Redux reducers, listen to application events, and add system tray menu items.

Process separation

LynxHub operates on a multi-process architecture based on Electron. Your extension runs code in two separate processes:

Main process

The main process runs in a Node.js environment. It has full access to operating system APIs.
  • Entrypoint: src/main/lynxExtension.ts (compiled and bundled to scripts/main/mainEntry.cjs as a CommonJS module).
  • Responsibility: Listens to system-level lifecycles, registers global IPC channels, adds tray menu items, and launches background processes (e.g., via node-pty).
  • Signature:

Renderer process

The renderer process displays the graphical interface and runs in a Chromium browser window.
  • Entrypoint: src/renderer/Extension.tsx (compiled and bundled to scripts/renderer/rendererEntry.mjs as an ES module).
  • Responsibility: Injects React UI components into predefined slots (Title Bar, Status Bar, Settings, Sidebar), adds custom pages/routes, and hooks into state management.
  • Signature:

Boot and loading sequence

LynxHub follows a structured sequence when loading extensions during application startup:

1. Discovery and validation

During startup, the host scans the app Plugins/ folder. It checks for a valid subdirectory containing metadata.json and the required entrypoint files.

2. Main process initialization

The host imports the backend entrypoint of the extension. It calls the exported initialExtension function and passes the API wrappers. At this point, the extension registers callbacks for subsequent lifecycle events.

3. Application ready hook

When Electron completes its initialization, the host invokes all registered onAppReady callbacks.

4. IPC channel setup

The host registers core IPC handlers. It then triggers listenForChannels callbacks. This allows your extension to register custom IPC event handlers.

5. Main window display

When the main application window is ready to be shown, the host triggers onReadyToShow callbacks.

Module Federation in the renderer

LynxHub uses Module Federation via @originjs/vite-plugin-federation to dynamically mount extension interfaces in production. This approach avoids rebuilding the host application.

Runtime loading flow

  1. Discovery: The host requests the active plugin addresses from the main process over IPC.
  2. Registration: For each active extension, the host registers its remote entry URL (<address>/scripts/renderer/rendererEntry.mjs) using the Virtual Module Federation API:
  3. Mounting: The host dynamically loads the entry component using __federation_method_getRemote(extensionId, 'Extension') and calls the InitialExtensions initializer.

Shared packages

To prevent loading duplicate library instances and to ensure shared context is maintained, the host shares core packages with all extensions:
  • react and react-dom
  • react-redux
  • @heroui/react (HeroUI v3 React components)
  • @heroui/styles (HeroUI v3 styling tokens)
  • react-aria (React accessibility hooks)
Any package listed above loads from the host shell. Your extension must treat these as peer dependencies. You must configure them as shared in your Vite configuration.

Vite build configuration

To build your extension correctly for LynxHub, configure @originjs/vite-plugin-federation and electron-vite in your electron.vite.config.ts configuration. Below is the standard configuration structure used by the template:

Development vs. production environments

LynxHub provides two separate loading strategies to optimize the developer experience:

Development mode

To bypass Module Federation and speed up updates, the host process attempts to hot-import the extension directly from your local source directory using the Vite alias:
  • Renderer: @lynx_extension/renderer/Extension (mapped to /extension/src/renderer)
  • Main: extension/src/main/lynxExtension
This allows you to benefit from Hot Module Replacement (HMR). You can see UI changes instantly without building or deploying.

Production mode

In production, LynxHub launches local servers for installed extensions. It loads their entry files from disk:
  • Validation: LynxHub verifies the directory structure under <AppData>/Plugins/<id>/. It ensures scripts/main/mainEntry.cjs and scripts/renderer/rendererEntry.mjs exist.
  • Protocol: Static assets and entrypoints are served locally and registered as Module Federation remotes.
Last modified on June 21, 2026