hashbrown

Getting Started

Guide

  1. 1. Basics of AI
  2. 2. System Instructions
  3. 3. Message History
  4. 4. Skillet Schema
  5. 5. Streaming
  6. 6. Tool Calling
  7. 7. Structured Output
  8. 8. Generative UI
  9. 9. JavaScript Runtime

Recipes

  1. Natural Language Forms
  2. UI Chatbot with Tools
  3. UI Kits
  4. Predictive Suggestions
  5. Remote MCP
  6. Threads
  7. Magic Text
  8. JSON Parser
  9. CopilotKit
  10. Local Models

Platforms

UI Kits in React

UI Kits package trusted components into reusable generative UI building blocks. A kit gives Hashbrown the schema it needs to generate UI and the renderer it needs to turn a resolved UI value into React elements.

Use UI Kits when you want to:

  • Reuse the same component set across useUiChat(), useUiCompletion(), and direct rendering.
  • Compose smaller kits into larger product kits.
  • Include prompt examples with the component schema.
  • Render fallback components while props are still streaming.
  • Validate UI generated outside of a Hashbrown chat hook.

1. Create a Kit

Expose each trusted component, then pass those components to useUiKit().

import { s } from '@hashbrownai/core';
import { exposeComponent, useUiKit } from '@hashbrownai/react';

function ProductCard({ name, summary }: { name: string; summary: string }) {
  return (
    <article>
      <h3>{name}</h3>
      <p>{summary}</p>
    </article>
  );
}

export function useProductUiKit() {
  return useUiKit({
    components: [
      exposeComponent(ProductCard, {
        name: 'ProductCard',
        description: 'Show a product recommendation.',
        props: {
          name: s.string('Product name'),
          summary: s.streaming.string('Why this product is relevant'),
        },
      }),
    ],
  });
}

useUiKit() returns:

  • components: the normalized exposed component list.
  • registry: component definitions keyed by name.
  • schema: the wrapper schema for UI output.
  • serializedSchema: a stable serialized form of the schema.
  • render(value): a React renderer for resolved UI wrapper values.

2. Use a Kit with UI Chat

Pass a kit wherever Hashbrown accepts components.

import { useUiChat } from '@hashbrownai/react';
import { useProductUiKit } from './product-ui-kit';

export function Assistant() {
  const productKit = useProductUiKit();
  const { messages, sendMessage } = useUiChat({
    model: 'gpt-5',
    system:
      'Help the user compare products. Render product recommendations when useful.',
    components: [productKit],
  });

  return (
    <ChatView
      messages={messages}
      onSubmit={(message) => sendMessage(message)}
    />
  );
}

The hook composes the kit, sends the kit schema to the model, validates complete UI output, and renders only the trusted components in the registry.


3. Compose Kits

Kits can include other kits. This lets feature teams own smaller component sets without duplicating schemas.

import { exposeMarkdown, useUiKit } from '@hashbrownai/react';
import { useProductUiKit } from './product-ui-kit';
import { useCheckoutUiKit } from './checkout-ui-kit';

export function useCommerceUiKit() {
  const productKit = useProductUiKit();
  const checkoutKit = useCheckoutUiKit();

  return useUiKit({
    components: [
      productKit,
      checkoutKit,
      exposeMarkdown({
        citations: true,
        caret: true,
      }),
    ],
  });
}

Component names must be unique unless they point at the same component implementation. Hashbrown throws on name collisions so a prompt cannot resolve one tag name to two different components.


4. Add Examples

Examples become part of the wrapper schema description. Use them to show good UI structure, not to list every possible component.

import { prompt } from '@hashbrownai/core';
import { useUiKit } from '@hashbrownai/react';

export function useProductUiKit() {
  return useUiKit({
    components: [productCard],
    examples: prompt`
      <ui>
        <ProductCard
          name="Trail Mix"
          summary="High-protein snack with a balanced calorie profile."
        />
      </ui>
    `,
  });
}

If an example references a component that is not in the kit, Hashbrown raises an error instead of silently sending bad guidance to the model.


5. Render Directly

Use kit.schema and kit.render() when the UI value comes from somewhere other than useUiChat() or useUiCompletion(), such as a server response, test fixture, or saved thread.

import type { s } from '@hashbrownai/core';
import { useProductUiKit } from './product-ui-kit';

export function SavedRecommendation({
  value,
}: {
  value: s.Infer<ReturnType<typeof useProductUiKit>['schema']>;
}) {
  const kit = useProductUiKit();

  return <>{kit.render(value)}</>;
}

render() validates the UI once all props and children are complete. While the UI is still streaming, it renders the best partial value it can.


6. Add Fallback Components

Fallback components render while props are still streaming. Use them when the final component needs required props that may not be complete yet.

import type { ComponentFallbackProps } from '@hashbrownai/core';
import { s } from '@hashbrownai/core';
import { exposeComponent, useUiKit } from '@hashbrownai/react';

function ProductCard({ name, summary }: { name: string; summary: string }) {
  return (
    <article>
      {name}: {summary}
    </article>
  );
}

function ProductCardFallback({ partialProps }: ComponentFallbackProps) {
  return (
    <article>
      <h3>{String(partialProps?.name ?? 'Choosing product...')}</h3>
      <p>{String(partialProps?.summary ?? '')}</p>
    </article>
  );
}

export function useProductUiKit() {
  return useUiKit({
    components: [
      exposeComponent(ProductCard, {
        name: 'ProductCard',
        description: 'Show a product recommendation.',
        fallback: ProductCardFallback,
        props: {
          name: s.string('Product name'),
          summary: s.streaming.string('Recommendation summary'),
        },
      }),
    ],
  });
}

Fallbacks keep streaming UI stable without making every production component accept incomplete props.

UI Kits in React 1. Create a Kit 2. Use a Kit with UI Chat 3. Compose Kits 4. Add Examples 5. Render Directly 6. Add Fallback Components