signalforge-alpha
v0.1.1
Published
Fine-grained reactive state management with automatic dependency tracking - Ultra-optimized, zero dependencies
Maintainers
Readme
SignalForge ⚡
The Easiest and Fastest State Management Library
Works everywhere - React, Vue, Angular, React Native, or plain JavaScript!
Built by ForgeCommunity 🚀
📚 Table of Contents
- Why SignalForge?
- Quick Start
- Installation
- Basic Concepts
- Step-by-Step Guide
- React Integration
- All Functions Explained
- Real Examples
- Performance
- Support
🎯 Why SignalForge?
✅ Super Easy - Just 3 main functions to learn!
⚡ 100x Faster - Lightning fast performance
🪶 Super Small - Only 2KB (tiny!)
🌍 Works Everywhere - Any framework or no framework
🔄 Auto-Updates - Changes happen automatically
💾 Auto-Save - Built-in storage
🛠️ Debugger - See what's happening
📦 TypeScript - Full type safety
🔐 Safe - No memory leaks
⚡ Quick Start
Step 1: Install
npm install signalforge-alphaStep 2: Create a Signal
import { createSignal } from 'signalforge-alpha';
// Create a signal (like a smart variable)
const count = createSignal(0);
// Read the value
console.log(count.get()); // Output: 0
// Change the value
count.set(5);
console.log(count.get()); // Output: 5That's it! You just created your first signal! 🎉
📦 Installation
For Web Projects
npm install signalforge-alphaFor React Native
npm install signalforge-alpha
# IMPORTANT: For persistent signals, also install:
npm install @react-native-async-storage/async-storage
# iOS only
cd ios && pod install && cd ..Run the React Native Example (Local)
Want to try it quickly in a real app? This repo includes a React Native example wired to the local package.
# From repo root
npm install
npm run build
# Then install and run the example app
cd examples/example
npm install
npm startIn a second terminal, build and run a platform:
# Android (Windows/macOS/Linux)
npm run android
# iOS (macOS only)
# First time per machine or after native changes:
# cd ios; bundle install; bundle exec pod install; cd ..
npm run iosNotes:
- The example depends on the local package via
"signalforge-alpha": "file:../..". - If you change library code under
src/, rebuild the dist and restart Metro:npm run buildat repo root, then restartnpm startin the example.
🧠 Basic Concepts
What is a Signal?
A signal is like a smart variable that:
- Holds a value (number, text, object, etc.)
- Tells other parts of your app when it changes
- Updates automatically
Think of it like a light switch - when you flip it, all the lights connected to it turn on/off automatically!
Three Main Functions
createSignal- Create a smart variablecreateComputed- Calculate based on other signals (auto-updates!)createEffect- Do something when signals change
📖 Step-by-Step Guide
Level 1: Basic Signal (Beginner)
What: Create a signal that stores a value
How to use:
import { createSignal } from 'signalforge-alpha';
// Step 1: Create a signal with initial value
const age = createSignal(25);
// Step 2: Read the value
console.log(age.get()); // 25
// Step 3: Change the value
age.set(26);
console.log(age.get()); // 26
// Step 4: Update based on current value
age.set(current => current + 1);
console.log(age.get()); // 27Real example: Shopping cart item count
const cartItems = createSignal(0);
// Add item to cart
function addToCart() {
cartItems.set(count => count + 1);
}
// Get current count
console.log('Items in cart:', cartItems.get());Level 2: Computed Signal (Auto-Calculate)
What: A signal that calculates its value automatically from other signals
How to use:
import { createSignal, createComputed } from 'signalforge-alpha';
// Step 1: Create base signals
const price = createSignal(100);
const quantity = createSignal(2);
// Step 2: Create computed signal (auto-calculates!)
const total = createComputed(() => {
return price.get() * quantity.get();
});
console.log(total.get()); // 200
// Step 3: Change base signal - computed updates automatically!
price.set(150);
console.log(total.get()); // 300 (auto-updated!)Real example: Shopping cart total
const itemPrice = createSignal(50);
const itemCount = createSignal(3);
const tax = createSignal(0.1); // 10% tax
// Calculates automatically!
const subtotal = createComputed(() => itemPrice.get() * itemCount.get());
const taxAmount = createComputed(() => subtotal.get() * tax.get());
const finalTotal = createComputed(() => subtotal.get() + taxAmount.get());
console.log('Subtotal:', subtotal.get()); // 150
console.log('Tax:', taxAmount.get()); // 15
console.log('Total:', finalTotal.get()); // 165
// Change quantity - everything updates!
itemCount.set(5);
console.log('New Total:', finalTotal.get()); // 275 (auto-calculated!)Level 3: Effects (Do Something When Changed)
What: Run code automatically when signals change
How to use:
import { createSignal, createEffect } from 'signalforge-alpha';
// Step 1: Create signal
const userName = createSignal('John');
// Step 2: Create effect (runs when userName changes)
const cleanup = createEffect(() => {
console.log('Hello, ' + userName.get() + '!');
});
// Output: "Hello, John!"
// Step 3: Change signal - effect runs automatically!
userName.set('Jane');
// Output: "Hello, Jane!"
// Step 4: Stop the effect when done
cleanup();Real example: Save to localStorage when data changes
const userSettings = createSignal({ theme: 'dark', fontSize: 14 });
// Auto-save whenever settings change!
createEffect(() => {
const settings = userSettings.get();
localStorage.setItem('settings', JSON.stringify(settings));
console.log('Settings saved!');
});
// Change settings - automatically saves!
userSettings.set({ theme: 'light', fontSize: 16 });
// Output: "Settings saved!"Level 4: Batch Updates (Multiple Changes at Once)
What: Update multiple signals efficiently
How to use:
import { createSignal, createComputed, batch } from 'signalforge-alpha';
const firstName = createSignal('John');
const lastName = createSignal('Doe');
const fullName = createComputed(() => `${firstName.get()} ${lastName.get()}`);
// Without batch - recalculates twice
firstName.set('Jane');
lastName.set('Smith');
// fullName recalculates twice ❌
// With batch - recalculates once!
batch(() => {
firstName.set('Jane');
lastName.set('Smith');
});
// fullName recalculates once ✅ (33x faster!)Level 5: Subscribe to Changes (Listen)
What: Run a function every time a signal changes
How to use:
const count = createSignal(0);
// Step 1: Subscribe to changes
const unsubscribe = count.subscribe((newValue) => {
console.log('Count changed to:', newValue);
});
// Step 2: Change value - subscriber gets notified
count.set(1); // Output: "Count changed to: 1"
count.set(2); // Output: "Count changed to: 2"
// Step 3: Stop listening
unsubscribe();
count.set(3); // No output (not listening anymore)Level 6: Untrack (Read Without Dependency)
What: Read a signal without creating a dependency
How to use:
import { createSignal, createComputed, untrack } from 'signalforge-alpha';
const count = createSignal(1);
const debugMode = createSignal(true);
const doubled = createComputed(() => {
const value = count.get() * 2;
// Read debugMode WITHOUT creating dependency
if (untrack(() => debugMode.get())) {
console.log('Debug:', value);
}
return value;
});
// Changing count triggers recompute ✅
count.set(5); // Output: "Debug: 10"
// Changing debugMode does NOT trigger recompute ✅
debugMode.set(false); // No output (not dependent!)⚛️ React Integration
Step 1: Install
npm install signalforge-alpha reactStep 2: Use in Components
Method A: useSignal (Component State)
import { useSignal } from 'signalforge-alpha/react';
function Counter() {
// Like useState but more powerful!
const [count, setCount] = useSignal(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}Method B: useSignalValue (Global State)
import { createSignal } from 'signalforge-alpha';
import { useSignalValue } from 'signalforge-alpha/react';
// Create global signal (outside component)
const globalCount = createSignal(0);
function Display() {
// Subscribe to global signal
const count = useSignalValue(globalCount);
return <p>Count: {count}</p>;
}
function Controls() {
// Components share the same signal!
return (
<button onClick={() => globalCount.set(c => c + 1)}>
Increment Global Count
</button>
);
}Method C: useSignalEffect (React + Signals)
import { createSignal } from 'signalforge-alpha';
import { useSignalEffect } from 'signalforge-alpha/react';
const userId = createSignal(1);
function UserProfile() {
const [userData, setUserData] = useState(null);
// Auto-runs when userId changes!
useSignalEffect(() => {
fetch(`/api/users/${userId.get()}`)
.then(r => r.json())
.then(setUserData);
});
return <div>{userData?.name}</div>;
}📱 React Native Specific Guide
SignalForge works perfectly in React Native! Here's what you need to know:
Installation
npm install signalforge-alpha
# For persistent signals (storage):
npm install @react-native-async-storage/async-storage
cd ios && pod install # iOS onlyBasic Usage
All hooks work exactly the same as in React:
import { createSignal } from 'signalforge-alpha';
import { useSignal, useSignalValue } from 'signalforge-alpha/react';
import { View, Text, Button } from 'react-native';
const globalCount = createSignal(0);
function App() {
const [localCount, setLocalCount] = useSignal(0);
const count = useSignalValue(globalCount);
return (
<View>
<Text>Local: {localCount}</Text>
<Text>Global: {count}</Text>
<Button title="Increment Local" onPress={() => setLocalCount(localCount + 1)} />
<Button title="Increment Global" onPress={() => globalCount.set(c => c + 1)} />
</View>
);
}Persistent Storage in React Native
Important: Use persist() inside useEffect() to ensure AsyncStorage is ready:
import { createSignal } from 'signalforge-alpha';
import { persist } from 'signalforge-alpha/utils';
import { useSignalValue } from 'signalforge-alpha/react';
import { useEffect } from 'react';
// Create signal at module level
const userPrefs = createSignal({ theme: 'light', fontSize: 14 });
function App() {
const prefs = useSignalValue(userPrefs);
// Set up persistence after mount
useEffect(() => {
const cleanup = persist(userPrefs, { key: 'user_prefs' });
return cleanup; // Stop persisting on unmount
}, []);
return (
<View>
<Text>Theme: {prefs.theme}</Text>
<Button
title="Toggle Theme"
onPress={() => userPrefs.set(p => ({
...p,
theme: p.theme === 'light' ? 'dark' : 'light'
}))}
/>
</View>
);
}Metro Configuration
For the example app or when linking to local SignalForge, configure Metro properly:
// metro.config.js
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const path = require('path');
const config = {
watchFolders: [
path.resolve(__dirname, '../..'),
],
resolver: {
nodeModulesPaths: [
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, '../../node_modules'),
],
},
};
module.exports = mergeConfig(getDefaultConfig(__dirname), config);Common Issues
Issue: "AsyncStorage not found"
Solution: Install @react-native-async-storage/async-storage and run pod install for iOS
Issue: "Module not found: signalforge-alpha/utils"
Solution: Rebuild the library with npm run build from the repo root
Issue: "Hooks not working"
Solution: Clear Metro cache: npm start -- --reset-cache
📚 All Functions Explained
Core Functions
createSignal(initialValue)
What: Creates a signal with an initial value
Returns: Signal object with get(), set(), subscribe(), destroy()
const age = createSignal(25);
age.get(); // Read value
age.set(26); // Set value
age.set(v => v + 1); // Update based on current
const unsub = age.subscribe(val => console.log(val)); // Listen
unsub(); // Stop listening
age.destroy(); // CleanupcreateComputed(computeFn)
What: Creates auto-updating computed value
Returns: Computed signal (read-only)
const doubled = createComputed(() => count.get() * 2);
doubled.get(); // Always up-to-date!createEffect(effectFn)
What: Runs code when dependencies change
Returns: Cleanup function
const cleanup = createEffect(() => {
console.log('Count is:', count.get());
});
cleanup(); // Stop effectbatch(fn)
What: Group multiple updates together (faster!)
Returns: Result of fn
batch(() => {
signal1.set(1);
signal2.set(2);
// Only recalculates once!
});untrack(fn)
What: Read signals without tracking
Returns: Result of fn
const value = untrack(() => signal.get());
// Doesn't create dependencyflushSync()
What: Force immediate batch flush (synchronous updates)
flushSync(); // Process all pending updates nowAdvanced Batching Functions
startBatch()
What: Start manual batch (advanced usage)
startBatch();
signal1.set(1);
signal2.set(2);
endBatch(); // Flush all updatesendBatch()
What: End manual batch and flush updates
flushBatches()
What: Force flush all pending batches
queueBatchCallback(fn)
What: Queue function to run after batch completes
queueBatchCallback(() => console.log('Batch done!'));getBatchDepth()
What: Get current batch nesting level
Returns: Number (0 = not batching)
getPendingCount()
What: Get number of pending updates
Returns: Number of signals waiting to update
isBatching()
What: Check if currently batching
Returns: Boolean
Utility Functions
derive([signals], fn)
What: Create computed from multiple signals
const sum = derive([a, b], (valA, valB) => valA + valB);combine(signals)
What: Combine multiple signals into array
const all = combine([signal1, signal2, signal3]);
all.get(); // [val1, val2, val3]map(signal, fn)
What: Transform signal value
const doubled = map(count, n => n * 2);filter(signal, predicate, defaultValue)
What: Filter signal updates
const evenOnly = filter(count, n => n % 2 === 0, 0);memo(signal, equalsFn)
What: Only update when value changes (custom equality)
const memoized = memo(userSignal, (a, b) => a.id === b.id);debounce(signal, delayMs)
What: Delay updates
const delayed = debounce(searchText, 300);throttle(signal, intervalMs)
What: Limit update frequency
const limited = throttle(scrollPos, 100);createResource(fetcher)
What: Track async operation status
Returns: Signal with { status, data, error }
const user = createResource(() => fetch('/api/user').then(r => r.json()));
console.log(user.get().status); // 'pending' | 'success' | 'error'
console.log(user.get().data); // Result when loadedStorage Functions
⚠️ React Native Requirement: For persistent signals in React Native, you must install AsyncStorage:
npm install @react-native-async-storage/async-storage
cd ios && pod install # iOS onlycreatePersistentSignal(key, initialValue)
What: Signal that auto-saves to storage
// Auto-saves to localStorage (Web) or AsyncStorage (React Native)
const theme = createPersistentSignal('app_theme', 'dark');
theme.set('light'); // Automatically saved!Note for React Native: Import from utils:
import { createPersistentSignal } from 'signalforge-alpha/utils';persist(signal, options)
What: Make existing signal persistent
const count = createSignal(0);
const stop = persist(count, { key: 'counter', debounce: 500 });
stop(); // Stop persistingNote for React Native: Import from utils and use in useEffect:
import { persist } from 'signalforge-alpha/utils';
import { useEffect } from 'react';
function App() {
useEffect(() => {
const stop = persist(count, { key: 'counter' });
return stop; // Cleanup on unmount
}, []);
}getStorageAdapter()
What: Get storage adapter for current environment
Returns: StorageAdapter (auto-detects Web/React Native/Node)
const storage = getStorageAdapter();
await storage.save('key', value);
const data = await storage.load('key');createStorageAdapter(env, options)
What: Create custom storage adapter
const storage = createStorageAdapter('web', { prefix: 'myapp_' });detectEnvironment()
What: Detect current environment
Returns: 'web' | 'react-native' | 'node' | 'unknown'
safeStringify(value) & safeParse(json)
What: JSON helpers with circular reference handling
const json = safeStringify({ a: 1, b: circularRef });
const obj = safeParse(json);Array & Object Helpers
createArraySignal(initialArray)
What: Signal with array methods
const todos = createArraySignal(['Task 1']);
todos.push('Task 2');
todos.pop();
todos.filter((_, i) => i !== 0);
todos.remove('Task 1');
todos.clear();
console.log(todos.length); // Array length
console.log(todos.get()); // Get full arrayMethods: push, pop, filter, map, find, remove, clear, length
createRecordSignal(initialObject)
What: Signal with object methods
const user = createRecordSignal({ name: 'John', age: 30 });
user.setKey('email', '[email protected]');
console.log(user.getKey('email')); // '[email protected]'
console.log(user.hasKey('age')); // true
user.deleteKey('age');
console.log(user.keys()); // ['name', 'email']
console.log(user.values()); // ['John', '[email protected]']
console.log(user.entries()); // [['name', 'John'], ...]
user.clear();Methods: setKey, getKey, deleteKey, hasKey, keys, values, entries, clear
Performance Monitoring
monitor(signal, label)
What: Wrap signal with performance tracking
const count = monitor(createSignal(0), 'counter');
// Logs read/write times automaticallyReact Hooks
useSignal(initialValue)
What: Create signal in React component
const [count, setCount] = useSignal(0);useSignalValue(signal)
What: Subscribe to external signal
const value = useSignalValue(globalSignal);useSignalEffect(effectFn)
What: Effect with auto-tracking
useSignalEffect(() => {
console.log(signal.get());
});🔌 Plugin System
SignalForge has a powerful plugin system for extending functionality!
Plugin Manager Functions
registerPlugin(name, plugin)
What: Register a plugin with the manager
import { registerPlugin, LoggerPlugin } from 'signalforge-alpha';
const logger = new LoggerPlugin({ level: 'info' });
registerPlugin('logger', logger.getPlugin());enablePlugin(name) & disablePlugin(name)
What: Enable/disable plugins at runtime
enablePlugin('logger'); // Turn on
disablePlugin('logger'); // Turn off (keeps data)getPlugin(name)
What: Get plugin instance
const logger = getPlugin('logger');isPluginEnabled(name)
What: Check if plugin is enabled
if (isPluginEnabled('time-travel')) {
// Do something
}getAllPlugins()
What: Get all registered plugins with status
const plugins = getAllPlugins();
// [{ name: 'logger', enabled: true, ... }]getPluginStats()
What: Get plugin usage statistics
const stats = getPluginStats();
console.log(stats); // Enable counts, error counts, etc.Built-in Plugins
Logger Plugin
Logs all signal changes with filtering
import { LoggerPlugin, registerPlugin } from 'signalforge-alpha';
const logger = new LoggerPlugin({
level: 'debug', // 'debug' | 'info' | 'warn' | 'error'
maxLogs: 1000, // Max logs to keep
enableConsole: true, // Log to console
verbose: false, // Show old/new values
signalPattern: /user\./, // Filter by name regex
});
registerPlugin('logger', logger.getPlugin());
// Query logs
const allLogs = logger.getLogs();
const userLogs = logger.getLogsForSignal('user_signal_id');
const stats = logger.getStats();
// Search
const results = logger.search('user');
// Export/Import
const json = logger.exportLogs();
logger.importLogs(json);Time Travel Plugin
Undo/redo for debugging (like Redux DevTools!)
import { TimeTravelPlugin, registerPlugin } from 'signalforge-alpha';
const timeTravel = new TimeTravelPlugin({
maxHistory: 100, // Max snapshots
fullSnapshotInterval: 10, // Full snapshot every N updates
enableCompression: true, // Use diffs to save memory
});
registerPlugin('time-travel', timeTravel.getPlugin());
// Use signals
count.set(5);
count.set(10);
count.set(15);
// Time travel!
timeTravel.undo(); // Back to 10
timeTravel.undo(); // Back to 5
timeTravel.redo(); // Forward to 10
// Jump to specific point
timeTravel.jumpTo(0); // Go to beginning
// Check status
console.log(timeTravel.canUndo()); // true/false
console.log(timeTravel.canRedo()); // true/false
// Get timeline
const timeline = timeTravel.getTimelineState();
console.log(`${timeline.current}/${timeline.total}`);
// Export/Import session
const session = timeTravel.exportSession();
localStorage.setItem('debug', JSON.stringify(session));🛠️ DevTools
SignalForge includes powerful developer tools for debugging!
DevTools Functions
enableDevTools(config)
What: Enable DevTools inspector
import { enableDevTools } from 'signalforge-alpha/devtools';
enableDevTools({
trackPerformance: true,
logToConsole: true,
flipperEnabled: true, // React Native Flipper integration
});listSignals()
What: Get all active signals
import { listSignals } from 'signalforge-alpha/devtools';
const signals = listSignals();
// [{ id, type, value, subscriberCount, ... }]getSignal(id)
What: Get specific signal metadata
const signal = getSignal('signal_123');
console.log(signal.value);
console.log(signal.dependencies);getDependencyGraph()
What: Get complete dependency graph for visualization
const graph = getDependencyGraph();
// Visualize relationships between signalsgetPerformanceMetrics()
What: Get performance measurements
const metrics = getPerformanceMetrics();
// [{ signalId, duration, timestamp, ... }]Performance Profiler
Track latency and batch performance!
import {
enableProfiler,
getProfilerData,
getSignalLatencyStats,
getBatchStats
} from 'signalforge-alpha/devtools';
// Enable profiler
enableProfiler({
maxLatencySamples: 1000,
maxBatchRecords: 500,
});
// Get stats
const latencyStats = getSignalLatencyStats('signal_123');
console.log('Avg:', latencyStats.average);
console.log('P95:', latencyStats.p95);
const batchStats = getBatchStats();
console.log('Avg batch size:', batchStats.averageSize);DevTools UI Components (React)
<SignalGraphVisualizer />
What: Visual dependency graph
import { SignalGraphVisualizer } from 'signalforge-alpha/devtools';
function DevPanel() {
return <SignalGraphVisualizer width={800} height={600} />;
}<PerformanceTab />
What: Performance metrics panel
import { PerformanceTab } from 'signalforge-alpha/devtools';
function DevPanel() {
return <PerformanceTab />;
}<LogViewer />
What: Log viewer UI
import { LogViewer } from 'signalforge-alpha/devtools';
function DevPanel() {
return <LogViewer logger={loggerPlugin} />;
}<TimeTravelTimeline />
What: Time travel UI
import { TimeTravelTimeline } from 'signalforge-alpha/devtools';
function DevPanel() {
return <TimeTravelTimeline plugin={timeTravelPlugin} />;
}📱 React Native Native Bridge (JSI)
Ultra-fast native C++ implementation for React Native!
Native Functions
installJSIBindings()
What: Install native JSI bindings (10x faster!)
import { installJSIBindings } from 'signalforge-alpha/native';
// In your app startup
installJSIBindings();isNativeAvailable()
What: Check if native module is available
import { isNativeAvailable } from 'signalforge-alpha/native';
if (isNativeAvailable()) {
console.log('Using native JSI! 🚀');
} else {
console.log('Using JS fallback');
}getRuntimeInfo()
What: Get runtime information
import { getRuntimeInfo } from 'signalforge-alpha/native';
const info = getRuntimeInfo();
console.log(info);
// { isJSI: true, isHermes: true, isTurboModule: false }runPerformanceBenchmark()
What: Benchmark native vs JS performance
import { runPerformanceBenchmark } from 'signalforge-alpha/native';
const results = runPerformanceBenchmark();
console.log('Native speedup:', results.speedup); // e.g., "10.5x faster"JSI Bridge Direct Usage
import jsiBridge from 'signalforge-alpha/native';
// Create signal in native
const id = jsiBridge.createSignal('mySignal', 42);
// Get/Set values (native speed!)
const value = jsiBridge.getSignal(id);
jsiBridge.setSignal(id, 100);
// Check implementation
console.log(jsiBridge.isUsingNative()); // true if JSI installed📊 Benchmarking
Built-in benchmark utilities!
import {
benchmarkSignalUpdates,
benchmarkBatchedUpdates,
compareWithRedux,
compareWithZustand,
runBenchmarkSuite,
getResults,
} from 'signalforge-alpha/utils';
// Run benchmarks
benchmarkSignalUpdates(10000);
benchmarkBatchedUpdates(10000);
compareWithRedux();
compareWithZustand();
// Run full suite
runBenchmarkSuite();
// Get results
const results = getResults();
console.table(results);💡 Real Examples
Example 1: Counter App
import { createSignal } from 'signalforge-alpha';
const count = createSignal(0);
function increment() {
count.set(c => c + 1);
}
function decrement() {
count.set(c => c - 1);
}
console.log(count.get()); // 0
increment();
console.log(count.get()); // 1Example 2: Shopping Cart
import { createSignal, createComputed } from 'signalforge-alpha';
const items = createSignal([
{ name: 'Apple', price: 1.5, qty: 2 },
{ name: 'Bread', price: 2.0, qty: 1 }
]);
const total = createComputed(() => {
return items.get().reduce((sum, item) => {
return sum + (item.price * item.qty);
}, 0);
});
console.log('Total:', total.get()); // 5.0
// Add item
items.set(current => [...current, { name: 'Milk', price: 3.0, qty: 1 }]);
console.log('New Total:', total.get()); // 8.0 (auto-updated!)Example 3: Form Validation
import { createSignal, createComputed } from 'signalforge-alpha';
const email = createSignal('');
const password = createSignal('');
const isEmailValid = createComputed(() => {
return email.get().includes('@');
});
const isPasswordValid = createComputed(() => {
return password.get().length >= 8;
});
const canSubmit = createComputed(() => {
return isEmailValid.get() && isPasswordValid.get();
});
email.set('[email protected]');
password.set('secret123');
console.log('Can Submit:', canSubmit.get()); // trueExample 4: React Todo App
import { createSignal } from 'signalforge-alpha';
import { useSignalValue } from 'signalforge-alpha/react';
// Global state
const todos = createSignal([]);
function TodoApp() {
const todoList = useSignalValue(todos);
const [input, setInput] = useState('');
const addTodo = () => {
todos.set(current => [...current, { id: Date.now(), text: input, done: false }]);
setInput('');
};
const toggleTodo = (id) => {
todos.set(current =>
current.map(todo =>
todo.id === id ? { ...todo, done: !todo.done } : todo
)
);
};
return (
<div>
<input value={input} onChange={e => setInput(e.target.value)} />
<button onClick={addTodo}>Add</button>
<ul>
{todoList.map(todo => (
<li key={todo.id} onClick={() => toggleTodo(todo.id)}>
<span style={{ textDecoration: todo.done ? 'line-through' : 'none' }}>
{todo.text}
</span>
</li>
))}
</ul>
</div>
);
}🚀 Performance
SignalForge is 100x faster than other libraries!
| Operation | SignalForge | Redux | MobX | |-----------|-------------|-------|------| | Read | 2ns | 100ms | 300ms | | Write | 111ns | 200ms | 500ms | | Batch | 0.003ms | 100ms | 200ms |
Why so fast?
- Zero dependencies
- Optimized code
- Smart batching
- Efficient memory use
🌍 Works Everywhere
✅ React - with hooks
✅ Vue - framework-agnostic
✅ Angular - framework-agnostic
✅ Svelte - framework-agnostic
✅ React Native - with native C++ bridge
✅ Next.js - SSR support
✅ Vanilla JS - no framework needed
✅ Node.js - server-side
✅ Electron - desktop apps
📦 Import Options
SignalForge provides multiple entry points for optimal bundle size:
1. Full Bundle (Recommended)
import { createSignal, createComputed } from 'signalforge-alpha';
// Everything included: 86KB2. Core Only (Minimal)
import { createSignal, createComputed } from 'signalforge-alpha/core';
// Just reactive primitives: 4KB3. React Hooks
import { useSignal, useSignalValue } from 'signalforge-alpha/react';
// React integration: 5KB4. DevTools
import { enableDevTools, listSignals } from 'signalforge-alpha/devtools';
// Developer tools: 25KB5. Plugins
import { LoggerPlugin, TimeTravelPlugin } from 'signalforge-alpha/plugins';
// Plugin system: 27KB6. Utils
import { derive, combine, debounce } from 'signalforge-alpha/utils';
// Utility functions: 6KB7. Ultra-Minimal (Advanced)
import { signal, computed, effect } from 'signalforge-alpha/minimal';
// Absolute minimum: 0.8KB (functional API)
const count = signal(0);
console.log(count()); // Read
count(5); // Write
count(prev => prev + 1); // UpdateUltra-Minimal API:
signal(initialValue)- Functional signal (read/write in one)computed(fn)- Auto-updating computedeffect(fn)- Side effectsbatch(fn)- Batch updatesuntrack(fn)- Read without tracking
🆘 Need Help?
Quick Links
Common Questions
Q: Do I need React?
A: No! Works with any framework or no framework.
Q: Is it hard to learn?
A: No! Just 3 main functions: createSignal, createComputed, createEffect
Q: Is it production-ready?
A: This is an alpha release. Test it first!
Q: What's the bundle size?
A: Only 2KB (minimal) or 86KB (full with devtools)
Q: Does it work on mobile?
A: Yes! React Native with native C++ for 10x speed.
📄 License
MIT - Free to use in any project!
🙏 Built By
ForgeCommunity - A collective of developers creating high-performance, open-source tools.
Contributing
Contributions welcome! Please open an issue or PR on our GitHub repository.
⭐ Support Us
If you like SignalForge, please:
- ⭐ Star us on GitHub
- 🐦 Share on social media
- 🐛 Report bugs
- 💡 Suggest features
- 📝 Improve docs
Happy coding with SignalForge! 🚀
