The React-first toolkit for WASM and Web Workers
Run heavy computations with React hooks. Use WASM for native-speed performance. Keep your UI at 60fps.
📚 Documentation • Live Demo • Getting Started • Examples • API • React Hooks • WASM
- ⚛️ React-first — Purpose-built hooks like
useComputewith loading, error, and progress states - 🦀 WASM integration — Load and call AssemblyScript/Rust WASM modules with zero boilerplate
- 🚀 Non-blocking — Everything runs in Web Workers, keeping your UI at 60fps
- 🔧 Zero config — No manual worker files, postMessage handlers, or WASM glue code
- 📦 Tiny — Core library is ~3KB gzipped
- 🎯 TypeScript — Full type safety for your compute functions and WASM bindings
- 🔄 Worker pool — Automatic load balancing across CPU cores
- 📊 Progress tracking — Built-in progress reporting for long-running tasks
You can use Web Workers and WASM without a library. But here's the reality:
| Task | Without ComputeKit | With ComputeKit |
|---|---|---|
| Web Worker setup | Create separate .js files, handle postMessage, manage callbacks |
kit.register('fn', myFunc) |
| WASM loading | Fetch, instantiate, memory management, glue code | await loadWasmModule('/my.wasm') |
| React integration | Manual state, effects, cleanup, abort handling | useCompute() hook |
| Worker pooling | Build your own pool, queue, and load balancer | Built-in |
| TypeScript | Tricky worker typing, no WASM types | Full type inference |
| Error handling | Try-catch across message boundaries | Automatic with React error states |
ComputeKit's unique value: The only library that combines React hooks + WASM + Worker pool into one cohesive, type-safe developer experience.
| ✅ Use ComputeKit | ❌ Don't use ComputeKit |
|---|---|
| Image/video processing | Simple DOM updates |
| Data transformations (100K+ items) | Small array operations |
| Mathematical computations | API calls (use native fetch) |
| Parsing large files | String formatting |
| Cryptographic operations | UI state management |
| Real-time data analysis | Small form validations |
# npm
npm install @computekit/core
# With React bindings
npm install @computekit/core @computekit/react
# pnpm
pnpm add @computekit/core @computekit/react
# yarn
yarn add @computekit/core @computekit/reactimport { ComputeKit } from '@computekit/core';
// 1. Create a ComputeKit instance
const kit = new ComputeKit();
// 2. Register a compute function
kit.register('fibonacci', (n: number) => {
if (n <= 1) return n;
let a = 0,
b = 1;
for (let i = 2; i <= n; i++) {
[a, b] = [b, a + b];
}
return b;
});
// 3. Run it (non-blocking!)
const result = await kit.run('fibonacci', 50);
console.log(result); // 12586269025 — UI never froze!import { ComputeKitProvider, useComputeKit, useCompute } from '@computekit/react';
import { useEffect } from 'react';
// 1. Wrap your app with the provider
function App() {
return (
<ComputeKitProvider>
<AppContent />
</ComputeKitProvider>
);
}
// 2. Register functions at the app level
function AppContent() {
const kit = useComputeKit();
useEffect(() => {
// Register your compute functions once
kit.register('fibonacci', (n: number) => {
if (n <= 1) return n;
let a = 0,
b = 1;
for (let i = 2; i <= n; i++) {
[a, b] = [b, a + b];
}
return b;
});
}, [kit]);
return <Calculator />;
}
// 3. Use the hook in any component
function Calculator() {
const { data, loading, error, run } = useCompute<number, number>('fibonacci');
return (
<div>
<button onClick={() => run(50)} disabled={loading}>
{loading ? 'Computing...' : 'Calculate Fibonacci(50)'}
</button>
{data && <p>Result: {data}</p>}
{error && <p>Error: {error.message}</p>}
</div>
);
}This is where ComputeKit shines — combining useCompute with WASM for native-speed performance:
import { ComputeKitProvider, useComputeKit, useCompute } from '@computekit/react';
import { useEffect, useRef } from 'react';
import { loadWasm } from './wasmLoader'; // Your WASM loader
// 1. Wrap your app
function App() {
return (
<ComputeKitProvider>
<ImageProcessor />
</ComputeKitProvider>
);
}
// 2. Register a WASM-powered compute function
function ImageProcessor() {
const kit = useComputeKit();
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
// Register a function that uses WASM internally
kit.register(
'blurImage',
async (input: {
data: number[];
width: number;
height: number;
passes: number;
}) => {
const wasm = await loadWasm();
const { data, width, height, passes } = input;
// Copy input to WASM memory
const ptr = wasm.getBufferPtr();
const wasmMem = new Uint8ClampedArray(wasm.memory.buffer, ptr, data.length);
wasmMem.set(data);
// Run WASM blur
wasm.blurImage(width, height, passes);
// Return result
return Array.from(new Uint8ClampedArray(wasm.memory.buffer, ptr, data.length));
}
);
}, [kit]);
// 3. Use useCompute like any other function!
const { data, loading, run } = useCompute<
{ data: number[]; width: number; height: number; passes: number },
number[]
>('blurImage');
const handleBlur = () => {
const canvas = canvasRef.current!;
const ctx = canvas.getContext('2d')!;
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
run({
data: Array.from(imageData.data),
width: canvas.width,
height: canvas.height,
passes: 100,
});
};
// Update canvas when result arrives
useEffect(() => {
if (data && canvasRef.current) {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d')!;
const imageData = new ImageData(
new Uint8ClampedArray(data),
canvas.width,
canvas.height
);
ctx.putImageData(imageData, 0, 0);
}
}, [data]);
return (
<div>
<canvas ref={canvasRef} width={256} height={256} />
<button onClick={handleBlur} disabled={loading}>
{loading ? 'Processing...' : 'Blur Image (WASM)'}
</button>
</div>
);
}Key benefits:
- WASM runs in a Web Worker via
useCompute— UI stays responsive - Same familiar
loading,data,errorpattern as other compute functions - WASM memory management encapsulated in the registered function
- Can easily add progress reporting, cancellation, etc.
kit.register('sum', (arr: number[]) => {
return arr.reduce((a, b) => a + b, 0);
});
const bigArray = Array.from({ length: 10_000_000 }, () => Math.random());
const sum = await kit.run('sum', bigArray);kit.register('grayscale', (imageData: Uint8ClampedArray) => {
const result = new Uint8ClampedArray(imageData.length);
for (let i = 0; i < imageData.length; i += 4) {
const avg = (imageData[i] + imageData[i + 1] + imageData[i + 2]) / 3;
result[i] = result[i + 1] = result[i + 2] = avg;
result[i + 3] = imageData[i + 3]; // Alpha
}
return result;
});kit.register('longTask', async (data, { reportProgress }) => {
const total = data.items.length;
const results = [];
for (let i = 0; i < total; i++) {
results.push(process(data.items[i]));
if (i % 100 === 0) {
reportProgress({ percent: (i / total) * 100 });
}
}
return results;
});
// React: track progress
const { progress, run } = useCompute('longTask', {
onProgress: (p) => console.log(`${p.percent}% complete`),
});Main class for managing compute operations.
const kit = new ComputeKit(options?: ComputeKitOptions);| Option | Type | Default | Description |
|---|---|---|---|
maxWorkers |
number |
navigator.hardwareConcurrency |
Max workers in the pool |
timeout |
number |
30000 |
Default timeout in ms |
debug |
boolean |
false |
Enable debug logging |
remoteDependencies |
string[] |
[] |
External scripts to load in workers |
Load external libraries inside your workers:
const kit = new ComputeKit({
remoteDependencies: [
'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js',
],
});
kit.register('processData', (data: number[]) => {
// @ts-ignore - lodash loaded via importScripts
return _.chunk(data, 3);
});| Method | Description |
|---|---|
register(name, fn) |
Register a compute function |
run(name, input, options?) |
Execute a function |
getStats() |
Get pool statistics |
terminate() |
Cleanup and terminate workers |
await kit.run('myFunction', data, {
timeout: 5000, // Override default timeout
priority: 10, // Higher = runs first (0-10)
signal: abortController.signal, // Abort support
onProgress: (p) => {}, // Progress callback
});Primary hook for running compute functions.
const {
data, // Result data
loading, // Boolean loading state
error, // Error if failed
progress, // Progress info
status, // 'idle' | 'running' | 'success' | 'error' | 'cancelled'
run, // Function to execute
reset, // Reset state
cancel, // Cancel current operation
} = useCompute<TInput, TOutput>(functionName, options?);
### `useComputeCallback`
Returns a memoized async function (similar to `useCallback`).
```typescript
const calculate = useComputeCallback('sum');
const result = await calculate([1, 2, 3, 4, 5]);
Monitor worker pool performance.
const stats = usePoolStats(1000); // Refresh every 1s
// stats.activeWorkers, stats.queueLength, stats.averageTaskDurationRegister and use a function in one hook.
const { run, data } = useComputeFunction('double', (n: number) => n * 2);ComputeKit supports WASM via AssemblyScript for maximum performance.
// compute/sum.ts
export function sum(arr: Int32Array): i32 {
let total: i32 = 0;
for (let i = 0; i < arr.length; i++) {
total += unchecked(arr[i]);
}
return total;
}npx asc compute/sum.ts -o compute/sum.wasm --optimizeimport { loadWasmModule } from '@computekit/core';
const wasmModule = await loadWasmModule('/compute/sum.wasm');
// Use with your compute functions-
Transfer large data — Use typed arrays (Uint8Array, Float64Array) for automatic transfer optimization
-
Batch small operations — Combine many small tasks into one larger task
-
Right-size your pool — More workers ≠ better. Match to CPU cores.
-
Use WASM for math — AssemblyScript functions can be 10-100x faster for numeric work
// ❌ Slow: Many small calls
for (const item of items) {
await kit.run('process', item);
}
// ✅ Fast: One batched call
await kit.run('processBatch', items);const kit = new ComputeKit({
workerPath: '/workers/compute-worker.js',
});For SharedArrayBuffer support, add these headers:
// vite.config.ts
export default {
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
};computekit/
├── packages/
│ ├── core/ # @computekit/core
│ │ ├── src/
│ │ │ ├── index.ts # Main exports
│ │ │ ├── pool.ts # Worker pool
│ │ │ ├── wasm.ts # WASM utilities
│ │ │ └── types.ts # TypeScript types
│ │ └── package.json
│ │
│ └── react/ # @computekit/react
│ ├── src/
│ │ └── index.ts # React hooks
│ └── package.json
│
├── compute/ # AssemblyScript functions
│ ├── blur.ts
│ ├── fibonacci.ts
│ ├── mandelbrot.ts
│ ├── matrix.ts
│ └── sum.ts
│
├── examples/
│ └── react-demo/ # React example app
│
└── docs/ # Documentation
Contributions are welcome! Please read our Contributing Guide first.
# Clone the repo
git clone https://github.com/tapava/compute-kit.git
cd compute-kit
# Install dependencies
npm install
# Build all packages
npm run build
# Run React demo
npm run dev
# Run tests
npm testMIT © Ghassen Lassoued
Built with ❤️ for the web platform