@spearwolf/signalize - A lightweight JavaScript library for signals & effects.
Reactive programming, made simple. Works in Browser & Node.js.
Type-safe. Fast. No framework lock-in.
@spearwolf/signalize is a JavaScript library for creating fine-grained reactivity through signals and effects.
- Standalone - Framework agnostic, works anywhere JavaScript runs
- Side-effect free - Targets ES2023+ environments
- TypeScript-first - Written in TypeScript v5 with full type support
- Modern decorators - Optional TC39 decorators for class-based APIs
Note
Reactivity is the secret sauce to building modern, dynamic web apps.
@spearwolf/signalize makes it easy. No frameworks, no boilerplate, just pure reactivity.
npm install @spearwolf/signalizeimport {createSignal, createEffect} from '@spearwolf/signalize';
// Create a signal with an initial value
const count = createSignal(0);
// Create an effect that runs whenever `count` changes
createEffect(() => {
console.log(`The count is now: ${count.get()}`);
});
// => "The count is now: 0"
// Update the signal
count.set(5);
// => "The count is now: 5"
count.set(10);
// => "The count is now: 10"That's it! No extra boilerplate, no framework dependencies. Just pure, simple reactivity.
The library revolves around four main primitives:
Reactive values that notify dependents when changed. Think of them as reactive variables.
const name = createSignal('Alice');
console.log(name.get()); // Read with tracking
console.log(name.value); // Read without tracking
name.set('Bob'); // WriteFunctions that automatically re-run when their signal dependencies change.
createEffect(() => {
// Automatically re-runs when `name` changes
console.log(`Hello, ${name.get()}!`);
});Computed signals - cached derived values that update when dependencies change.
const firstName = createSignal('John');
const lastName = createSignal('Doe');
const fullName = createMemo(() => `${firstName.get()} ${lastName.get()}`);
console.log(fullName()); // => "John Doe"Explicit one-way data flow connections between signals. Inspired by visual programming tools like Unreal Engine Blueprints.
const source = createSignal(10);
const target = createSignal(0);
link(source, target);
console.log(target.value); // => 10
source.set(42);
console.log(target.value); // => 42For those who prefer object-oriented patterns:
import {signal, memo} from '@spearwolf/signalize/decorators';
class Counter {
@signal() accessor value = 0;
@memo()
doubled() {
return this.value * 2;
}
increment() {
this.value++;
}
}Important
The decorator API is still in the early stages of development. It only uses the new JavaScript standard decorators, not the legacy TypeScript ones.
For comprehensive documentation, see the docs/ folder:
| Document | Description |
|---|---|
| Introduction | Overview and key features |
| Getting Started | Installation and first steps |
| Developer Guide | Comprehensive guide to all features |
| Full API Reference | Complete API documentation |
| Cheat Sheet | Quick reference for all APIs |
createSignal, destroySignal, isSignal, getSignalsCount, muteSignal, unmuteSignal, touch, value
createEffect, getEffectsCount, onCreateEffect, onDestroyEffect
createMemo
link, unlink, getLinksCount
batch, beQuiet, isQuiet, hibernate
SignalGroup, SignalAutoMap
destroyObjectSignals, findObjectSignalByName, findObjectSignalNames, findObjectSignals
@signal, @memo
Contributions are welcome! If you find a bug or have a feature request, please open an issue. If you want to contribute code or documentation, please open a pull request.
See CONTRIBUTING.md for development guidelines and CODE_OF_CONDUCT.md for community guidelines.
For version history and migration guides, see the CHANGELOG.
This project is licensed under the Apache-2.0 License. See the LICENSE file for details.
The hero image above was created at the request of spearwolf using OpenAI's DALL-E and guided by ChatGPT. It was then animated by KLING AI and converted by Ezgif.com.
