> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lynxhub.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Module architecture

> Understand the architecture and integration model of LynxHub modules.

LynxHub modules represent standalone features or AI engines, represented as **cards** in the interface. Unlike extensions (which dynamically hook into the main shell's React tree), modules are isolated packages running self-contained tools, backing terminal processes, and configuration menus.

***

## Process separation

Modules divide execution between the Electron Main process and the Renderer process to ensure backend reliability and interface responsiveness:

```mermaid theme={null}
graph TD
    subgraph Electron Main Process (Node.js)
        HostMain[Host Main Process] <-->|IPC Channels| ModuleMain["Module Main (TypeScript Source)"]
        ModuleMain -->|Compiled / Bundled| MainBundle["scripts/main.mjs"]
    end
    subgraph Electron Renderer Process (Chromium)
        HostRenderer[Host React Shell] <-->|lynxplugin:// Protocol| ModuleRenderer["Module Renderer (TypeScript Source)"]
        ModuleRenderer -->|Compiled / Bundled| RendererBundle["scripts/renderer.mjs"]
    end
```

### Main process

The main process coordinates the installation, update checks, uninstallation, and execution of backing terminal commands (such as executing Python scripts or starting a local model binary via `node-pty`).

* **Entrypoint**: `src/main.ts` (compiled and bundled to `scripts/main.mjs` as an ES module).
* **Responsibility**: Exposes backend lifecycle hooks and commands for execution.
* **Signature**:

  ```typescript theme={null}
  import {MainModules, MainModuleUtils} from '../../src/common/types/plugins/modules';

  export default async function initialModule(utils: MainModuleUtils): Promise<MainModules[]> {
    return [
      {
        id: 'my-card-id',
        methods: () => ({
          getRunCommands: async () => {
            return 'python main.py';
          },
          // Other optional methods
          readArgs: async () => { ... },
          saveArgs: async (args) => { ... },
          isInstalled: async () => { ... },
          uninstall: async () => { ... },
          mainIpc: () => { ... }
        }),
      },
    ];
  }
  ```

### Renderer process

The renderer process handles card visualization, settings/argument configuration forms, and installation wizard steppers.

* **Entrypoint**: `src/renderer.ts` (compiled and bundled to `scripts/renderer.mjs` as an ES module).
* **Responsibility**: Registers card UI layouts, defines category mappings, and specifies custom argument inputs.
* **Signature**:

  ```typescript theme={null}
  import {CardModules} from '../../src/common/types/plugins/modules';

  const rendererModules: CardModules = [
    {
      routePath: 'imageGen_page', // placement target (e.g. 'imageGen_page', 'textGen_page', etc.)
      cards: [
        {
          id: 'my-card-id',
          title: 'My Card',
          description: 'Description...',
          repoUrl: 'https://github.com/my-username/my-card-repo',
          type: 'image',
          supportCustomArguments: true,
          arguments: comfyuiArguments,
          methods: {
            catchAddress: (line: string) => { ... },
            parseArgsToString: (args: ChosenArgument[]) => { ... },
            parseStringToArgs: (args: string) => { ... },
            cardInfo: (api, callback) => { ... },
            manager: {
              startInstall: (stepper: InstallationStepper) => { ... },
              updater: {
                updateType: 'git',
              },
            },
          },
          installationType: 'git',
        },
      ],
    },
  ];

  export default rendererModules;
  ```

***

## Boot and loading sequence

LynxHub performs the following steps to load modules during application startup:

```mermaid theme={null}
sequenceDiagram
    participant App as App Lifecycle
    participant MM as ModuleManager
    participant Disk as AppData Plugins Folder
    participant Main as Module Main (main.mjs)
    participant Rend as Module Renderer (renderer.mjs)

    App->>MM: Initialize module manager
    MM->>Disk: Scan and validate plugin folders
    Note over MM: Filters out disabled cards
    MM->>Main: Import module main script
    MM->>Main: Call initialModule(utils)
    Note over Main: Cache returned methods
    App->>MM: Main window ready-to-show
    MM->>Main: Invoke mainIpc() handlers
    App->>Rend: Import renderer.mjs via lynxplugin://
    Note over Rend: Aggregate cards for React router routes
```

### 1. Discovery and validation

During startup, the host scans folders inside the `Plugins/` directory. It ensures that required files exist before loading a module.

### 2. Import and aggregation

The host imports the backend entrypoint `scripts/main.mjs`. It calls `initialModule` and registers card-specific backend operations. The frontend then dynamically loads `scripts/renderer.mjs` using the custom protocol to display card components.

***

## Custom plugin protocol (lynxplugin://)

Modern browsers and Chromium engines prevent loading assets or scripts directly from the local file system (`file://` URLs) due to security restrictions.

To resolve this safely, LynxHub registers a custom protocol handler at boot:

* **Protocol**: `lynxplugin://`
* **Hostname mapping**: The hostname corresponds to the plugin folder ID.
* **Path mapping**: The path maps directly to files under `<AppData>/Plugins/<id>/<path>`.

***

## Host card state management

When card modules run, the host application manages their states internally. Module developers do not need to write state management code. The host aggregates card states using its internal stores:

```mermaid theme={null}
graph LR
    Redux[Host Redux: cards.runningCard] -->|Coordinates| HostShell[Host Shell UI]
    HostShell -->|Mounts| CardInstance[Card Instance]
    CardInstance <-->|Reads/Writes| Zustand[Host Zustand Store: store.ts]
```

### Host Zustand store (local)

The host maintains a Zustand store for each mounted card instance to handle interface updates:

* Tracking selected arguments.
* Monitoring installation and compiler progress.
* Streaming active terminal outputs.
* Displaying loading states.

### Host Redux store (global)

The host updates its central Redux store when cards launch or close, allowing navigation bars and panels to track active processes.

***

## Rollup build configuration

To compile and package your module correctly, configure Rollup to output ES modules. Below is the standard Rollup configuration (`rollup.config.mjs`) used by the module template:

```typescript theme={null}
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import nodeResolve from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';

/** @type {import('rollup').RollupOptions} */
const config = {
  input: ['module/src/main.ts', 'module/src/renderer.ts'],
  output: {
    dir: 'module_out/scripts',
    format: 'es',
    entryFileNames: '[name].mjs',
    chunkFileNames: '[name]_[hash:6].mjs',
  },
  external: ['electron'],
  plugins: [json(), typescript({tsconfig: 'module/tsconfig.json'}), nodeResolve(), commonjs()],
};

export default config;
```

Make sure to externalize any Node.js dependencies (such as `electron`) in your build config for the main script so they are not bundled.

***

## Development vs. production environments

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

| Feature                   | Development mode                            | Production mode                            |
| :------------------------ | :------------------------------------------ | :----------------------------------------- |
| **Main entry import**     | `module/src/main` (TypeScript Source)       | `scripts/main.mjs` (ES module)             |
| **Renderer entry import** | `@lynx_module/renderer` (Vite alias)        | `scripts/renderer.mjs` (custom protocol)   |
| **Loading mechanism**     | Hot-imported from local source folder       | Served via `lynxplugin://` protocol        |
| **Updates**               | Hot Module Replacement (HMR) instantly      | Requires a build and app restart           |
| **Location**              | Root `/module` directory of the application | `<AppData>/Plugins/<module-id>/` directory |

### Development mode

During development, the host redirects module loading to local aliases to support instant code updates:

* **Renderer**: `@lynx_module/renderer` (pointing to `/module/src/renderer`)
* **Main**: `module/src/main`

### Production mode

In production:

* **Validation**: LynxHub scans folders inside the `Plugins` directory. It ensures that `scripts/main.mjs` and `scripts/renderer.mjs` exist before loading.
* **Filtering**: Disabled cards (`plugin.disabledCards`) are filtered out early in both processes so they are never loaded into memory.
