Install Store and connect your first Tap resource to React.
Store (@assistant-ui/store) connects Tap resources to React with scoped, type-safe state management.
Installation
npm install @assistant-ui/store @assistant-ui/tapDefine your client types
Register your clients by augmenting the ScopeRegistry interface. This gives you type safety across all Store hooks.
import "@assistant-ui/store";
declare module "@assistant-ui/store" {
interface ScopeRegistry {
counter: {
methods: {
getState: () => { count: number };
increment: () => void;
};
};
}
}Create a resource
Define a Tap resource that returns ClientOutput<"counter">. This connects the resource's methods to the client type you just registered.
import { resource, tapState, tapMemo } from "@assistant-ui/tap";
import type { ClientOutput } from "@assistant-ui/store";
export const CounterResource = resource(
({ initialCount = 0 }: { initialCount?: number }): ClientOutput<"counter"> => {
const [count, setCount] = tapState(initialCount);
const state = tapMemo(() => ({ count }), [count]);
return {
getState: () => state,
increment: () => setCount((c) => c + 1),
};
},
);Use it in React
Use useAui to create a client, AuiProvider to provide it to the tree, and useAuiState to subscribe to state.
"use client";
import { useAui, AuiProvider } from "@assistant-ui/store";
import { CounterResource } from "@/lib/store/counter-store";
import { CounterDisplay } from "./CounterDisplay";
export const CounterApp = () => {
const aui = useAui({
counter: CounterResource({ initialCount: 0 }),
});
return (
<AuiProvider value={aui}>
<CounterDisplay />
</AuiProvider>
);
};"use client";
import { useAui, useAuiState } from "@assistant-ui/store";
export const CounterDisplay = () => {
const count = useAuiState((s) => s.counter.count);
const aui = useAui();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => aui.counter().increment()}>+</button>
</div>
);
};useAuiState((s) => s.counter.count) subscribes to just the count value — the component only re-renders when it changes.
aui.counter() returns the methods object, so aui.counter().increment() calls the increment method you defined in the resource.