Documentation Index
Fetch the complete documentation index at: https://mintlify.com/BintzGavin/helios/llms.txt
Use this file to discover all available pages before exploring further.
Helios leverages Solid’s fine-grained reactivity system through signals that efficiently update only when needed.
Quick start
Install dependencies
npm install @helios-project/core solid-js
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;
}
Initialize Helios
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'));
Create your first animation
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
Signal-driven animations
Canvas animations
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>
);
}
Use createEffect to draw frame-by-frame animations: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:
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
Initialize Helios globally
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();
Use createMemo for derived values
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 side effects
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;
}
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