AI Content Generation
Using ContentSchemas with AI to generate component content while maintaining developer control over behavior
AI Content Generation
mdxui components are designed for AI-assisted content generation through the content/actions pattern. This guide shows how to use ContentSchema exports with AI to generate compelling content while keeping behavioral control with developers.
The Two-Schema System
Every mdxui component exports two interfaces:
1. TypeScript Props (Full Interface)
import type { HeroProps } from 'mdxui'
// Accepts JSX, icons, formatted text
type HeroProps = {
title: ReactNode
subtitle?: ReactNode
callToAction: ReactNode
secondaryCallToAction?: ReactNode
variant?: 'default' | 'code-below' | 'video-beside'
actions?: {
primary?: string | ActionConfig
secondary?: string | ActionConfig
}
}2. Zod ContentSchema (AI-Generatable)
import { HeroContentSchema } from 'mdxui/zod'
// AI generates strings only - no behavior
const HeroContentSchema = z.object({
title: z.string().describe('compelling headline for the hero section'),
subtitle: z.string().optional().describe('supporting subheadline'),
callToAction: z.string().describe('action-oriented primary button text'),
secondaryCallToAction: z.string().optional().describe('secondary action text'),
variant: z.enum(['default', 'code-below', 'video-beside']).optional(),
})Why Two Schemas?
TypeScript Props define what the component accepts at runtime:
ReactNodeallows JSX, icons, formatted text- Includes
actionsfor developer-wired behavior - Used by templates and MDX authors
ContentSchema defines what AI can safely generate:
z.string()for text content only- NO
actions- prevents hallucinated URLs - Includes semantic descriptions for AI context
Using with ai-props
The ai-props package provides a React component for AI content generation:
import { AI } from 'ai-props'
import { Hero, HeroContentSchema } from 'mdxui'
export function LandingPage() {
return (
<AI
schema={HeroContentSchema}
prompt="Generate a hero section for a developer tools SaaS that helps teams ship faster with AI-powered code generation"
>
{(content) => (
<Hero
{...content} // Spread AI-generated content safely
actions={{
primary: '/signup',
secondary: '/demo'
}}
/>
)}
</AI>
)
}How It Works
- AI generates content using the Zod schema as a structured output specification
- Content is validated against the schema (type-safe at runtime)
- Render prop receives typed content (inferred from Zod schema)
- Developer wires behavior by adding the
actionsprop
Available ContentSchemas
All mdxui components export a *ContentSchema:
// Site components
import {
HeroContentSchema,
FeaturesContentSchema,
PricingContentSchema,
TestimonialsContentSchema,
CTAContentSchema,
FAQContentSchema,
} from 'mdxui/zod'
// App components
import {
DashboardContentSchema,
SettingsContentSchema,
} from 'mdxui/zod'Example: Features Section
import { AI } from 'ai-props'
import { Features, FeaturesContentSchema } from 'mdxui'
<AI
schema={FeaturesContentSchema}
prompt="Generate 4 features for a no-code website builder targeting solopreneurs"
>
{(content) => (
<Features
{...content}
columns={2}
actions={{
feature1: '/features/ai-design',
feature2: '/features/templates',
feature3: '/features/hosting',
feature4: '/features/analytics',
}}
/>
)}
</AI>Generated content might look like:
{
"title": "Everything You Need to Launch",
"subtitle": "No design or coding skills required",
"features": [
{
"name": "AI-Powered Design",
"description": "Describe your vision and watch AI create beautiful, on-brand designs in seconds"
},
{
"name": "Professional Templates",
"description": "Start with battle-tested templates designed for conversion and SEO"
},
{
"name": "Lightning-Fast Hosting",
"description": "Global CDN ensures your site loads instantly anywhere in the world"
},
{
"name": "Built-in Analytics",
"description": "Track visitors, conversions, and revenue without installing plugins"
}
]
}Example: Pricing Section
import { AI } from 'ai-props'
import { Pricing, PricingContentSchema } from 'mdxui'
<AI
schema={PricingContentSchema}
prompt="Create 3 pricing tiers for a developer API platform: free tier for hobbyists, pro tier at $29/mo for indie devs, and enterprise tier with custom pricing"
>
{(content) => (
<Pricing
{...content}
actions={{
free: '/signup?plan=free',
pro: '/signup?plan=pro',
enterprise: '/contact-sales',
}}
/>
)}
</AI>Best Practices
1. Be Specific in Prompts
Good:
prompt="Generate a hero section for a B2B SaaS that helps marketing teams automate social media posts. Emphasize time savings and ROI. Target busy marketing managers."Too vague:
prompt="Generate a hero section"2. Separate Content from Behavior
Good:
<Hero {...aiContent} actions={{ primary: '/signup', secondary: '/demo' }} />Bad (mixing concerns):
// Don't let AI generate URLs - they'll be hallucinated
<Hero
{...aiContent}
actions={{
primary: aiContent.signupUrl, // ❌ Not type-safe, AI will hallucinate
secondary: aiContent.demoUrl, // ❌ URLs should be developer-controlled
}}
/>3. Use Variants to Guide AI
Variants influence what content AI generates:
<AI
schema={HeroContentSchema}
prompt="Generate a hero section for a code editor with a demo video"
>
{(content) => (
<Hero
{...content}
variant="video-beside" // AI knows to generate content suitable for video layout
video={{ src: '/demo.mp4', poster: '/poster.jpg' }}
actions={{ primary: '/download' }}
/>
)}
</AI>4. Combine AI Content with Manual Content
You can mix AI-generated content with manual overrides:
<AI schema={HeroContentSchema} prompt="...">
{(content) => (
<Hero
title={<>Ship <Highlight>10x faster</Highlight> with AI</>} // Manual override
subtitle={content.subtitle} // Use AI-generated subtitle
callToAction={content.callToAction} // Use AI-generated CTA
actions={{ primary: '/signup' }}
/>
)}
</AI>5. Cache AI Responses
The AI component includes built-in caching:
<AI
schema={HeroContentSchema}
prompt="..."
cacheKey="landing-hero" // Cache by key
ttl={3600000} // Cache for 1 hour (ms)
>
{(content) => <Hero {...content} actions={{ primary: '/signup' }} />}
</AI>Error Handling
The AI component handles validation errors gracefully:
<AI
schema={HeroContentSchema}
prompt="..."
fallback={
<Hero
title="Ship faster with AI"
subtitle="The developer platform that writes code for you"
callToAction="Get Started"
actions={{ primary: '/signup' }}
/>
}
>
{(content) => <Hero {...content} actions={{ primary: '/signup' }} />}
</AI>If AI generation fails or validation fails, the fallback content is rendered.
Advanced: Custom ContentSchemas
For custom components, create your own ContentSchema:
import { z } from 'zod'
export const CustomHeroContentSchema = z.object({
badge: z.string().describe('announcement badge text (e.g., "New: AI-powered code review")'),
title: z.string().describe('compelling headline'),
subtitle: z.string().describe('supporting subheadline'),
callToAction: z.string().describe('primary button text'),
secondaryCallToAction: z.string().optional(),
testimonial: z.object({
quote: z.string(),
author: z.string(),
role: z.string(),
}).optional().describe('social proof quote from a customer'),
})
export type CustomHeroProps = z.infer<typeof CustomHeroContentSchema> & {
actions?: {
primary?: string | ActionConfig
secondary?: string | ActionConfig
}
variant?: 'default' | 'with-testimonial'
}TypeScript Integration
The type system ensures safety:
import { z } from 'zod'
import { HeroContentSchema } from 'mdxui/zod'
// Infer TypeScript type from Zod schema
type HeroContent = z.infer<typeof HeroContentSchema>
// Content type matches the Props type (minus actions)
const content: HeroContent = {
title: 'Ship faster',
subtitle: 'Build with AI',
callToAction: 'Get Started',
}
// Full component props include content + actions
<Hero {...content} actions={{ primary: '/signup' }} />Related
- Component Design - How to design components following the content/actions pattern
- Migration Guide - Migrating existing components to the content/actions pattern