npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ai-props

v0.1.2

Published

Magic AI Prop Generation

Downloads

192

Readme

ai-props

npm version License: MIT

A React component package that provides an AI component for generating and spreading AI-generated props to child components.

Installation

npm install ai-props

Usage

The AI component mirrors the generateObject function from the ai package and spreads the generated object's properties to its children.

Model Configuration

The AI component supports both string-based OpenAI models and provider-specific model objects:

// Simple string-based OpenAI model (recommended for OpenAI)
<AI
  model='gpt-4'
  schema={schema}
  prompt='Generate content'
/>

// Provider-specific model object (required for other providers)
import { anthropic } from '@ai-sdk/anthropic'

const model = anthropic('claude-2')
<AI
  model={model}
  schema={schema}
  prompt='Generate content'
/>

### Streaming Support

The AI component supports real-time streaming of generated content, providing a more interactive user experience:

```tsx
<AI
  model='gpt-4'
  stream={true}
  schema={{
    title: 'string',
    content: 'string'
  }}
  prompt='Generate an article about React'
>
  {(props, { isStreaming }) => (
    <article className={isStreaming ? 'animate-pulse' : ''}>
      <h1>{props.title}</h1>
      <div>{props.content}</div>
      {isStreaming && (
        <div className='text-gray-500'>Generating content...</div>
      )}
    </article>
  )}
</AI>

When using streaming:

  • Set stream={true} to enable real-time updates
  • Access streaming status via isStreaming in render prop
  • UI updates automatically as content arrives
  • Maintain type safety with your schema
  • Reduced time to first content display

API Proxy Integration

For enhanced security and control, you can route requests through your own API endpoint:

<AI
  model='gpt-4'
  apiEndpoint='/api/generate'
  headers={{
    'Authorization': 'Bearer ${process.env.API_KEY}',
    'X-Custom-Header': 'value'
  }}
  schema={schema}
  prompt='Generate content'
/>

Your API endpoint should:

  • Accept the same parameters as the AI provider
  • Return compatible streaming or non-streaming responses
  • Handle authentication and rate limiting
  • Implement proper error handling

Benefits of using an API proxy:

  • Keep API keys secure on your server
  • Add custom request validation
  • Implement usage tracking
  • Control model access and costs
  • Add custom error handling

Example API endpoint implementation:

// pages/api/generate.ts
import { OpenAIStream } from 'ai'

export async function POST(req: Request) {
  const { prompt, schema, stream } = await req.json()

  const response = await fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'gpt-4',
      messages: [{ role: 'user', content: prompt }],
      stream: stream,
    }),
  })

  if (stream) {
    const stream = OpenAIStream(response)
    return new Response(stream)
  }

  const json = await response.json()
  return Response.json(json)
}

Simplified Schema Interface

You can define your schema using a simple object structure without importing Zod:

import { AI } from 'ai-props'

function MyComponent() {
  return (
    <AI
      schema={{
        productType: 'App | API | Marketplace | Platform | Packaged Service | Professional Service | Website',
        profile: {
          customer: 'ideal customer profile in 3-5 words',
          solution: 'describe the offer in 4-10 words'
        },
        description: 'website meta description',
        tags: ['SEO-optimized meta tags']
      }}
      prompt='Generate product details'
    >
      {(props) => (
        <article>
          <h1>{props.productType}</h1>
          <div>
            <p>Customer: {props.profile.customer}</p>
            <p>Solution: {props.profile.solution}</p>
          </div>
          <p>{props.description}</p>
          <ul>
            {props.tags.map((tag, i) => (
              <li key={i}>{tag}</li>
            ))}
          </ul>
        </article>
      )}
    </AI>
  )
}

The simplified schema interface supports:

  • Pipe-separated strings ('Option1 | Option2 | Option3') which are automatically converted to enums
  • Nested objects with type descriptions
  • Array types with description hints

Direct Zod Schema Usage

You can also use Zod schemas directly for more complex validation:

import { AI } from 'ai-props'
import { z } from 'zod'

// Define your schema
const schema = z.object({
  title: z.string(),
  description: z.string()
})

// Use the AI component
function MyComponent() {
  return (
    <AI
      schema={schema}
      prompt='Generate a title and description for a blog post about React'
    >
      {(props) => (
        <article>
          <h1>{props.title}</h1>
          <p>{props.description}</p>
        </article>
      )}
    </AI>
  )
}

Default Model Configuration

The AI component uses a default model configuration:

import { openai } from '@ai-sdk/openai'
const model = openai('gpt-4o')

You can override this by providing your own model configuration through props.

Props

The AI component accepts all props from the generateObject function:

Required Props

  • schema: A Zod schema or Schema object defining the structure of the generated object. Supports:
    • Direct Zod schemas for complex validation
    • Simplified object syntax without Zod imports
    • Pipe-separated strings for automatic enum conversion (e.g., 'Option1 | Option2')
  • prompt: The prompt to send to the language model

Optional Props

  • output: Type of output ('object' | 'array' | 'enum' | 'no-schema')
  • schemaName: Optional name for the output schema
  • schemaDescription: Optional description for the output schema
  • mode: Generation mode ('auto' | 'json' | 'tool'), defaults to 'auto'
  • model: Override the default model
  • experimental_telemetry: Optional telemetry configuration
  • experimental_providerMetadata: Additional provider-specific metadata

Array Output Mode

The AI component supports generating and rendering arrays of items using the output='array' prop. When using array output mode, you can also enable CSS Grid layout with the cols prop:

<AI
  schema={blogSchema}
  prompt='Generate 6 blog post previews'
  output='array'
  cols={3}
  gap='2rem'
  className='grid-container'
  itemClassName='grid-item'
>
  {(props) => (
    <article>{/* Item content */}</article>
  )}
</AI>

Grid Support Props

  • cols: Number of columns in the grid (default: 3)
  • gap: Gap between grid items (CSS gap value)
  • className: Class applied to the grid container
  • itemClassName: Class applied to each grid item

Styling Support

The AI component integrates with clsx and tailwind-merge for flexible styling:

<AI
  className='max-w-7xl mx-auto px-4 py-16 grid-cols-1 md:grid-cols-2 lg:grid-cols-3'
  itemClassName='bg-white p-6 rounded-lg shadow-md h-full flex flex-col'
>
  {/* Component content */}
</AI>

Class names are merged using the cn utility, which combines clsx and tailwind-merge for conflict-free class composition.

Examples

Hero Section Example

A waitlist landing page hero section for an AI-powered SaaS product:

import { AI } from 'ai-props'

const heroSchema = {
  productType: 'App | API | Marketplace | Platform',
  profile: {
    customer: 'ideal customer profile in 3-5 words',
    solution: 'describe the offer in 4-10 words'
  },
  description: 'website meta description',
  tags: ['SEO-optimized meta tags'],
  headline: 'compelling headline for AI SaaS product',
  subheadline: 'engaging subheadline explaining value proposition',
  ctaText: 'action-oriented button text',
  benefits: ['3-5 key benefits'],
  targetAudience: 'specific target audience description'
}

export function HeroSection() {
  return (
    <AI<typeof heroSchema>
      schema={heroSchema}
      prompt='Generate a hero section for an AI-powered SaaS product waitlist landing page'
      className='bg-gradient-to-br from-blue-50 to-indigo-50'
    >
      {(props) => (
        <div className='max-w-6xl mx-auto px-4 py-16'>
          <h1 className='text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-blue-600 to-indigo-600'>
            {props.headline}
          </h1>
          <p className='text-xl text-gray-600 mb-8'>{props.subheadline}</p>
          <button className='bg-blue-600 text-white px-8 py-3 rounded-lg text-lg font-medium hover:bg-blue-700 transition-colors'>
            {props.ctaText}
          </button>
          <div className='mt-12'>
            <h2 className='text-2xl font-semibold mb-4'>Perfect for {props.targetAudience}</h2>
            <ul className='grid grid-cols-1 md:grid-cols-2 gap-4'>
              {props.benefits.map((benefit, index) => (
                <li key={index} className='flex items-start bg-white p-4 rounded-lg shadow-sm'>
                  <span className='text-blue-500 mr-2'>✓</span>
                  {benefit}
                </li>
              ))}
            </ul>
          </div>
        </div>
      )}
    </AI>
  )
}

#### Blog List Example

A grid of blog post previews using array output mode:

```tsx
import { AI } from 'ai-props'

