Package Exports
- @front10/generative-ui
- @front10/generative-ui/examples
Readme
@front10/generative-ui
A complete abstraction for creating generative UI components that automatically display when specific tools are executed in chat. Designed to work with Vercel AI SDK 5.0 and provide a simple, scalable, and reusable way to create dynamic user experiences with interactive feedback capabilities.
π Installation
npm install @front10/generative-ui
# or
yarn add @front10/generative-ui
# or
pnpm add @front10/generative-ui
π¦ What's Included
Core Package
import {
GenerativeUIProvider,
useGenerativeUI,
GenerativeUIRegistry,
useRegisterGenerativeComponent,
GenerativeUIRenderer,
useRenderGenerativeUI,
UserAction
} from '@front10/generative-ui';
Examples
import {
productCardExample,
imageGalleryExample,
sentimentAnalyzerExample,
examples
} from '@front10/generative-ui/examples';
π― Quick Start
1. Setup Provider
// app/layout.tsx
import { GenerativeUIProvider } from '@front10/generative-ui';
export default function RootLayout({ children }) {
return (
<html>
<body>
<GenerativeUIProvider>{children}</GenerativeUIProvider>
</body>
</html>
);
}
2. Register Components with Action Handlers
// components/chat.tsx
import { useGenerativeUI } from '@front10/generative-ui';
import { useGenerativeActions } from '@/hooks/use-generative-actions';
import { productCardExample } from '@front10/generative-ui/examples';
export function Chat() {
const { registerComponent } = useGenerativeUI();
const { handleUserAction } = useGenerativeActions();
// Register components with individual action handlers
React.useLayoutEffect(() => {
registerComponent({
toolId: 'getProductInfo',
LoadingComponent: ProductCardLoading,
SuccessComponent: ProductCard,
ErrorComponent: ProductCardError,
onUserAction: action => {
console.log('Product Card action:', action);
handleUserAction(action);
}
});
registerComponent({
toolId: 'searchImages',
LoadingComponent: ImageGalleryLoading,
SuccessComponent: ImageGallery,
ErrorComponent: ImageGalleryError,
onUserAction: action => {
console.log('Image Gallery action:', action);
handleUserAction(action);
}
});
}, [registerComponent, handleUserAction]);
return <div>Chat Component</div>;
}
3. Render in Messages
// components/message.tsx
import { useRenderGenerativeUI } from '@front10/generative-ui';
export function Message({ message }) {
const renderGenerativeUI = useRenderGenerativeUI();
return (
<div>
{message.parts?.map((part, index) => {
if (part.type.startsWith('tool-')) {
const toolId = part.type.replace('tool-', '');
const { toolCallId, state } = part;
const input = 'input' in part ? part.input : undefined;
const output = 'output' in part ? part.output : undefined;
const error = 'errorText' in part ? part.errorText : undefined;
const renderedComponent = renderGenerativeUI({
toolId,
state,
input,
output,
error,
toolCallId
});
if (renderedComponent) {
return <div key={toolCallId}>{renderedComponent}</div>;
}
}
return null;
})}
</div>
);
}
π¨ Interactive Examples
Product Card with Multiple Actions
import { useGenerativeActions } from '@/hooks/use-generative-actions';
export function Chat() {
const { handleUserAction } = useGenerativeActions();
registerComponent({
toolId: 'getProductInfo',
LoadingComponent: ProductCardLoading,
SuccessComponent: ProductCard,
ErrorComponent: ProductCardError,
onUserAction: action => {
console.log('Product action:', action);
handleUserAction(action);
}
});
// The component automatically receives onAction prop
// and can trigger multiple actions:
// - add_to_cart
// - view_details
// - add_to_wishlist
// - share_product
}
Calendar Events with Complex Interactions
import { useGenerativeActions } from '@/hooks/use-generative-actions';
export function Chat() {
const { handleUserAction } = useGenerativeActions();
registerComponent({
toolId: 'getEvents',
LoadingComponent: CalendarLoading,
SuccessComponent: CalendarComponent,
ErrorComponent: CalendarError,
onUserAction: action => {
console.log('Calendar action:', action);
handleUserAction(action);
}
});
// The calendar component supports multiple actions:
// - create_event
// - edit_event
// - delete_event
// - confirm_event
// - cancel_event
// - view_event_details
// - share_event
}
π§ API Reference
Core Components
GenerativeUIProvider
The main provider that handles component registration and rendering with interactive feedback.
<GenerativeUIProvider onUserAction={handleUserAction}>
{children}
</GenerativeUIProvider>
useGenerativeUI
Hook to access the Generative UI context.
const { registerComponent, renderComponent, onUserAction } = useGenerativeUI();
GenerativeUIRegistry
Component for automatically registering multiple components.
<GenerativeUIRegistry components={[component1, component2]} />
useRegisterGenerativeComponent
Helper hook for registering a single component.
useRegisterGenerativeComponent({
toolId: 'myTool',
LoadingComponent: MyLoading,
SuccessComponent: MySuccess,
ErrorComponent: MyError
});
GenerativeUIRenderer
Component that renders components based on the tool's state.
<GenerativeUIRenderer
toolId='myTool'
state='output-available'
input={input}
output={output}
error={error}
toolCallId='call-123'
/>
useRenderGenerativeUI
Hook helper for rendering components from the message system.
const renderGenerativeUI = useRenderGenerativeUI();
Types
UserAction
interface UserAction {
toolId: string; // Identificador del tool/componente
toolCallId?: string; // ID especΓfico de la llamada al tool
action: string; // Identificador de la acciΓ³n (ej: "accept", "cancel", "select")
data?: any; // Datos adicionales de la acciΓ³n
context?: any; // Contexto adicional
}
GenerativeUIComponent<TInput, TOutput>
interface GenerativeUIComponent<TInput = any, TOutput = any> {
toolId: string;
LoadingComponent?: React.ComponentType<{
input?: TInput;
onAction?: (action: Omit<UserAction, 'toolId'>) => void;
}>;
SuccessComponent: React.ComponentType<{
output: TOutput;
input?: TInput;
onAction?: (action: Omit<UserAction, 'toolId'>) => void;
}>;
ErrorComponent?: React.ComponentType<{
error: string;
input?: TInput;
onAction?: (action: Omit<UserAction, 'toolId'>) => void;
}>;
}
ToolState
type ToolState =
| 'input-streaming'
| 'input-available'
| 'output-available'
| 'output-error';
GenerativeUIRendererProps
interface GenerativeUIRendererProps {
toolId: string;
state: ToolState;
input?: any;
output?: any;
error?: string;
toolCallId: string;
}
π― Interactive Feedback Examples
Using the Built-in Hook
Create a custom hook to handle user actions:
// hooks/use-generative-actions.ts
'use client';
import { useChat } from '@ai-sdk/react';
export interface UserAction {
toolId: string;
toolCallId?: string;
action: string;
data?: any;
context?: any;
}
export function useGenerativeActions() {
const { sendMessage } = useChat();
const handleUserAction = (action: UserAction) => {
// Create descriptive messages based on actions
let content = '';
switch (action.action) {
case 'add_to_cart':
content = `I want to add ${
action.data?.productName || 'this product'
} to my cart`;
break;
case 'view_details':
content = `Show me more details about ${
action.data?.productName || 'this product'
}`;
break;
default:
content = `I performed the action: ${action.action}`;
}
// Send to LLM using sendMessage (Vercel AI SDK v5)
sendMessage({
role: 'user',
parts: [
{
type: 'text',
text: content
}
]
});
};
return { handleUserAction };
}
Creating Interactive Components
// Example: Product Card with multiple actions
export const ProductCard: React.FC<ProductCardProps> = ({
output,
onAction
}) => {
const { product } = output;
const handleAddToCart = () => {
onAction?.({
action: 'add_to_cart',
data: {
productId: product.id,
productName: product.name,
price: product.price
},
context: { timestamp: Date.now() }
});
};
const handleViewDetails = () => {
onAction?.({
action: 'view_details',
data: { productId: product.id }
});
};
return (
<div className='product-card'>
<h3>{product.name}</h3>
<p>{product.price}</p>
<div className='actions'>
<button onClick={handleAddToCart}>Add to Cart</button>
<button onClick={handleViewDetails}>View Details</button>
</div>
</div>
);
};
Handling Actions in Your App (Vercel AI SDK v5)
// In your main chat component
const { sendMessage } = useChat();
const handleUserAction = (action: UserAction) => {
// Create descriptive messages based on actions
let content = '';
switch (action.action) {
case 'add_to_cart':
content = `I want to add ${
action.data?.productName || 'this product'
} to my cart`;
break;
case 'view_details':
content = `Show me more details about ${
action.data?.productName || 'this product'
}`;
break;
default:
content = `I performed the action: ${action.action}`;
}
// Send to LLM using sendMessage (Vercel AI SDK v5)
sendMessage({
role: 'user',
parts: [
{
type: 'text',
text: content
}
]
});
};
Handling Actions in Your App (Vercel AI SDK v4 and earlier)
// For older versions of Vercel AI SDK
const { append } = useChat();
const handleUserAction = (action: UserAction) => {
let content = '';
switch (action.action) {
case 'add_to_cart':
content = `I want to add ${
action.data?.productName || 'this product'
} to my cart`;
break;
default:
content = `I performed the action: ${action.action}`;
}
// Send to LLM using append (Vercel AI SDK v4 and earlier)
append({
role: 'user',
content
});
};
π― Benefits
- Separation of concerns: UI separated from tool logic
- Reusability: Components reusable in different contexts
- Maintainability: Easy to maintain and extend
- User experience: Immediate visual feedback during execution
- Consistency: Uniform experience across the application
- Scalability: Easy to add new tools and components
- Type safety: Complete TypeScript for better DX
- Compatibility: Works with any Vercel AI SDK implementation
- Interactive feedback: Components can send actions back to the LLM
- Multiple actions: Single components can trigger multiple different actions
- Per-component handlers: Each component can have its own action handler
π Project Status
β Production ready - The abstraction is fully functional, documented, and tested with interactive feedback capabilities.
π Examples
See the examples/
directory for complete working examples:
- Product Card: Product information display with cart, wishlist, and sharing actions
- Image Gallery: Image search with interactive gallery and selection actions
- Sentiment Analyzer: Text sentiment analysis with visualizations and feedback actions
- Calendar Events: Event management with create, edit, delete, and confirmation actions
π€ Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
π License
This project is licensed under the MIT License - see the LICENSE file for details.
Need help? Check the examples in the examples/
directory or open an issue on GitHub.