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

# Solid integration

> Use Helios with Solid for fine-grained reactive video animations

Helios leverages Solid's fine-grained reactivity system through signals that efficiently update only when needed.

## Quick start

**1. Install dependencies**

```bash theme={null}
npm install @helios-project/core solid-js
```

**2. Create the createHeliosSignal helper**

```js lib/createHeliosSignal.js theme={null}
import { createSignal, onCleanup, onMount } from 'solid-js';

export function createHeliosSignal(helios) {
    const [state, setState] = createSignal(helios.getState());

    onMount(() => {
        const unsub = helios.subscribe(setState);
        onCleanup(() => {
            unsub();
        });
    });

    return state;
}
```

**3. Initialize Helios**

```jsx index.jsx theme={null}
import { render } from 'solid-js/web';
import App from './App';
import { Helios } from '@helios-project/core';

// Initialize Helios
const helios = new Helios({
    duration: 5,
    fps: 30,
    autoSyncAnimations: true
});
window.helios = helios;
helios.bindToDocumentTimeline();

render(() => <App />, document.getElementById('app'));
```

**4. Create your first animation**

```jsx App.jsx theme={null}
import { createMemo } from 'solid-js';
import { createHeliosSignal } from './lib/createHeliosSignal';
import './style.css';

function App() {
    // Ensure helios exists (should be initialized in index.jsx)
    if (!window.helios) {
        console.warn('Helios not initialized on window');
    }

    const state = createHeliosSignal(window.helios);

    // Derived state for rotation (0 to 360 deg)
    const rotation = createMemo(() => {
        const s = state();
        const totalFrames = s.duration * window.helios.fps;
        const progress = totalFrames > 0 ? s.currentFrame / totalFrames : 0;
        return progress * 360;
    });

    return (
        <div class="container">
            <div class="column">
                <h2>Signal Driven</h2>
                <div
                    class="box signal-box"
                    style={{ transform: `rotate(${rotation()}deg)` }}
                >
                    Signal
                </div>
            </div>

            <div class="column">
                <h2>CSS Driven</h2>
                <div class="box css-box">
                    CSS
                </div>
            </div>
        </div>
    );
}

export default App;
```

## Animation approaches

> [tab] Signal-driven animations
>
> Animate using Solid's reactive signals:
>
> ```jsx theme={null}
> import { createMemo } from 'solid-js';
> import { createHeliosSignal } from './lib/createHeliosSignal';
>
> function SignalAnimation() {
>     const state = createHeliosSignal(window.helios);
>
>     const opacity = createMemo(() => 
>         Math.min(1, state().currentFrame / 30)
>     );
>
>     const transform = createMemo(() => {
>         const frame = state().currentFrame;
>         return `translateX(${frame * 5}px) rotate(${frame * 2}deg)`;
>     });
>
>     return (
>         <div style={{ 
>             opacity: opacity(), 
>             transform: transform() 
>         }}>
>             Animated content
>         </div>
>     );
> }
> ```

> [tab] Canvas animations
>
> Use `createEffect` to draw frame-by-frame animations:
>
> ```jsx theme={null}
> import { createEffect } from 'solid-js';
> import { createHeliosSignal } from './lib/createHeliosSignal';
> import { Helios } from '@helios-project/core';
>
> // Initialize Helios if not already present
> if (!window.helios) {
>     window.helios = new Helios({
>         fps: 30,
>         duration: 60,
>         width: 1920,
>         height: 1080,
>         autoStart: true,
>     });
> }
>
> function CanvasAnimation() {
>     let canvasRef;
>     const frame = createHeliosSignal(window.helios);
>
>     createEffect(() => {
>         const canvas = canvasRef;
>         if (!canvas) return;
>
>         const ctx = canvas.getContext('2d');
>         if (!ctx) return;
>
>         const state = frame();
>         const { width, height, currentFrame, duration } = state;
>
>         canvas.width = width;
>         canvas.height = height;
>
>         // Clear
>         ctx.fillStyle = '#1a1a1a';
>         ctx.fillRect(0, 0, width, height);
>
>         // Draw
>         const totalFrames = duration * window.helios.fps;
>         const progress = totalFrames > 0 ? currentFrame / totalFrames : 0;
>
>         ctx.fillStyle = '#446b9e';
>         const size = 200;
>         const x = (width - size) * progress;
>         const y = (height - size) / 2;
>
>         ctx.fillRect(x, y, size, size);
>
>         // Draw text
>         ctx.fillStyle = 'white';
>         ctx.font = '40px sans-serif';
>         ctx.fillText(`Frame: ${currentFrame}`, 50, 100);
>     });
>
>     return (
>         <canvas ref={canvasRef} style={{ width: '100%', height: 'auto' }} />
>     );
> }
> ```

## Animation helpers

Helios provides utility functions for common animation patterns:

