npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@shiftbloom-studio/symphony-state

v0.1.0

Published

Orchestrate multiple state sources without a monolithic global store.

Downloads

172

Readme

Symphony State

npm CI license

Orchestrate multiple state sources without a monolithic global store.

Symphony State coordinates local state, React Context, external stores (Zustand/Redux), server state libraries (TanStack Query/SWR), URL params, and browser persistence without taking ownership of those sources. It focuses on deterministic, dependency-driven propagation and atomic transactions so you can keep cross-domain state consistent.

Why Symphony State?

  • Mixed sources drift: local state, URL params, and external stores can diverge.
  • Update storms: independent updates trigger multiple re-renders.
  • Cross-domain dependencies: cart state depends on auth/pricing, etc.

Symphony State provides an orchestration layer that schedules updates in a single wave and keeps dependencies consistent.

Installation

npm install @shiftbloom-studio/symphony-state

Quickstart (AtomAdapter)

import {
  createConductor,
  defineSection,
  createAtomAdapter
} from "@shiftbloom-studio/symphony-state";
import { SymphonyProvider, useSection } from "@shiftbloom-studio/symphony-state/react";

const auth = defineSection({
  key: "auth",
  source: createAtomAdapter({ userId: null as string | null })
});

const conductor = createConductor({ sections: [auth] });

function AuthPanel() {
  const authSection = useSection<{ userId: string | null }>("auth");
  return (
    <button onClick={() => authSection.set({ userId: "42" })}>
      {authSection.value.userId ?? "Login"}
    </button>
  );
}

export function App() {
  return (
    <SymphonyProvider conductor={conductor}>
      <AuthPanel />
    </SymphonyProvider>
  );
}

Quickstart (Zustand + Redux adapters)

import { createZustandAdapter } from "@shiftbloom-studio/symphony-state/adapters/zustand";
import { createReduxAdapter } from "@shiftbloom-studio/symphony-state/adapters/redux";

const zustandSection = defineSection({
  key: "filters",
  source: createZustandAdapter(zustandStore)
});

const reduxSection = defineSection({
  key: "cart",
  source: createReduxAdapter(reduxStore, {
    select: (state) => state.cart,
    update: (next) => ({ type: "cart/replace", payload: next }),
    patch: (partial) => ({ type: "cart/patch", payload: partial })
  })
});

Transactions

conductor.transaction(() => {
  conductor.getSection("auth").set({ userId: "42" });
  conductor.getSection("cart").patch({ ownerId: "42" });
}, "login");

All section updates are staged, resolved in dependency order, committed atomically, and only then are subscribers notified.

Derived sections

import { defineDerivedSection } from "@shiftbloom-studio/symphony-state";

const pricing = defineDerivedSection({
  key: "pricing",
  inputs: ["cart", "auth"],
  compute: (cart, auth) => ({
    total: cart.items.length * (auth.isPremium ? 0.8 : 1)
  })
});

Derived sections are read-only and recompute only when their inputs change.

Next.js patterns

App Router

// app/layout.tsx
"use client";
import { SymphonyProvider } from "@shiftbloom-studio/symphony-state/react";
import { conductor } from "./symphony";

export default function RootLayout({ children }) {
  return <SymphonyProvider conductor={conductor}>{children}</SymphonyProvider>;
}

Pages Router

// pages/_app.tsx
import { SymphonyProvider } from "@shiftbloom-studio/symphony-state/react";
import { conductor } from "../symphony";

export default function App({ Component, pageProps }) {
  return (
    <SymphonyProvider conductor={conductor}>
      <Component {...pageProps} />
    </SymphonyProvider>
  );
}

Hydration helper

import { SymphonyScript } from "@shiftbloom-studio/symphony-state/react";

<SymphonyScript state={{ auth: { userId: "42" } }} />;

Persistence

import { createStorageSink } from "@shiftbloom-studio/symphony-state";

const auth = defineSection({
  key: "auth",
  source: createAtomAdapter({ userId: null }),
  persist: createStorageSink({
    key: "symphony-auth",
    throttleMs: 200
  })
});

DevTools (optional)

import { SymphonyDevTools } from "@shiftbloom-studio/symphony-state/devtools";

<SymphonyDevTools maxTransactions={10} />;

DevTools are dev-only, tree-shakeable, and unstyled apart from minimal CSS variables.

API Reference

| API | Description | | ----------------------------------- | ---------------------------------------------- | | createConductor(config) | Create a conductor instance. | | defineSection(def) | Define a section backed by a source adapter. | | defineDerivedSection(def) | Define a derived, read-only section. | | createAtomAdapter(initial) | Built-in minimal store. | | createExternalStoreAdapter(store) | Wrap an external get/set/subscribe store. | | createUrlParamsAdapter(options) | Sync with URL search params. | | createStorageSink(options) | Persist section values to storage. | | SymphonyProvider | React context provider. | | useSection(key) | React hook for section read/write. | | useSelector(key, selector) | Selector hook with equality. | | createSymphony(config) | Typed helper that wires a conductor and hooks. | | SymphonyDevTools | Optional devtools panel. |

Design principles

  • Orchestration, not ownership: Symphony State coordinates existing stores.
  • Predictable updates: deterministic, dependency-ordered commit waves.
  • Tree-shakeable: optional adapters and devtools ship as separate entrypoints.
  • SSR-safe: no unguarded window usage in core.

License

MIT