AI SDK Tools
AI SDK Tools

Artifacts

Advanced streaming interfaces for AI applications. Create structured, type-safe artifacts that stream real-time updates from AI tools to React components with progress tracking and error handling.

npm install @ai-sdk-tools/artifacts

What it does

🌊 Streaming

Stream real-time updates from AI tools to React components with smooth, responsive interfaces.

📊 Progress

Track progress and show loading states as AI tools process requests and generate responses.

🔒 Type Safety

Full TypeScript support with schema validation using Zod for type-safe data structures.

⚡ Performance

Optimized rendering with selective updates and efficient state management.

🛠️ Error Handling

Built-in error handling with retry mechanisms and graceful fallbacks.

🎨 Customizable

Highly customizable with support for custom UI components and styling.

Getting Started

1. Install the package

npm install @ai-sdk-tools/artifacts

2. Create an artifact

import { artifact } from '@ai-sdk-tools/artifacts'
import { z } from 'zod'

const burnRateArtifact = artifact('burn-rate', z.object({
  monthlyBurn: z.number(),
  runway: z.number(),
  title: z.string(),
  stage: z.enum(['loading', 'processing', 'complete']).default('loading'),
}))

3. Use in your component

import { useArtifact } from '@ai-sdk-tools/artifacts/client'

function BurnRateChart() {
  const { data, status, error, progress } = useArtifact(burnRateArtifact)
  
  if (status === 'error') return <div>Error: {error}</div>
  if (!data) return <div>Loading...</div>
  
  return (
    <div>
      <h2>{data.title}</h2>
      <p>Monthly Burn: ${data.monthlyBurn.toLocaleString()}</p>
      <p>Runway: {data.runway} months</p>
      {progress && <div>Progress: {Math.round(progress * 100)}%</div>}
    </div>
  )
}

Features

Schema Validation

Define data structures with Zod schemas for type safety and validation:

const userProfileArtifact = artifact('user-profile', z.object({
  name: z.string(),
  email: z.string().email(),
  avatar: z.string().url().optional(),
  preferences: z.object({
    theme: z.enum(['light', 'dark']),
    notifications: z.boolean(),
  }),
}))

Progress Tracking

Track progress and show loading states:

function ProgressBar() {
  const { progress, status, isActive } = useArtifact(processingArtifact)
  
  return (
    <div>
      {isActive && (
        <div className="w-full bg-gray-200 rounded-full h-2.5">
          <div 
            className="bg-blue-600 h-2.5 rounded-full" 
            style={{ width: `${(progress || 0) * 100}%` }}
          />
        </div>
      )}
      <p>Status: {status}</p>
    </div>
  )
}

Error Handling

Built-in error handling with retry mechanisms:

const resilientArtifact = artifact('resilient-data', z.object({
  data: z.string(),
  status: z.enum(['idle', 'loading', 'complete', 'error']).default('idle')
}))

function ResilientComponent() {
  const { data, status, error } = useArtifact(resilientArtifact, {
    onError: (error) => {
      console.error('Artifact error:', error)
      // Custom error handling
    },
    onComplete: (data) => {
      console.log('Success!', data)
    }
  })
  
  return <div>{status === 'error' ? error : data?.data}</div>
}

API Reference

artifact(id, schema)

Create a new artifact definition with schema validation:

import { artifact } from '@ai-sdk-tools/artifacts'
import { z } from 'zod'

const myArtifact = artifact(
  'unique-id', // Unique artifact identifier
  z.object({   // Zod schema for type safety
    title: z.string(),
    data: z.array(z.number()).default([]),
    status: z.enum(['idle', 'loading', 'complete']).default('idle')
  })
)

useArtifact(artifact, callbacks?)

Hook for consuming a specific streaming artifact:

import { useArtifact } from '@ai-sdk-tools/artifacts/client'

const {
  data,        // Current artifact payload (typed)
  status,      // 'idle' | 'loading' | 'streaming' | 'complete' | 'error'
  progress,    // Progress value (0-1)
  error,       // Error message if failed
  isActive,    // Whether artifact is currently processing
  hasData,     // Whether artifact has any data
} = useArtifact(myArtifact, {
  onUpdate: (data, prevData) => console.log('Updated:', data),
  onComplete: (data) => console.log('Done!', data),
  onError: (error) => console.error('Failed:', error),
  onProgress: (progress) => console.log(`${progress * 100}%`),
})

useArtifacts(options?)

Hook for listening to all artifacts across all types. Perfect for switch cases:

import { useArtifacts } from '@ai-sdk-tools/artifacts/client'

const {
  byType,       // All artifacts grouped by type
  latest,       // Latest version of each artifact type
  artifacts,    // All artifacts in chronological order
  current,      // Most recent artifact across all types
} = useArtifacts({
  onData: (artifactType, data) => {
    console.log(`New ${artifactType} artifact:`, data)
  }
})

// Perfect for rendering different artifact types
return (
  <div>
    {Object.entries(latest).map(([type, artifact]) => {
      switch (type) {
        case 'burn-rate':
          return <BurnRateComponent key={type} data={artifact} />
        case 'financial-report':
          return <ReportComponent key={type} data={artifact} />
        default:
          return <GenericComponent key={type} type={type} data={artifact} />
      }
    })}
  </div>
)

// Perfect for Canvas-style switching on current artifact
function Canvas() {
  const { current } = useArtifacts()

  switch (current?.type) {
    case 'burn-rate-canvas':
      return <BurnRateCanvas />
    case 'revenue-canvas':
      return <RevenueCanvas />
    default:
      return <DefaultCanvas />
  }
}

Examples