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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@sterra/microscope

v0.0.16

Published

🔬 Atomic state manager for React.

Readme

Microscope 🔬

Atomic state manager for React.

Table of Contents

Features

  • 🧬 Small core: A minimal API that’s easy to learn and easy to debug.
  • 🎯 Focused updates: Components only re-render when the part of the state they care about actually changes.
  • 🔧 Useful utilities: Persistence, derived values, and store combinations without extra packages.
  • 🛠️ Clear behavior: No hidden magic or unexpected side effects.
  • 🚫 Low overhead: Lightweight by design, both conceptually and in bytes.

Installation

npm install @sterra/microscope
# or
yarn add @sterra/microscope
# or
pnpm add @sterra/microscope

Quick Start

1. Create a Store

Create a store anywhere in your app. It lives outside of React.

import { store } from "@sterra/microscope";

interface CounterState {
  count: number;
}

export const $counter = store<CounterState>({ count: 0 });

You can update it from anywhere (components, utils, etc.):

export const increment = () => {
  $counter.set((prev) => ({ count: prev.count + 1 }));
};

2. Use in React

Use the hook to subscribe to updates.

import { useStore } from "@sterra/microscope";
import { $counter, increment } from "./stores/counter";

export function Counter() {
  // Select only what you need.
  // The component re-renders ONLY when the selected value changes.
  const count = useStore($counter, (state) => state.count);

  return <button onClick={increment}>Count is {count}</button>;
}

Core Concepts

Updating State

You can set state directly, use a functional updater, or perform shallow merges.

// Replace state
$store.set({ count: 10 });

// Update based on previous state
$store.set((prev) => ({ count: prev.count + 1 }));

// Shallow Merge (Patch)
// Useful for updating a single property in a large object
$store.patch({ count: 5 });

Optimized Selectors

useStore accepts a selector and an optional equality function. It automatically handles memoization to ensure stable object references don't trigger re-renders.

// This component will NOT re-render if 'user.name' stays the same,
// even if other parts of the store (like 'user.age') update.
const userName = useStore($user, (state) => state.user.name);

Utilities

Microscope comes with powerful built-in utilities to handle common state patterns.

Persistence (persisted)

Automatically sync state with localStorage (or sessionStorage). This utility handles SSR safety and Cross-Tab Synchronization automatically.

import { persisted } from "@sterra/microscope";

export const $theme = persisted(
  "app-theme",
  { mode: "light" },
  {
    storage: "local", // or "session" or a custom engine
    skipHydration: false,
  }
);

// Usage is identical to a normal store
const theme = useStore($theme);

Computed State (derive)

Create read-only stores that automatically update when their parent changes.

const $count = store({ val: 5 });

// $doubled will automatically update whenever $count changes
const $doubled = $count.derive((s) => s.val * 2);

Combining Stores (combine)

Merge multiple stores into a single, reactive read-only stream.

import { store, combine } from "@sterra/microscope";

const $user = store({ name: "Alice" });
const $tasks = store({ list: [] });

// Combines updates from both stores
const $summary = combine([$user, $tasks], (user, tasks) => {
  return `${user.name} has ${tasks.list.length} tasks`;
});

Middlewares

Microscope supports a robust middleware system that allows you to intercept, modify, or log state changes before they are committed to the store.

How it works

A middleware is a function that receives the previous state, the next (proposed) state, and the store instance. It returns the final state to be saved.

type Middleware<T> = (prev: T, next: T, store: Store<T>) => T;

Example: Logging Middleware

Here is a simple middleware that logs every state change to the console.

import { store, type Middleware } from "@sterra/microscope";

const logger: Middleware<any> = (prev, next) => {
  console.log("Previous:", prev);
  console.log("Next:", next);

  return next; // Return the state unchanged
};

const $counter = store({ count: 0 }, [logger]);

$counter.set({ count: 5 });
// Console:
// Previous: { count: 0 }
// Next: { count: 5 }

Example: Validation & Data modification

You can use middleware to enforce rules, ensuring your state is always valid.

// Ensure the counter never goes below zero
const nonNegative: Middleware<{ count: number }> = (prev, next) => {
  if (next.count < 0) {
    console.warn("Counter cannot be negative. Reverting to 0.");

    return { ...next, count: 0 }; // Modify the state on the fly
  }

  return next;
};

const $counter = store({ count: 0 }, [nonNegative]);

$counter.set({ count: -5 });
console.log($counter.get()); // { count: 0 }

Order of Execution

Middlewares run in the order they are passed to the store. The output of the first middleware becomes the next input of the second, forming a pipeline.

const $store = store(initial, [
  logger, // Runs first
  validator, // Runs second (receives input from logger)
  persisted, // Runs last (saves the final validated value)
]);

Integrations

Immer Support

If you prefer mutable syntax (e.g., draft.push(...)), you can use the official Immer integration.

Installation

npm install @sterra/microscope-immer immer

Usage

Wrap your store with withImmer.

import { store } from "@sterra/microscope";
import { withImmer } from "@sterra/microscope-immer";

const $todos = withImmer(store({ items: [] }));

// Now 'set' accepts a standard Immer producer
$todos.set((draft) => {
  // You can mutate the draft directly!
  draft.items.push({ id: 1, text: "Buy Milk" });
});