> ## 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.

# Renderer frontend overview

> Understand the environment and boot sequence of the LynxHub extension frontend.

Extensions run inside the Electron renderer process. You can build rich user interfaces, listen to application events, inject custom page routes, and coordinate operations with the main process.

***

## Environment details

The LynxHub frontend uses the following stack:

* **UI library**: React
* **Styling**: Tailwind CSS v4
* **Component library**: HeroUI v3 (`@heroui/react`)

***

## Entrypoint configuration

Your extension frontend must build into `scripts/renderer/rendererEntry.mjs`. The host application loads this bundle dynamically during its boot sequence.

Your entrypoint file must export an `InitialExtensions` function. The host executes this function synchronously before mounting the React application tree:

```typescript theme={null}
import {ExtensionRendererApi} from '@lynx/plugins/extensions/types/api';
import {RendererIpcApi} from '@lynx/plugins/extensions/types/ipcWrapper';

export function InitialExtensions(lynxAPI: ExtensionRendererApi, rendererIpc: RendererIpcApi, extensionId: string): void {
  // Your frontend initialization logic here
}
```

### Initialization parameters

The initialization function receives three arguments:

1. `lynxAPI`: The main interface to inject components, manage routes, and customize default views.
2. `rendererIpc`: A type-safe IPC wrapper to communicate with the extension's backend process.
3. `extensionId`: A unique, stable identifier assigned to your extension.

***

## Central state management

If your extension requires shared global state, you can register Redux slice reducers. Call the `addReducer` method during initialization:

```typescript theme={null}
import {createSlice} from '@reduxjs/toolkit';

const mySlice = createSlice({
  name: 'myExtensionState',
  initialState: {count: 0},
  reducers: {
    increment: state => {
      state.count += 1;
    },
  },
});

export function InitialExtensions(lynxAPI) {
  lynxAPI.addReducer([
    {
      name: 'myExtension',
      reducer: mySlice.reducer,
    },
  ]);
}
```

Components loaded in the application can consume this state using standard `useSelector` and `useDispatch` hooks.

***

## Global React hooks

You can run global React logic by registering custom hook components. Call the `addCustomHook` method:

```typescript theme={null}
import {useEffect} from 'react';

function MyCustomHook() {
  useEffect(() => {
    console.log('Extension custom hook mounted globally');
  }, []);

  return null;
}

export function InitialExtensions(lynxAPI) {
  lynxAPI.addCustomHook(MyCustomHook);
}
```

The host application mounts registered custom hooks at the root of the React tree. This makes them ideal for background listeners, telemetry, or window-level hotkey managers.

***

## Production error tracking

You can initialize Sentry to capture frontend exceptions. Call `initBrowserSentry` with your DSN:

```typescript theme={null}
export function InitialExtensions(lynxAPI) {
  const scope = lynxAPI.initBrowserSentry('https://your-sentry-dsn@sentry.io/project');
  scope.setTag('extension_mode', 'production');
}
```
