Leaderboard GOAT(edited)
v0 Structured Data Installation Prompt
Structured Data is one of the best ways for AI crawlers and Google to find and rank your content, but most websites underutilize this. So I created a v0 prompt to install a structured data utility that includes examples for many common kinds of structured data that Google will recognize.
You can paste this prompt directly into the v0 message composer to have v0 fully install a Structured Data utility with Google-supported best practices implementation:
I need you to create a complete Structured Data system for my Next.js project. Please add ALL of the following files exactly as they are provided below, with all the component parts, and lib file. This is a comprehensive Structured Data system that includes various types of Google-supported structured data snippets.
Please create the following files with their exact content:
[V0_FILE]typescriptreact:file="lib/structured-data.tsx"import type { Organization, WebSite, BreadcrumbList, Person, Product, Article, LocalBusiness, Event, Recipe, Course, JobPosting, WithContext } from "schema-dts"
// Base component for any structured data
interface BaseStructuredDataProps { data: WithContext<any> sanitize?: boolean}
export function StructuredData({ data, sanitize = true }: BaseStructuredDataProps) { const jsonString = JSON.stringify(data) const sanitizedJson = sanitize ? jsonString.replace(/</g, "\\u003c") : jsonString return ( <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: sanitizedJson }} /> )}
// Organization Schemainterface OrganizationProps { name: string url: string logo?: string description?: string address?: { streetAddress?: string addressLocality?: string addressRegion?: string postalCode?: string addressCountry?: string } contactPoint?: { telephone?: string email?: string contactType?: string } sameAs?: string[] foundingDate?: string}
export function OrganizationSchema(props: OrganizationProps) { const data: WithContext<Organization> = { "@context": "https://schema.org", "@type": "Organization", name: props.name, url: props.url, ...(props.logo && { logo: props.logo }), ...(props.description && { description: props.description }), ...(props.address && { address: { "@type": "PostalAddress", ...props.address } }), ...(props.contactPoint && { contactPoint: { "@type": "ContactPoint", ...props.contactPoint } }), ...(props.sameAs && { sameAs: props.sameAs }), ...(props.foundingDate && { foundingDate: props.foundingDate }) }
return <StructuredData data={data} />}
// Website Schemainterface WebsiteProps { name: string url: string description?: string searchUrl?: string searchQueryParam?: string author?: { name: string url?: string } publisher?: { name: string logo?: string }}
export function WebsiteSchema(props: WebsiteProps) { const data: WithContext<WebSite> = { "@context": "https://schema.org", "@type": "WebSite", name: props.name, url: props.url, ...(props.description && { description: props.description }), ...(props.searchUrl && { potentialAction: { "@type": "SearchAction", target: `${props.searchUrl}?${props.searchQueryParam || 'q'}={search_term_string}`, "query-input": `required name=search_term_string` } }), ...(props.author && { author: { "@type": "Person", name: props.author.name, ...(props.author.url && { url: props.author.url }) } }), ...(props.publisher && { publisher: { "@type": "Organization", name: props.publisher.name, ...(props.publisher.logo && { logo: props.publisher.logo }) } }) }
return <StructuredData data={data} />}
// Breadcrumb Schemainterface BreadcrumbItem { name: string url: string}
interface BreadcrumbProps { items: BreadcrumbItem[]}
export function BreadcrumbSchema({ items }: BreadcrumbProps) { const data: WithContext<BreadcrumbList> = { "@context": "https://schema.org", "@type": "BreadcrumbList", itemListElement: items.map((item, index) => ({ "@type": "ListItem", position: index + 1, name: item.name, item: item.url })) }
return <StructuredData data={data} />}
// Person Schemainterface PersonProps { name: string url?: string image?: string jobTitle?: string worksFor?: { name: string url?: string } description?: string email?: string telephone?: string address?: { streetAddress?: string addressLocality?: string addressRegion?: string postalCode?: string addressCountry?: string } sameAs?: string[]}
export function PersonSchema(props: PersonProps) { const data: WithContext<Person> = { "@context": "https://schema.org", "@type": "Person", name: props.name, ...(props.url && { url: props.url }), ...(props.image && { image: props.image }), ...(props.jobTitle && { jobTitle: props.jobTitle }), ...(props.worksFor && { worksFor: { "@type": "Organization", name: props.worksFor.name, ...(props.worksFor.url && { url: props.worksFor.url }) } }), ...(props.description && { description: props.description }), ...(props.email && { email: props.email }), ...(props.telephone && { telephone: props.telephone }), ...(props.address && { address: { "@type": "PostalAddress", ...props.address } }), ...(props.sameAs && { sameAs: props.sameAs }) }
return <StructuredData data={data} />}
// Product Schemainterface ProductProps { name: string description: string image?: string[] brand?: string sku?: string mpn?: string offers?: { price: string priceCurrency: string availability?: string url?: string seller?: string } aggregateRating?: { ratingValue: number reviewCount: number bestRating?: number worstRating?: number } review?: Array<{ author: string datePublished: string reviewBody: string reviewRating: { ratingValue: number bestRating?: number } }>}
export function ProductSchema(props: ProductProps) { const data: WithContext<Product> = { "@context": "https://schema.org", "@type": "Product", name: props.name, description: props.description, ...(props.image && { image: props.image }), ...(props.brand && { brand: { "@type": "Brand", name: props.brand } }), ...(props.sku && { sku: props.sku }), ...(props.mpn && { mpn: props.mpn }), ...(props.offers && { offers: { "@type": "Offer", price: props.offers.price, priceCurrency: props.offers.priceCurrency, ...(props.offers.availability && { availability: `https://schema.org/${props.offers.availability}` }), ...(props.offers.url && { url: props.offers.url }), ...(props.offers.seller && { seller: { "@type": "Organization", name: props.offers.seller } }) } }), ...(props.aggregateRating && { aggregateRating: { "@type": "AggregateRating", ratingValue: props.aggregateRating.ratingValue, reviewCount: props.aggregateRating.reviewCount, bestRating: props.aggregateRating.bestRating || 5, worstRating: props.aggregateRating.worstRating || 1 } }), ...(props.review && { review: props.review.map(review => ({ "@type": "Review", author: { "@type": "Person", name: review.author }, datePublished: review.datePublished, reviewBody: review.reviewBody, reviewRating: { "@type": "Rating", ratingValue: review.reviewRating.ratingValue, bestRating: review.reviewRating.bestRating || 5 } })) }) }
return <StructuredData data={data} />}
// Article Schemainterface ArticleProps { headline: string description: string image?: string[] author: { name: string url?: string } publisher: { name: string logo?: string } datePublished: string dateModified?: string url: string articleBody?: string wordCount?: number keywords?: string[]}
export function ArticleSchema(props: ArticleProps) { const data: WithContext<Article> = { "@context": "https://schema.org", "@type": "Article", headline: props.headline, description: props.description, ...(props.image && { image: props.image }), author: { "@type": "Person", name: props.author.name, ...(props.author.url && { url: props.author.url }) }, publisher: { "@type": "Organization", name: props.publisher.name, ...(props.publisher.logo && { logo: { "@type": "ImageObject", url: props.publisher.logo } }) }, datePublished: props.datePublished, ...(props.dateModified && { dateModified: props.dateModified }), url: props.url, ...(props.articleBody && { articleBody: props.articleBody }), ...(props.wordCount && { wordCount: props.wordCount }), ...(props.keywords && { keywords: props.keywords }) }
return <StructuredData data={data} />}
// Local Business Schemainterface LocalBusinessProps { name: string description?: string url?: string telephone?: string email?: string address: { streetAddress: string addressLocality: string addressRegion: string postalCode: string addressCountry: string } geo?: { latitude: number longitude: number } openingHours?: string[] priceRange?: string image?: string[] aggregateRating?: { ratingValue: number reviewCount: number }}
export function LocalBusinessSchema(props: LocalBusinessProps) { const data: WithContext<LocalBusiness> = { "@context": "https://schema.org", "@type": "LocalBusiness", name: props.name, ...(props.description && { description: props.description }), ...(props.url && { url: props.url }), ...(props.telephone && { telephone: props.telephone }), ...(props.email && { email: props.email }), address: { "@type": "PostalAddress", ...props.address }, ...(props.geo && { geo: { "@type": "GeoCoordinates", latitude: props.geo.latitude, longitude: props.geo.longitude } }), ...(props.openingHours && { openingHours: props.openingHours }), ...(props.priceRange && { priceRange: props.priceRange }), ...(props.image && { image: props.image }), ...(props.aggregateRating && { aggregateRating: { "@type": "AggregateRating", ratingValue: props.aggregateRating.ratingValue, reviewCount: props.aggregateRating.reviewCount } }) }
return <StructuredData data={data} />}
// Event Schemainterface EventProps { name: string description: string startDate: string endDate?: string location: { name: string address: { streetAddress: string addressLocality: string addressRegion: string postalCode: string addressCountry: string } } organizer?: { name: string url?: string } offers?: { price: string priceCurrency: string availability?: string url?: string } image?: string[] url?: string}
export function EventSchema(props: EventProps) { const data: WithContext<Event> = { "@context": "https://schema.org", "@type": "Event", name: props.name, description: props.description, startDate: props.startDate, ...(props.endDate && { endDate: props.endDate }), location: { "@type": "Place", name: props.location.name, address: { "@type": "PostalAddress", ...props.location.address } }, ...(props.organizer && { organizer: { "@type": "Organization", name: props.organizer.name, ...(props.organizer.url && { url: props.organizer.url }) } }), ...(props.offers && { offers: { "@type": "Offer", price: props.offers.price, priceCurrency: props.offers.priceCurrency, ...(props.offers.availability && { availability: `https://schema.org/${props.offers.availability}` }), ...(props.offers.url && { url: props.offers.url }) } }), ...(props.image && { image: props.image }), ...(props.url && { url: props.url }) }
return <StructuredData data={data} />}[V0_FILE]typescriptreact:file="components/structured-data-examples.tsx"import { OrganizationSchema, WebsiteSchema, BreadcrumbSchema, PersonSchema, ProductSchema, ArticleSchema, LocalBusinessSchema, EventSchema} from "@/lib/structured-data"
// Example usage componentsexport function ExampleOrganization() { return ( <OrganizationSchema name="Acme Corporation" url="https://acme.com" logo="https://acme.com/logo.png" description="Leading provider of innovative solutions" address={{ streetAddress: "123 Business St", addressLocality: "San Francisco", addressRegion: "CA", postalCode: "94105", addressCountry: "US" }} contactPoint={{ telephone: "+1-555-123-4567", email: "contact@acme.com", contactType: "customer service" }} sameAs={[ "https://twitter.com/acme", "https://linkedin.com/company/acme" ]} /> )}
export function ExampleWebsite() { return ( <WebsiteSchema name="Acme Blog" url="https://acme.com" description="Latest insights and updates from Acme" searchUrl="https://acme.com/search" searchQueryParam="q" author={{ name: "Acme Team", url: "https://acme.com/about" }} publisher={{ name: "Acme Corporation", logo: "https://acme.com/logo.png" }} /> )}
export function ExampleBreadcrumb() { return ( <BreadcrumbSchema items={[ { name: "Home", url: "https://acme.com" }, { name: "Products", url: "https://acme.com/products" }, { name: "Software", url: "https://acme.com/products/software" } ]} /> )}
export function ExamplePerson() { return ( <PersonSchema name="John Doe" url="https://johndoe.com" image="https://johndoe.com/photo.jpg" jobTitle="Software Engineer" worksFor={{ name: "Acme Corporation", url: "https://acme.com" }} description="Experienced software engineer specializing in web development" email="john@johndoe.com" sameAs={[ "https://twitter.com/johndoe", "https://linkedin.com/in/johndoe" ]} /> )}
export function ExampleProduct() { return ( <ProductSchema name="Acme Widget Pro" description="Professional-grade widget for all your needs" image={["https://acme.com/widget-1.jpg", "https://acme.com/widget-2.jpg"]} brand="Acme" sku="AWP-001" offers={{ price: "99.99", priceCurrency: "USD", availability: "InStock", url: "https://acme.com/products/widget-pro" }} aggregateRating={{ ratingValue: 4.5, reviewCount: 127 }} /> )}
export function ExampleArticle() { return ( <ArticleSchema headline="How to Build Better Software" description="A comprehensive guide to software development best practices" image={["https://acme.com/article-image.jpg"]} author={{ name: "Jane Smith", url: "https://acme.com/authors/jane-smith" }} publisher={{ name: "Acme Blog", logo: "https://acme.com/logo.png" }} datePublished="2024-01-15" dateModified="2024-01-20" url="https://acme.com/blog/build-better-software" keywords={["software", "development", "best practices"]} /> )}
export function ExampleLocalBusiness() { return ( <LocalBusinessSchema name="Acme Coffee Shop" description="Artisanal coffee and pastries in downtown" url="https://acmecoffee.com" telephone="+1-555-COFFEE" address={{ streetAddress: "456 Main St", addressLocality: "San Francisco", addressRegion: "CA", postalCode: "94102", addressCountry: "US" }} geo={{ latitude: 37.7749, longitude: -122.4194 }} openingHours={[ "Mo-Fr 07:00-19:00", "Sa 08:00-20:00", "Su 08:00-18:00" ]} priceRange="$$" aggregateRating={{ ratingValue: 4.8, reviewCount: 203 }} /> )}
export function ExampleEvent() { return ( <EventSchema name="Acme Tech Conference 2024" description="Annual technology conference featuring the latest innovations" startDate="2024-06-15T09:00:00" endDate="2024-06-16T17:00:00" location={{ name: "Convention Center", address: { streetAddress: "789 Convention Blvd", addressLocality: "San Francisco", addressRegion: "CA", postalCode: "94103", addressCountry: "US" } }} organizer={{ name: "Acme Corporation", url: "https://acme.com" }} offers={{ price: "299.00", priceCurrency: "USD", availability: "InStock", url: "https://acme.com/conference/tickets" }} image={["https://acme.com/conference-banner.jpg"]} url="https://acme.com/conference" /> )}[V0_FILE]typescriptreact:file="app/page.tsx" isDeleted="true"import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"import { Badge } from "@/components/ui/badge"import { ExampleOrganization, ExampleWebsite, ExampleBreadcrumb, ExamplePerson, ExampleProduct, ExampleArticle, ExampleLocalBusiness, ExampleEvent} from "@/components/structured-data-examples"
export default function StructuredDataLibrary() { const schemas = [ { name: "Organization", description: "For companies, organizations, and institutions", component: <ExampleOrganization />, useCase: "Company pages, about pages, contact pages" }, { name: "Website", description: "For websites and web applications", component: <ExampleWebsite />, useCase: "Homepage, main site pages" }, { name: "Breadcrumb", description: "For navigation breadcrumbs", component: <ExampleBreadcrumb />, useCase: "Product pages, category pages, deep navigation" }, { name: "Person", description: "For individual people and profiles", component: <ExamplePerson />, useCase: "Author pages, team member profiles, personal websites" }, { name: "Product", description: "For products and services", component: <ExampleProduct />, useCase: "E-commerce product pages, service listings" }, { name: "Article", description: "For blog posts, news articles, and content", component: <ExampleArticle />, useCase: "Blog posts, news articles, documentation" }, { name: "Local Business", description: "For local businesses and physical locations", component: <ExampleLocalBusiness />, useCase: "Restaurant pages, store locations, service providers" }, { name: "Event", description: "For events, conferences, and gatherings", component: <ExampleEvent />, useCase: "Event pages, conference listings, meetups" } ]
return ( <div className="min-h-screen bg-gradient-to-br from-slate-50 to-slate-100 p-8"> <div className="max-w-7xl mx-auto"> <div className="text-center mb-12"> <h1 className="text-4xl font-bold text-slate-900 mb-4"> Generic Structured Data Library </h1> <p className="text-xl text-slate-600 max-w-3xl mx-auto"> A comprehensive collection of reusable structured data components for better SEO and search engine understanding. Each component follows Schema.org standards and includes XSS protection. </p> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-12"> {schemas.map((schema) => ( <Card key={schema.name} className="hover:shadow-lg transition-shadow"> <CardHeader> <div className="flex items-center justify-between"> <CardTitle className="text-lg">{schema.name} Schema</CardTitle> <Badge variant="secondary">Schema.org</Badge> </div> <CardDescription>{schema.description}</CardDescription> </CardHeader> <CardContent> <div className="space-y-3"> <div> <h4 className="font-medium text-sm text-slate-700 mb-1">Use Cases:</h4> <p className="text-sm text-slate-600">{schema.useCase}</p> </div> <div className="hidden"> {schema.component} </div> </div> </CardContent> </Card> ))} </div>
<Card className="mb-8"> <CardHeader> <CardTitle>Key Features</CardTitle> <CardDescription>What makes this library special</CardDescription> </CardHeader> <CardContent> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> <div className="space-y-2"> <h4 className="font-medium text-slate-900">🔒 XSS Protection</h4> <p className="text-sm text-slate-600"> Automatic sanitization of dangerous characters to prevent XSS attacks </p> </div> <div className="space-y-2"> <h4 className="font-medium text-slate-900">📝 TypeScript Support</h4> <p className="text-sm text-slate-600"> Full TypeScript support with schema-dts for type safety </p> </div> <div className="space-y-2"> <h4 className="font-medium text-slate-900">🎯 Schema.org Compliant</h4> <p className="text-sm text-slate-600"> All components follow official Schema.org specifications </p> </div> <div className="space-y-2"> <h4 className="font-medium text-slate-900">🔧 Highly Configurable</h4> <p className="text-sm text-slate-600"> Flexible props system with optional fields for customization </p> </div> <div className="space-y-2"> <h4 className="font-medium text-slate-900">⚡ Performance Optimized</h4> <p className="text-sm text-slate-600"> Lightweight components with minimal runtime overhead </p> </div> <div className="space-y-2"> <h4 className="font-medium text-slate-900">🎨 Framework Agnostic</h4> <p className="text-sm text-slate-600"> Works with Next.js, React, and other modern frameworks </p> </div> </div> </CardContent> </Card>
<Card> <CardHeader> <CardTitle>Installation & Usage</CardTitle> <CardDescription>How to use these components in your project</CardDescription> </CardHeader> <CardContent> <div className="space-y-4"> <div> <h4 className="font-medium mb-2">1. Install Dependencies</h4> <code className="block bg-slate-100 p-3 rounded text-sm"> npm install schema-dts </code> </div> <div> <h4 className="font-medium mb-2">2. Copy the Library</h4> <p className="text-sm text-slate-600 mb-2"> Copy the <code>lib/structured-data.tsx</code> file to your project </p> </div> <div> <h4 className="font-medium mb-2">3. Use in Your Components</h4> <code className="block bg-slate-100 p-3 rounded text-sm whitespace-pre">{`import { OrganizationSchema } from "@/lib/structured-data"
export default function AboutPage() { return ( <div> <OrganizationSchema name="Your Company" url="https://yoursite.com" description="Your company description" /> {/* Your page content */} </div> )}`} </code> </div> </div> </CardContent> </Card> </div> </div> )}[V0_FILE]typescriptreact:file="README.md" type="code" isDeleted="true"# Generic Structured Data Library
A comprehensive, type-safe library for adding structured data to your web applications. Built with TypeScript and following Schema.org standards.
## Features
- 🔒 **XSS Protection**: Automatic sanitization of dangerous characters- 📝 **TypeScript Support**: Full type safety with schema-dts- 🎯 **Schema.org Compliant**: Follows official specifications- 🔧 **Highly Configurable**: Flexible props with optional fields- ⚡ **Performance Optimized**: Lightweight with minimal overhead- 🎨 **Framework Agnostic**: Works with Next.js, React, and more
## Installation
```bashnpm install schema-dts```
## Available Schemas
### OrganizationSchemaFor companies, organizations, and institutions.
```tsx
```
### WebsiteSchemaFor websites and web applications.
```tsx
```
### ProductSchemaFor e-commerce products and services.
```tsx
```
### ArticleSchemaFor blog posts, news articles, and content.
```tsx
```
### PersonSchemaFor individual people and profiles.
```tsx
```
### LocalBusinessSchemaFor local businesses and physical locations.
```tsx
```
### EventSchemaFor events, conferences, and gatherings.
```tsx
```
### BreadcrumbSchemaFor navigation breadcrumbs.
```tsx
```
## Security
All components include XSS protection by default. The library automatically sanitizes dangerous characters like `<` to prevent injection attacks. You can disable this by setting `sanitize={false}` on the base `StructuredData` component, but this is not recommended.
## Validation
You can validate your structured data using:- md-link-0- md-link-1
## Contributing
Feel free to extend this library with additional schema types or improvements.