Core without React
The hooks are a thin React skin over an engine that doesn’t know React exists. This section documents that engine — everything you can call from a worker, a plain module, a test, or another framework.
You already have it. use-everywhere re-exports the whole of
@use-everywhere/core, so there is one dependency either way:
import { createSharedStore, newer } from 'use-everywhere';// identical to:import { createSharedStore, newer } from '@use-everywhere/core';Install @use-everywhere/core directly only if you have no React at all.
Test seams live on a testing subpath rather than the package root, so a
multi-tab simulation harness never reaches your production bundle:
import { MemoryHub } from 'use-everywhere/testing';// identical to:import { MemoryHub } from '@use-everywhere/core/testing';What lives where
Section titled “What lives where”Hooks — useSharedState, useLeader, … | Hooks |
Factories — defineChannel, createStoreHooks | Hooks — they return hooks, so they’re documented alongside them |
Engines — createSharedStore, createChannel, createPresence, createLeader | Engines |
Version clock — newer, Version | The version clock |
Transports — NoopTransport, BroadcastChannelTransport (plus MemoryHub on /testing) | Transports |
Debug seam — observeBus, enableDebug, getBusNames | Debugging |
Escape hatches — getSharedStore, getLeader, DEFAULT_NAME, the error classes | Escape hatches |
Cross-origin windows — openWindow, connectToOpener | useWindowResult |
Persistence adapters — localStorageAdapter, webStorageAdapter | createStoreHooks |
Every signature is also generated from the source in the API reference. This section is the prose; that one is the exhaustive list.
The one rule
Section titled “The one rule”An engine is a resource, not a value. It holds a bus, a heartbeat, and listeners, so whatever you create, you close:
const store = createSharedStore('settings', { theme: 'dark' });// …laterstore.close();The React hooks handle this for you — they memoise one engine per name for the lifetime of the page, which is why there’s no Provider and no cleanup to write. Outside React, it’s yours.
Engines sharing a name share a bus, and therefore share one clientId and
one underlying BroadcastChannel:
const store = createSharedStore('app', {});const presence = createPresence('app');
store.clientId === presence.clientId; // true — same tab, same identityThat’s why presence works even in a tab that never created a Presence: the
heartbeat lives on the bus, not on the engine.