Skip to main content
Helios leverages Solid’s fine-grained reactivity system through signals that efficiently update only when needed.

Quick start

1

Install dependencies

npm install @helios-project/core solid-js
2

Create the createHeliosSignal helper

lib/createHeliosSignal.js
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

index.jsx
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

App.jsx
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

Animate using Solid’s reactive signals:
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>
    );
}

Animation helpers

Helios provides utility functions for common animation patterns:
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:
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

Create the Helios instance on window in your entry file for global access:
// index.jsx
import { Helios } from '@helios-project/core';

const helios = new Helios({ duration: 5, fps: 30 });
window.helios = helios;
helios.bindToDocumentTimeline();
Always use createMemo for computed animation values to ensure efficient updates:
import { createMemo } from 'solid-js';

const rotation = createMemo(() => {
    const progress = state().currentFrame / totalFrames;
    return progress * 360;
});
Use onMount and onCleanup to manage Helios subscriptions:
import { onMount, onCleanup } from 'solid-js';

onMount(() => {
    const unsub = helios.subscribe(setState);
    onCleanup(() => {
        unsub();
    });
});
Use createEffect for canvas drawing and other side effects:
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:
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

Animation helpers

Learn about interpolation, spring physics, and easing functions

Canvas rendering

Create high-performance canvas animations

Sequences

Build complex multi-scene animations

Export videos

Render your animations to video files

Build docs developers (and LLMs) love