import type { Metadata } from 'next' import Link from 'next/link' import { notFound } from 'next/navigation' import { SITE_URL } from '@/lib/core/utils/urls' import { BackLink, ChevronArrow } from '@/app/(landing)/components' import { JsonLd } from '@/app/(landing)/components/json-ld' import { LandingFAQ } from '@/app/(landing)/components/landing-faq' import { FeaturedModelCard, FeaturedProviderCard, ProviderIcon, } from '@/app/(landing)/models/components/model-primitives' import { ModelTimelineChart } from '@/app/(landing)/models/components/model-timeline-chart' import { buildProviderFaqs, formatPrice, formatTokenCount, getProviderBySlug, MODEL_PROVIDERS_WITH_CATALOGS, TOP_MODEL_PROVIDERS, } from '@/app/(landing)/models/utils' const baseUrl = SITE_URL export const dynamicParams = false export async function generateStaticParams() { return MODEL_PROVIDERS_WITH_CATALOGS.map((provider) => ({ provider: provider.slug, })) } export async function generateMetadata({ params, }: { params: Promise<{ provider: string }> }): Promise { const { provider: providerSlug } = await params const provider = getProviderBySlug(providerSlug) if (!provider || provider.models.length === 0) { return {} } const providerFaqs = buildProviderFaqs(provider) return { title: `${provider.name} Models`, description: `Browse ${provider.modelCount} ${provider.name} models tracked in Sim. Compare pricing, context windows, default model selection, and capabilities for ${provider.name}'s AI model lineup.`, keywords: [ `${provider.name} models`, `${provider.name} pricing`, `${provider.name} context window`, `${provider.name} model list`, `${provider.name} AI models`, ...provider.models.slice(0, 6).map((model) => model.displayName), ], // og:image/twitter:image come from the sibling opengraph-image.tsx - // Next serves it at a hash-suffixed URL, so hardcoding it here 404s. openGraph: { title: `${provider.name} Models | Sim`, description: `Explore ${provider.modelCount} ${provider.name} models with pricing and capability details.`, url: `${baseUrl}${provider.href}`, type: 'website', }, twitter: { card: 'summary_large_image', title: `${provider.name} Models | Sim`, description: providerFaqs[0]?.answer ?? provider.summary, }, alternates: { canonical: `${baseUrl}${provider.href}`, }, } } export default async function ProviderModelsPage({ params, }: { params: Promise<{ provider: string }> }) { const { provider: providerSlug } = await params const provider = getProviderBySlug(providerSlug) if (!provider || provider.models.length === 0) { notFound() } const faqs = buildProviderFaqs(provider) const relatedProviders = MODEL_PROVIDERS_WITH_CATALOGS.filter( (entry) => entry.id !== provider.id && TOP_MODEL_PROVIDERS.includes(entry.name) ).slice(0, 4) const breadcrumbJsonLd = { '@context': 'https://schema.org', '@type': 'BreadcrumbList', itemListElement: [ { '@type': 'ListItem', position: 1, name: 'Home', item: baseUrl }, { '@type': 'ListItem', position: 2, name: 'Models', item: `${baseUrl}/models` }, { '@type': 'ListItem', position: 3, name: provider.name, item: `${baseUrl}${provider.href}` }, ], } const itemListJsonLd = { '@context': 'https://schema.org', '@type': 'ItemList', name: `${provider.name} Models`, description: `List of ${provider.modelCount} ${provider.name} models tracked in Sim.`, url: `${baseUrl}${provider.href}`, numberOfItems: provider.modelCount, itemListElement: provider.models.map((model, index) => ({ '@type': 'ListItem', position: index + 1, url: `${baseUrl}${model.href}`, name: model.displayName, })), } const faqJsonLd = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faqs.map((faq) => ({ '@type': 'Question', name: faq.question, acceptedAnswer: { '@type': 'Answer', text: faq.answer, }, })), } return ( <>

{provider.name} models

{provider.modelCount} models
{provider.featuredModels.length > 0 && ( <>
)} {provider.models.map((model) => (

{model.displayName}

{model.id}

{formatPrice(model.pricing.input)}/1M in {formatPrice(model.pricing.output)}/1M out {model.contextWindow ? ( {formatTokenCount(model.contextWindow)} ctx ) : null} ))} {relatedProviders.length > 0 && ( <>
)}

Frequently asked questions

) }