# How Are Components Managed in the Stremio-Web Codebase: A Complete Guide

> Discover how Stremio-web manages components within its codebase. Learn about organized folders, central re-exports, and module aliasing for efficient scaling and tree-shaking.

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

---

**Components in stremio-web are organized as self-contained folders under `src/components/`, centrally re-exported through [`src/components/index.ts`](https://github.com/Stremio/stremio-web/blob/main/src/components/index.ts), and consumed via the `stremio/components` module alias to ensure tree-shaking and maintainable scaling.**

The Stremio web application ([Stremio/stremio-web](https://github.com/Stremio/stremio-web)) is built with React and TypeScript, employing a modular architecture that keeps UI elements discoverable and encapsulated. This article examines the specific patterns used to manage components, from file organization to import resolution.

## Component Architecture Overview

Every reusable UI element lives under `src/components/` as a self-contained folder. Each folder typically contains:

- A TypeScript implementation file (`*.tsx`)
- A Less stylesheet (`*.less`)
- An optional test suite

This structure ensures that logic, styling, and tests are co-located, making individual components easy to locate and move. The architecture deliberately separates UI concerns from business logic, which resides in `src/services/`.

## Component Anatomy and File Structure

### Self-Contained Component Folders

Components follow a strict co-location pattern. For example, the `Button` component exists at `src/components/Button/` and contains both [`Button.tsx`](https://github.com/Stremio/stremio-web/blob/main/Button.tsx) and `Button.less`. This guarantees that any file importing `Button` automatically brings along its scoped styles.

### Implementation Patterns

Components are implemented as pure functional components using React hooks. They utilize `forwardRef` for ref forwarding and import styles as CSS Modules.

Here is the implementation pattern from [`src/components/Button/Button.tsx`](https://github.com/Stremio/stremio-web/blob/main/src/components/Button/Button.tsx):

```tsx
import { createElement, forwardRef, useCallback } from 'react';
import classNames from 'classnames';
import { LongPressEventType, useLongPress } from 'use-long-press';
import styles from './Button.less';

type Props = {
    className?: string;
    href?: string;
    disabled?: boolean;
    children: React.ReactNode;
    onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
    onLongPress?: () => void;
};

const Button = forwardRef(({ className, href, disabled, children, onLongPress, ...props }: Props, ref) => {
    const longPress = useLongPress(onLongPress!, { detect: LongPressEventType.Pointer });
    
    return createElement(
        typeof href === 'string' && href.length > 0 ? 'a' : 'div',
        {
            tabIndex: 0,
            ...props,
            ref,
            className: classNames(className, styles['button-container'], { disabled }),
            href,
            ...longPress(),
        },
        children
    );
});

export default Button;

```

Key implementation details include:

- **Logic** – Managed through hooks like `useCallback` and custom hooks such as `useLongPress`.
- **Styling** – Scoped via CSS Modules (`Button.less`), referenced as `styles['button-container']`.
- **Export** – Default export for individual consumption, later aggregated in the central index.

## Centralized Component Registry

### The Index Hub Pattern

The file [`src/components/index.ts`](https://github.com/Stremio/stremio-web/blob/main/src/components/index.ts) serves as the single entry point for the entire component library. It imports each component from its respective folder and re-exports them as named exports:

```ts
// src/components/index.ts
import Button from './Button';
import Toggle from './Toggle';
import Image from './Image';
// ... other imports

export {
    Button,
    Toggle,
    Image,
    // ... all other components
};

```

This pattern enables developers to import multiple components from a single path while maintaining tree-shaking compatibility.

### Module Aliasing with Webpack and TypeScript

To avoid relative path hell (e.g., `../../../components/Button`), the project configures a module alias `stremio/components` that resolves to `src/components/`.

**Webpack configuration** maps the alias for bundling, while **TypeScript path mapping** in [`tsconfig.json`](https://github.com/Stremio/stremio-web/blob/main/tsconfig.json) provides IDE support and compile-time checking:

```json
{
  "paths": {
    "stremio/components/*": ["src/components/*"]
  }
}

```

This allows concise, predictable imports throughout the application:

```tsx
import { Button, Toggle, Image } from 'stremio/components';

```

## Import and Usage Patterns

The alias is used extensively across the application. For example, [`src/routes/Settings/Menu/Menu.tsx`](https://github.com/Stremio/stremio-web/blob/main/src/routes/Settings/Menu/Menu.tsx) imports the `Button` component:

```tsx
// src/routes/Settings/Menu/Menu.tsx
import { Button } from 'stremio/components';

// Usage within component
<Button onClick={handleClick}>Save</Button>

```

Higher-level compositions, such as [`src/App/UpdaterBanner/UpdaterBanner.tsx`](https://github.com/Stremio/stremio-web/blob/main/src/App/UpdaterBanner/UpdaterBanner.tsx), demonstrate how multiple components are combined:

```tsx
import { Button, Image, Transition } from 'stremio/components';

export const UpdaterBanner = () => (
  <Transition when={true} name="fade" duration={300}>
    <Button onClick={() => console.log('clicked')}>Update Now</Button>
    <Image src="/logo.png" alt="Stremio logo" />
  </Transition>
);

```

## Styling Strategy with CSS Modules

Components import adjacent `.less` files that are processed through the CSS Modules loader. This scopes class names locally, preventing global namespace pollution.

In `src/components/Button/Button.less`, classes like `.button-container` are transformed at build time. The component references these via the imported `styles` object:

```tsx
className={classNames(className, styles['button-container'], { disabled })}

```

This approach ensures that styles defined for a button do not leak to other elements, even if class names overlap.

## State Management and Lifecycle

Most components in stremio-web are **stateless** pure UI widgets. When state is required (for example, in toggle switches), components manage it internally via `useState` or through shared **React Contexts** such as `GamepadContext` and `CoreProvider`.

Business logic is deliberately kept out of components, residing instead in services under `src/services/`. This separation of concerns keeps components focused on presentation while state and side effects are handled by dedicated providers.

## Adding a New Component

To extend the component library, follow this workflow:

1. **Create the folder** at `src/components/MyNewComponent/`.
2. **Add the implementation** in [`MyNewComponent.tsx`](https://github.com/Stremio/stremio-web/blob/main/MyNewComponent.tsx) following the hooks and `forwardRef` pattern.
3. **Add styles** in `MyNewComponent.less`.
4. **Register the export** by adding `import MyNewComponent from './MyNewComponent';` to [`src/components/index.ts`](https://github.com/Stremio/stremio-web/blob/main/src/components/index.ts) and including it in the export list.
5. **Consume** the component via `import { MyNewComponent } from 'stremio/components';`.

## Summary

- Components reside in self-contained folders under `src/components/`, each containing implementation, styles, and optional tests.
- [`src/components/index.ts`](https://github.com/Stremio/stremio-web/blob/main/src/components/index.ts) acts as a central registry, re-exporting all components for consumption.
- The `stremio/components` module alias (configured in Webpack and TypeScript) enables clean, absolute imports.
- CSS Modules provide scoped styling via `.less` files imported as objects.
- Components are predominantly stateless; state is handled via React Contexts or local hooks, with business logic living in `src/services/`.

## Frequently Asked Questions

### Where are UI components located in the stremio-web codebase?

All UI components are located in the `src/components/` directory. Each component occupies its own subfolder (e.g., `src/components/Button/`) containing the TypeScript implementation file, a Less stylesheet, and optional test files.

### How does the `stremio/components` import alias work?

The alias is defined in both the Webpack configuration and [`tsconfig.json`](https://github.com/Stremio/stremio-web/blob/main/tsconfig.json). It maps the string `stremio/components` to the physical path `src/components/`, allowing developers to import components using absolute paths rather than relative ones. This provides IDE autocomplete support and ensures consistent import syntax across the application.

### What styling approach does stremio-web use for components?

The codebase uses CSS Modules with Less preprocessing. Each component imports a `.less` file, and the CSS Modules loader scopes all class names to that specific component. This prevents style leakage and allows developers to use simple class names like `.button-container` without worrying about global conflicts.

### How do I add a new component to the stremio-web codebase?

Create a new folder under `src/components/` with your `.tsx` and `.less` files, then register the component in [`src/components/index.ts`](https://github.com/Stremio/stremio-web/blob/main/src/components/index.ts) by importing it and adding it to the export list. Once registered, you can import it anywhere in the application using `import { MyComponent } from 'stremio/components';`.