@phcdevworks/spectre-shell-signals
v1.0.0
Published
Minimal, framework-agnostic reactive primitives package for Spectre applications.
Maintainers
Readme
@phcdevworks/spectre-shell-signals
@phcdevworks/spectre-shell-signals is the minimal reactive-primitives package for
Spectre applications.
Maintained by PHCDevworks as part of the Spectre suite, it provides a small, framework-agnostic foundation for writable signals, derived values, and reactive effects. The package is intentionally narrow: it owns primitive reactivity only so sibling packages can build on predictable synchronous semantics without inheriting a broader state-management framework.
This package is published as @phcdevworks/spectre-shell-signals. Its source
repository is hosted at
phcdevworks/spectre-shell-signals.
Key capabilities
- Writable signals with explicit
.valuereads and writes - Lazy computed values with dependency tracking and cached recomputation
- Reactive effects with cleanup before re-run and on disposal
- Synchronous, readable behavior that is portable across runtimes
- Small public API surface designed to resist scope drift
Installation
npm install @phcdevworks/spectre-shell-signalsQuick start
import { computed, effect, signal } from "@phcdevworks/spectre-shell-signals";
const count = signal(0);
const doubled = computed(() => count.value * 2);
const stop = effect(() => {
console.log(doubled.value);
});
count.value = 1;
stop();Effects can also register cleanup work that runs before the next execution and when the effect is disposed:
import { effect, signal } from "@phcdevworks/spectre-shell-signals";
const enabled = signal(true);
const stop = effect((onCleanup) => {
if (!enabled.value) {
return;
}
const id = setInterval(() => {
console.log("tick");
}, 1000);
onCleanup(() => clearInterval(id));
});
enabled.value = false;
stop();What this package owns
signal<T>(initialValue)for writable reactive valuescomputed<T>(fn)for lazy derived valueseffect(fn)for reactive side effects- Dependency tracking, invalidation, and cleanup/disposal behavior
- Minimal TypeScript types for the public API
This package should stay at the primitive reactivity layer.
What this package does not own
- Global stores, app-wide state containers, or business logic state layers
- Routers, navigation state, URL params, or shell orchestration
- DOM bindings, renderer integrations, or framework lifecycle adapters
- Async cache/query behavior, persistence, streams, or event buses
- Devtools, inspectors, dashboards, or plugin systems
If a feature is not directly required for signal, computed, effect, tracking, invalidation, or disposal, it does not belong here.
Package exports / API surface
Runtime exports:
signalcomputedeffect
Type exports:
Signal<T>Computed<T>EffectCallbackEffectCleanupStopEffect
Behavior summary:
signal(initialValue)returns an object with a tracked.valuegetter and invalidating settercomputed(fn)is lazy, cached, and recomputes only when read after invalidationeffect(fn)runs immediately, tracks reads during execution, and returns a stop functiononCleanuphandlers run before the next effect execution and when the effect is stopped- Signal writes use
Object.isto skip unchanged updates
Relationship to the rest of Spectre
Spectre keeps responsibilities separate:
@phcdevworks/spectre-tokensowns visual language, semantic roles, and token contracts@phcdevworks/spectre-uiowns token-driven styling, Tailwind helpers, and class recipes@phcdevworks/spectre-shellowns thin shell composition and runtime surface@phcdevworks/spectre-shell-routerowns URL resolution and navigation primitives@phcdevworks/spectre-shell-signalsowns reactive primitives only
That separation keeps the reactivity layer portable and prevents it from becoming a general-purpose runtime or state framework.
Development
Install dependencies, then run the package checks:
npm run checkKey source areas:
src/signal.tssrc/computed.tssrc/effect.tssrc/internals/node.tssrc/internals/tracking.tstests/signals.test.ts
Contributing
When contributing:
- keep the API tiny and explicit
- prefer implementation clarity over abstraction-heavy design
- avoid adding framework concepts or store-like helpers
- add tests before changing reactive semantics
- run npm run check before opening a pull request
Scope discipline is part of the package contract.
License
MIT © PHCDevworks. See LICENSE.
