App.js and distributed to the component tree through React context.
ServicesContext pattern
All services are held in a plain object passed toServicesProvider (src/services/ServicesContext/ServicesProvider.js):
useServices hook:
ServicesContext itself is a plain React.createContext({}). There is no Provider abstraction beyond ServicesProvider — the context value is the services object directly.
Service lifecycle
All five services follow the same lifecycle contract:| State | Meaning |
|---|---|
starting: true | start() called, transport initialising |
active: true | Transport ready, service operational |
error: Error | Transport failed, service non-functional |
App.js starts all services inside a useEffect and stops them on cleanup:
App.js listens for stateChanged on Core and Shell to set the initialized flag that gates rendering. The app renders a blank screen until both Core and Shell have settled (active or errored).
Core
File:src/services/Core/Core.js
Manages the lifecycle of the WASM core and exposes a transport for all communication.
Properties
| Property | Type | Description |
|---|---|---|
active | boolean | true when the transport is initialised and ready |
error | Error | null | Set if transport initialisation failed |
starting | boolean | true while the transport is initialising |
transport | CoreTransport | null | The active transport instance |
CoreTransport
File:src/services/Core/CoreTransport.js
CoreTransport spawns a Web Worker (worker.js) and wraps the @stremio/stremio-core-web/bridge interface.
| Method | Signature | Description |
|---|---|---|
dispatch | (action, field) | Send an action to a core model. field scopes the action to a specific model instance. |
getState | (field) → Promise | Fetch the current state of a model. |
getDebugState | () → Promise | Fetch the full debug state of the core. |
analytics | (event) | Send an analytics event with the current hash path. |
decodeStream | (stream) → Promise | Decode a stream descriptor string. |
transport:
| Event | Payload | Description |
|---|---|---|
NewState | string[] | List of model names whose state changed |
CoreEvent | { event, args } | Named domain event (e.g. SettingsUpdated) |
core:
| Event | Description |
|---|---|
stateChanged | Fired when active, error, or starting changes |
Window focus sync
When the browser window regains focus and Core is active,App.js dispatches four sync actions:
PullAddonsFromAPIPullUserFromAPISyncLibraryWithAPIPullNotifications
Shell
File:src/services/Shell/Shell.js
Bridges the native Qt desktop shell when Stremio Web runs inside the Stremio desktop application. In browser-only deployments the transport fails to initialise and shell.error is set, but the app continues running.
ShellTransport
File:src/services/Shell/ShellTransport.js
Uses window.qt.webChannelTransport (a Qt WebChannel) to communicate with the host application over a JSON message protocol.
- On init, sends a
QtMsgTypes.initmessage and waits for the object descriptor. - Connects to all signals exposed by the
transportQt object. - Exposes a
send(event, args)method that invokes theonEventmethod on the Qt side. - Emits an
app-readysignal to the shell once initialised.
| Event | Description |
|---|---|
open-media | Open a stremio:// deep link URL |
windowClosed | The native window close button was pressed |
App.js handles open-media by parsing the stremio:// URL and redirecting window.location.href to the corresponding hash route.
Chromecast
File:src/services/Chromecast/Chromecast.js
Initialises the Google Cast SDK and manages a ChromecastTransport. Errors gracefully when the Cast API is not available (e.g. non-Chrome browsers).
Properties
| Property | Type | Description |
|---|---|---|
active | boolean | true when the Cast SDK is initialised |
error | Error | null | 'Google Cast API not available' if SDK is absent |
transport | ChromecastTransport | null | Active transport for casting control |
App.js configures it:
KeyboardShortcuts
File:src/services/KeyboardShortcuts/KeyboardShortcuts.js
Attaches a global keydown listener to window. Shortcuts are ignored when the user is typing in an INPUT element or when a modifier key (Ctrl, Alt, Shift, Meta) is held.
Shortcuts
| Key | Action |
|---|---|
0 | Navigate to #/search |
1 | Navigate to #/ (Board) |
2 | Navigate to #/discover |
3 | Navigate to #/library |
4 | Navigate to #/calendar |
5 | Navigate to #/addons |
6 | Navigate to #/settings |
Backspace | history.back() |
Properties
| Property | Type | Description |
|---|---|---|
active | boolean | true when the keydown listener is attached |
DragAndDrop
File:src/services/DragAndDrop/DragAndDrop.js
Handles files dropped onto the browser window. Attaches dragover (to prevent the default browser navigation) and drop listeners.
Currently handles one file type:
| MIME type | Action |
|---|---|
application/x-bittorrent | Reads the file as an ArrayBuffer and dispatches StreamingServer/CreateTorrent to the core |
application/x-subrip | Accepted but not yet handled |
text/vtt | Accepted but not yet handled |
error event with { message, file: { name, type } }.
DragAndDrop receives core as a constructor argument because it needs to dispatch actions directly:
Properties
| Property | Type | Description |
|---|---|---|
active | boolean | true when the event listeners are attached |
Events
| Event | Payload | Description |
|---|---|---|
error | { message, file } | Emitted when a dropped file cannot be processed |
stateChanged | — | Emitted when active changes |
