Share State Across Sprincul Models with the Global Store
Use Sprincul.store to set, get, and subscribe to shared key/value state. Any model on the page can read and react to store changes without direct coupling.
The global store gives every model on your page access to the same key/value state without requiring you to wire models together manually. It is useful whenever two or more models need to react to the same piece of data — a selected theme, a logged-in user, a notification count — without one model knowing about the other’s implementation.
Sprincul.store is a flat key/value map backed by nanostores atoms. Any model (or any script on the page) can read from it, write to it, and subscribe to changes. You do not need to configure it; it is available as soon as you import Sprincul.
Writes value under key. If the key does not exist yet, Sprincul creates the underlying atom automatically. All active subscribers for that key are notified.
Registers callback to run whenever the value at key changes. Returns an unsubscribe function you can call to stop listening.
const unsubscribe = Sprincul.store.subscribe('theme', (value) => { console.log('theme changed to:', value);});// Later, when you no longer need updates:unsubscribe();
subscribe fires after a value changes, not when you first call it. To read the current value at subscription time, call Sprincul.store.get(key) before subscribing.
Removes all entries from the store. Existing subscribers are not automatically cleaned up, so call unsubscribe() on any active subscriptions before clearing if you want to avoid stale callbacks.
You can write to the store at any point — before registering models, before calling Sprincul.init(), or after. There is no required ordering. If you want a default value in place before any model reads or subscribes, set it early:
// Seed a default before initSprincul.store.set('theme', 'light');Sprincul.register('ThemeSwitcher', ThemeSwitcher);Sprincul.register('HeroSection', HeroSection);Sprincul.init();
Practical example: theme switcher and themed component
The following example shows two independent models communicating through the store. ThemeSwitcher writes the active theme, and HeroSection reads and reacts to it.
Reading the store in beforeInit() and subscribing in afterInit() is the recommended pattern. beforeInit() runs before bindings are attached, so any state you set there is ready when the first render pass fires.
Every call to subscribe returns an unsubscribe function. Hold onto it and call it when the model is torn down or when you no longer need the subscription. If you subscribe inside afterInit(), a good pattern is to store the unsubscribe function on the instance:
import { SprinculModel, Sprincul } from 'sprincul';export default class Sidebar extends SprinculModel { #unsubscribeUser = null; afterInit() { this.#unsubscribeUser = Sprincul.store.subscribe('currentUser', (user) => { this.state.username = user?.name ?? 'Guest'; }); } // Call this when you remove the model from the DOM, or let Sprincul's // built-in cleanup handle it if the element is removed naturally. teardown() { this.#unsubscribeUser?.(); }}
Sprincul automatically destroys model instances when their root element is removed from the DOM, so subscriptions tied to that model’s lifetime are cleaned up as part of normal page lifecycle management.