const blogSchema = {
  productType: 'App | API | Marketplace | Platform',
  profile: {
    customer: 'ideal customer profile in 3-5 words',
    solution: 'describe the offer in 4-10 words'
  },
  description: 'website meta description',
  tags: ['relevant topic tags'],
  title: 'engaging blog post title',
  excerpt: 'compelling 2-3 sentence excerpt',
  readTime: 'estimated read time',
  category: 'Blog | Tutorial | Case Study | News'
}

export function BlogList() {
  return (
    <AI<typeof blogSchema>
      schema={blogSchema}
      prompt='Generate 6 blog post previews about AI and machine learning'
      output='array'
      cols={3}
      gap='2rem'
      className='max-w-7xl mx-auto px-4 py-16 grid-cols-1 md:grid-cols-2 lg:grid-cols-3'
      itemClassName='h-full'
    >
      {(props) => (
        <article className='bg-white p-6 rounded-lg shadow-md h-full flex flex-col'>
          <div className='text-sm text-gray-500 mb-2 flex items-center justify-between'>
            <span>{props.category}</span>
            <span>{props.readTime}</span>
          </div>
          <h2 className='text-xl font-semibold mb-3'>{props.title}</h2>
          <p className='text-gray-600 mb-4 flex-grow'>{props.excerpt}</p>
          <div className='flex flex-wrap gap-2 mt-auto'>
            {props.tags.map((tag, index) => (
              <span key={index} className='bg-gray-100 text-gray-600 px-3 py-1 rounded-full text-sm'>
                {tag}
              </span>
            ))}
          </div>
        </article>
      )}
    </AI>
  )
}

## Development

This package uses:
- Vite for building
- Vitest for testing
- React Cosmos for component development and testing

## Dependencies

This package requires the following peer dependencies:
- `react` (^18.2.0)
- `react-dom` (^18.2.0)
- `@types/react` (^18.2.0)
- `@types/react-dom` (^18.2.0)

And the following runtime dependencies:
- `ai` (^4.0.18)
- `@ai-sdk/openai` (^1.0.8)
- `clsx` (^2.1.1)
- `tailwind-merge` (^2.5.5)
- `zod` (^3.22.4)

Make sure to install these dependencies if they're not already in your project:

```bash
npm install ai @ai-sdk/openai clsx tailwind-merge zod

License

MIT