Back to home

📘 Bonsai Documentation

Wanna grow your state like a pro? 🌱 You've come to the right forest.

🌿 Bonsai Guidebook

Bonsai: Your State Tree Whisperer 🌳✨

Welcome to Bonsai — the chill, lightweight state manager that won't make your brain wilt. Whether you're nurturing a small shrub of global state or a whole enchanted forest of nested components, Bonsai's got you.

🌱 What is Bonsai?

Think of it as your Zen garden for state. You get flat and tree-based state tools that make your React life peaceful and performant.

🎯 Why Bonsai Rocks

  • Flat or Tree? Why not both? Choose your shape — flat for simplicity, tree for structure.
  • Fast like a squirrel 🐿️ — React's useSyncExternalStore keeps re-renders minimal.
  • Middleware magic 🧙 — Log, validate, or cancel updates with wizardry.
  • DevPanel 📊 — Built-in real-time debug panel with editable state fields.

🚀 Next.js + Bonsai = ❤️

Works perfectly in both client and server components. Hydration? Handled. Transitions? Smooth like butter.

What’s new in v1.1.0

  • createStore: one-call setup with options { devtools, middleware }
  • DevTools auto-mount: enable with devtools: true; toggle with Ctrl+Shift+B
  • Koa-style middleware adapter: (next) => (path, value, prev) => next(path, value)
  • Classic APIs remain supported (initTreeState, useTreeBonsai, set, subscribe)

📦 Install It Like It's Hot

npm install @bonsai-ts/stateyarn add @bonsai-ts/statepnpm add @bonsai-ts/statebun add @bonsai-ts/state

Client Components (createStore)

"use client";

import { createStore } from "@bonsai-ts/state";

// Initialize once with options (auto-mount DevTools in dev when enabled)
export const appStore = createStore(
  {
    count: 0,
    user: { name: "elorm", isActive: true },
  },
  { devtools: true }
);

// Use in client components
function Counter() {
  const count = appStore.use<number>("count") || 0;
  return (
    <button onClick={() => appStore.set("count", count + 1)}>
      Increment ({count})
    </button>
  );
}

Server Components

With createStore, the APIs are isomorphic. Define your store in a module and use it from client components. DevTools auto-mount only runs in the browser.

// store.ts
import { createStore } from "@bonsai-ts/state";
export const appStore = createStore({ count: 0 }, { devtools: true });

// app/Counter.tsx (Client Component)
"use client";
import { appStore } from "./store";
export function Counter() {
  const count = appStore.use<number>("count") || 0;
  return <button onClick={() => appStore.set("count", count + 1)}>{count}</button>;
}

// app/page.tsx (Server Component)
import { Counter } from "./Counter";
export default function Page() {
  return <Counter />;
}

Best Practices for Next.js 🎯

  • Client Components — Use Bonsai hooks in components marked with "use client"
  • Server Components — Initialize state on the server and pass it to client components
  • Hydration — Bonsai handles hydration automatically, ensuring smooth server-to-client transitions
  • Performance — Use scoped state for component-specific state to optimize re-renders