# How Data Is Fetched and Managed in Stremio-Web Components: Web Worker Bridge Explained

> Discover how Stremio-web uses a Web Worker bridge to fetch and manage data efficiently. Learn how React components access immutable state and dispatch actions without UI thread blocking.

- Repository: [Stremio/stremio-web](https://github.com/Stremio/stremio-web)
- Tags: internals
- Published: 2026-05-23

---

**Stremio-web delegates all data operations to a Web Worker via a `CoreTransport` bridge, allowing React components to fetch immutable state snapshots and dispatch Redux-like actions without blocking the UI thread.**

Stremio-web is the official web frontend for the Stremio media center platform. Rather than managing state through traditional HTTP requests or client-side stores, stremio-web uses a Web Worker Bridge to communicate with `@stremio/stremio-core-web`. This architecture separates UI rendering from data management, ensuring the interface remains responsive while the core handles torrent parsing, API calls, and state mutations.

## Core Transport Layer: The Bridge to Stremio Core

The data fetching pipeline originates in [`src/core/createTransport.ts`](https://github.com/Stremio/stremio-web/blob/main/src/core/createTransport.ts), which constructs a `CoreTransport` object wrapping a Bridge instance. This transport forwards all communication to the Web Worker running the Stremio core logic.

The transport exposes five async methods via RPC-style calls:

- `init(args)` — initializes the core with configuration objects
- `getState(model)` — returns the current snapshot of a specific core model (e.g., `profile`, `library`, `streams`)
- `dispatch(action, model?)` — sends Redux-like actions to mutate core state
- `encodeStream / decodeStream` — helpers for stream URL encoding
- `analytics(event)` — transmits telemetry data

```typescript
// src/core/createTransport.ts
const createTransport = (): CoreTransport => {
    const init = (args: object) => bridge.call(['init'], [args]);
    const getState = (model: string) => bridge.call(['getState'], [model]);
    const dispatch = (action: DispatchAction, model?: string) =>
        bridge.call(['dispatch'], [action, model, location.hash]);
    // ... encodeStream, decodeStream, analytics implementations
    return { init, getState, dispatch, encodeStream, decodeStream, analytics };
};

```

Every method travels through `bridge.call`, which serializes requests and posts them to the Web Worker, keeping the main thread free for rendering.

## React Context Integration

To make the transport available throughout the component tree, stremio-web implements a React Context pattern defined in [`src/core/CoreContext.ts`](https://github.com/Stremio/stremio-web/blob/main/src/core/CoreContext.ts) and provided via [`src/core/CoreProvider.tsx`](https://github.com/Stremio/stremio-web/blob/main/src/core/CoreProvider.tsx).

The provider instantiates the transport exactly once using `React.useMemo`, ensuring a single Web Worker connection persists across the application lifecycle:

```tsx
// src/core/CoreProvider.tsx
const CoreProvider: React.FC = ({ children }) => {
    const transport = React.useMemo(createTransport, []);
    return (
        <CoreContext.Provider value={transport}>
            {children}
        </CoreContext.Provider>
    );
};

```

Components access this transport through the `useCore` hook ([`src/core/useCore.ts`](https://github.com/Stremio/stremio-web/blob/main/src/core/useCore.ts)), which consumes `CoreContext` and returns the transport instance. This pattern eliminates prop drilling and provides universal access to data fetching and action dispatching.

## Data-Fetching Hooks for UI Components

Stremio-web abstracts direct transport calls into reusable React hooks located in `src/common/`. These hooks manage subscription logic, re-rendering when models update, and proper cleanup on unmount.

### useModelState: The Generic Model Fetcher

The `useModelState` hook ([`src/common/useModelState.js`](https://github.com/Stremio/stremio-web/blob/main/src/common/useModelState.js)) is the primary mechanism for how data is fetched and managed in stremio-web components. It accepts a model name (e.g., `'library'`, `'recommendations'`, `'settings'`), calls `transport.getState(model)` on mount, and subscribes to subsequent updates broadcast from the Web Worker.

```javascript
// src/common/useModelState.js usage
import useModelState from '../common/useModelState';

const Library = () => {
    const library = useModelState('library'); // Calls transport.getState('library')
    if (!library) return null;
    return (
        <ul>
            {library.items.map(item => (
                <li key={item.id}>{item.title}</li>
            ))}
        </ul>
    );
};

```

### Specialized Hooks for Domain Models

For frequently accessed data, stremio-web provides specialized wrappers that enhance the base `useModelState` functionality:

- **`useProfile`** ([`src/common/useProfile.js`](https://github.com/Stremio/stremio-web/blob/main/src/common/useProfile.js)) — fetches the `profile` model and exposes convenience methods like `login()` and `logout()` that wrap dispatch calls
- **`useSettings`** — retrieves user preferences from the `settings` model
- **`useStreamingServer`** ([`src/common/useStreamingServer.js`](https://github.com/Stremio/stremio-web/blob/main/src/common/useStreamingServer.js)) — manages streaming server configuration and health checks
- **`usePlayUrl`** ([`src/common/usePlayUrl.ts`](https://github.com/Stremio/stremio-web/blob/main/src/common/usePlayUrl.ts)) — resolves playable URLs for specific streams by communicating with the core's stream resolution logic

These hooks follow a consistent pattern: they call `getState` for their respective models and return the immutable snapshot data to the consuming component.

## Dispatching Actions to Modify State

While fetching data handles read operations, user interactions require writing state back to the core. When users add items to their library, play streams, or modify settings, components dispatch actions through the transport.

Components obtain the `dispatch` function either directly from `useCore()` or from specialized hooks that wrap the transport:

```javascript
// Direct dispatch from component
import { useCore } from '../core/useCore';

function AddToLibraryButton({ item }) {
    const core = useCore(); // Accesses transport from CoreContext
    const handleClick = () => {
        core.dispatch({ type: 'ADD_TO_LIBRARY', payload: item });
    };
    return <button onClick={handleClick}>Add to library</button>;
}

```

The `dispatch` method forwards the action to `bridge.call(['dispatch'], [action, model, location.hash])`, which the Web Worker processes asynchronously. The core updates its internal state and broadcasts new snapshots to subscribed models, automatically triggering React re-renders in components using `useModelState` or similar hooks.

## Web Worker Lifecycle and Performance Characteristics

The Web Worker is instantiated exactly once via `new Worker(`${process.env.COMMIT_HASH}/scripts/worker.js`)` when `createTransport` first executes. All RPC traffic between the UI thread and the core runs through this single bridge instance.

This architecture provides specific performance benefits:

- **Non-blocking UI thread**: Heavy operations like torrent parsing, metadata fetching, and cryptographic operations execute in the worker thread
- **Immutable state snapshots**: The core maintains a single source of truth; components receive fresh snapshots via `getState` rather than mutable references
- **Selective subscriptions**: Components only re-render when their specific requested models update, not on every global state change

## Summary

- Stremio-web uses a **Web Worker Bridge** ([`src/core/createTransport.ts`](https://github.com/Stremio/stremio-web/blob/main/src/core/createTransport.ts)) to isolate core logic from the React UI thread
- The **CoreTransport** exposes `getState(model)` for reading data and `dispatch(action)` for mutations via RPC
- **React Context** ([`src/core/CoreProvider.tsx`](https://github.com/Stremio/stremio-web/blob/main/src/core/CoreProvider.tsx)) injects the transport into the component tree, accessed via `useCore()`
- **Custom hooks** like `useModelState` ([`src/common/useModelState.js`](https://github.com/Stremio/stremio-web/blob/main/src/common/useModelState.js)) and `useProfile` ([`src/common/useProfile.js`](https://github.com/Stremio/stremio-web/blob/main/src/common/useProfile.js)) wrap transport calls and manage model subscriptions
- All data fetching and state management occurs asynchronously through the Web Worker, ensuring the main thread remains responsive during intensive operations

## Frequently Asked Questions

### How does stremio-web fetch data without freezing the user interface?

Stremio-web instantiates a Web Worker that runs the Stremio core logic in a background thread. The [`createTransport.ts`](https://github.com/Stremio/stremio-web/blob/main/createTransport.ts) file establishes a bridge that forwards all `getState` and `dispatch` calls to this worker via `bridge.call`. Because the core executes off the main thread, expensive operations like parsing torrent streams or fetching metadata never block React's render cycle.

### What is the difference between `useCore` and `useModelState` in stremio-web?

`useCore()` ([`src/core/useCore.ts`](https://github.com/Stremio/stremio-web/blob/main/src/core/useCore.ts)) returns the raw `CoreTransport` object containing methods like `getState`, `dispatch`, and `analytics`. `useModelState` ([`src/common/useModelState.js`](https://github.com/Stremio/stremio-web/blob/main/src/common/useModelState.js)) is a higher-level hook that internally calls `useCore`, invokes `transport.getState(model)` for a specific model name, and manages the subscription lifecycle including cleanup. Most components should use `useModelState` or specialized hooks like `useProfile` rather than accessing the transport directly.

### Can components dispatch actions to multiple models simultaneously?

Yes. The `dispatch` method accepts an optional second parameter specifying the target model. When a component calls `core.dispatch({ type: 'PLAY', payload: stream })`, the transport forwards this action to the Web Worker, which routes it to the appropriate model handler. The core processes the update, modifies its internal state, and broadcasts changes back to any subscribed components listening to affected models.

### Where is the Web Worker initialized in the stremio-web source code?

The Web Worker is created inside the Bridge implementation when `createTransport` is first invoked, which occurs in [`src/core/CoreProvider.tsx`](https://github.com/Stremio/stremio-web/blob/main/src/core/CoreProvider.tsx) during the initial render. The worker script loads from `${process.env.COMMIT_HASH}/scripts/worker.js`. This single instance persists for the entire application lifetime, handling all RPC communication between the React UI and the Stremio core according to the implementation in [`src/core/createTransport.ts`](https://github.com/Stremio/stremio-web/blob/main/src/core/createTransport.ts).