Skip to content

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";
Hooks — useSharedState, useLeader, …Hooks
Factories — defineChannel, createStoreHooksHooks — they return hooks, so they’re documented alongside them
Engines — createSharedStore, createChannel, createPresence, createLeaderEngines
Version clock — newer, VersionThe version clock
Transports — NoopTransport, BroadcastChannelTransport (plus MemoryHub on /testing)Transports
Debug seam — observeBus, enableDebug, getBusNamesDebugging
Escape hatches — getSharedStore, getLeader, DEFAULT_NAME, the error classesEscape hatches
Cross-origin windows — openWindow, connectToOpeneruseWindowResult
Persistence adapters — localStorageAdapter, webStorageAdaptercreateStoreHooks

Every signature is also generated from the source in the API reference. This section is the prose; that one is the exhaustive list.

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" });
// …later
store.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 identity

That’s why presence works even in a tab that never created a Presence: the heartbeat lives on the bus, not on the engine.