Documents
README
README
Type
External
Status
Published
Created
Mar 17, 2026
Updated
Mar 26, 2026
Updated by
Dosu Bot

@assistant-ui/store Example App#

This is a Next.js application demonstrating the @assistant-ui/store package.

Features Demonstrated#

  • Client Registry: Module augmentation for type-safe client definitions
  • tapClientList: Managing lists with index and key lookup
  • tapAssistantEmit: Emitting and subscribing to scoped events
  • Derived: Creating derived client scopes from parent resources
  • Provider Pattern: Scoped access to list items via FooProvider
  • Component Composition: Render props pattern with components prop

Getting Started#

# Install dependencies (from monorepo root)
pnpm install

# Run the development server
cd examples/store-example
pnpm dev

Open http://localhost:3000 to see the example.

Project Structure#

  • lib/store/foo-scope.ts - Type definitions via module augmentation:
    • Client registry definitions (foo, fooList)
    • State, methods, meta, and events types
  • lib/store/foo-store.tsx - Store implementation with:
    • Resource implementations (FooItemResource, FooListResource)
    • Provider component (FooProvider)
    • FooList mapping component
  • lib/example-app.tsx - Example app with styled components:
    • Foo component with update/delete actions
    • EventLog component demonstrating event subscriptions
    • ExampleApp with layout and styling
  • app/page.tsx - Main page that renders the ExampleApp

Key Concepts#

Client Registry#

declare module "@assistant-ui/store" {
  interface ScopeRegistry {
    foo: {
      state: { id: string; bar: string };
      methods: {
        getState: () => FooState;
        updateBar: (newBar: string) => void;
        remove: () => void;
      };
      meta: {
        source: "fooList";
        query: { index: number } | { key: string };
      };
      events: {
        "foo.updated": { id: string; newValue: string };
        "foo.removed": { id: string };
      };
    };
  }
}

Resource Implementation#

const FooListResource = resource(
  ({ initialValues }): ClientOutput<"fooList"> => {
    const emit = tapAssistantEmit();

    const foos = tapClientList({
      initialValues: initialValues ? [/* ... */] : [],
      getKey: (foo) => foo.id,
      resource: FooItemResource,
    });

    return {
      state: { foos: foos.state },
      methods: {
        getState: () => state,
        foo: foos.get,
        addFoo: () => { /* ... */ },
      },
    };
  },
);

Provider Pattern with Derived#

const FooProvider = ({ index, children }) => {
  const aui = useAui({
    foo: Derived({
      source: "fooList",
      query: { index },
      get: (aui) => aui.fooList().foo({ index }),
    }),
  });
  return <AuiProvider value={aui}>{children}</AuiProvider>;
};

Event Subscriptions#

// Subscribe to specific events within a scope
useAuiEvent("foo.updated", (payload) => {
  console.log(`Updated to: ${payload.newValue}`);
});

// Subscribe to all events using wildcard
useAuiEvent("*", (data) => {
  console.log(data.event, data.payload);
});

Learn More#