```jsx theme={null}
import { createMemo } from 'solid-js';
import { interpolate, spring } from '@helios-project/core';
import { createHeliosSignal } from './lib/createHeliosSignal';

function HelperDemo() {
    const state = createHeliosSignal(window.helios);

    // Interpolate x position: 0 -> 200 over frames 0-60
    const x = createMemo(() => 
        interpolate(state().currentFrame, [0, 60], [0, 200], { extrapolateRight: 'clamp' })
    );

    // Spring scale: 0 -> 1 starting at frame 0
    const scale = createMemo(() => 
        spring({ 
            frame: state().currentFrame, 
            fps: 30, 
            from: 0, 
            to: 1, 
            config: { stiffness: 100 } 
        })
    );

    return (
        <div style={{
            transform: `translateX(${x()}px) scale(${scale()})`,
            width: '100px',
            height: '100px',
            background: 'hotpink'
        }}>
            Animated
        </div>
    );
}
```

## Fine-grained reactivity

Solid's fine-grained reactivity means only the specific DOM nodes that depend on changing signals will update:

```jsx theme={null}
import { createMemo } from 'solid-js';
import { createHeliosSignal } from './lib/createHeliosSignal';

function FineGrainedExample() {
    const state = createHeliosSignal(window.helios);

    // Each memo creates a separate reactive computation
    const x = createMemo(() => state().currentFrame * 5);
    const y = createMemo(() => Math.sin(state().currentFrame * 0.1) * 100);
    const color = createMemo(() => {
        const hue = (state().currentFrame * 2) % 360;
        return `hsl(${hue}, 70%, 50%)`;
    });

    return (
        <>
            {/* Only the transform updates when x or y changes */}
            <div style={{ transform: `translate(${x()}px, ${y()}px)` }}>
                Box 1
            </div>

            {/* Only the background-color updates when color changes */}
            <div style={{ 'background-color': color() }}>
                Box 2
            </div>
        </>
    );
}
```

## Best practices

> [accordion] Initialize Helios globally
>
> Create the Helios instance on `window` in your entry file for global access:
>
> ```jsx theme={null}
> // index.jsx
> import { Helios } from '@helios-project/core';
>
> const helios = new Helios({ duration: 5, fps: 30 });
> window.helios = helios;
> helios.bindToDocumentTimeline();
> ```

> [accordion] Use createMemo for derived values
>
> Always use `createMemo` for computed animation values to ensure efficient updates:
>
> ```jsx theme={null}
> import { createMemo } from 'solid-js';
>
> const rotation = createMemo(() => {
>     const progress = state().currentFrame / totalFrames;
>     return progress * 360;
> });
> ```

> [accordion] Clean up subscriptions
>
> Use `onMount` and `onCleanup` to manage Helios subscriptions:
>
> ```jsx theme={null}
> import { onMount, onCleanup } from 'solid-js';
>
> onMount(() => {
>     const unsub = helios.subscribe(setState);
>     onCleanup(() => {
>         unsub();
>     });
> });
> ```

> [accordion] Use createEffect for side effects
>
> Use `createEffect` for canvas drawing and other side effects:
>
> ```jsx theme={null}
> import { createEffect } from 'solid-js';
>
> createEffect(() => {
>     const ctx = canvas.getContext('2d');
>     const currentFrame = state().currentFrame;
>     // Draw based on currentFrame
> });
> ```

## TypeScript support

Helios provides full TypeScript support for Solid:

```tsx theme={null}
import type { Helios } from '@helios-project/core';
import { createSignal, onMount, onCleanup, type Accessor } from 'solid-js';

interface HeliosState {
    currentFrame: number;
    duration: number;
    fps: number;
}

export function createHeliosSignal(helios: Helios): Accessor<HeliosState> {
    const [state, setState] = createSignal<HeliosState>(helios.getState());

    onMount(() => {
        const unsub = helios.subscribe(setState);
        onCleanup(() => {
            unsub();
        });
    });

    return state;
}
```

## Performance benefits

Solid's fine-grained reactivity provides excellent performance for video animations:

* **No Virtual DOM**: Direct DOM updates mean less overhead
* **Surgical updates**: Only affected DOM nodes update
* **Automatic dependency tracking**: Solid knows exactly what needs to update
* **Compiled reactivity**: Reactive code is optimized at build time

## Next steps

> [card] [Animation helpers](https://docs.heliosrender.com/features/animation-helpers.md)
>
> Learn about interpolation, spring physics, and easing functions

> [card] [Canvas rendering](https://docs.heliosrender.com/guides/canvas)
>
> Create high-performance canvas animations

> [card] [Sequences](https://docs.heliosrender.com/guides/sequences)
>
> Build complex multi-scene animations

> [card] [Export videos](https://docs.heliosrender.com/guides/export)
>
> Render your animations to video files


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.