import type { Metadata } from "next"; import Link from "next/link"; import { ArrowRight } from "lucide-react"; import { Container, Eyebrow } from "@/components/marketing/section"; import { Button } from "@/components/ui/button"; import { ProviderIcon } from "@/components/brand/provider-icon"; import { PublicCatalogGroup, type CatalogRow } from "@/components/models/public-catalog"; import { PROVIDERS, PROVIDER_ORDER } from "@/lib/client/providers"; import { getPublicModels, popularComparisons } from "@/lib/models/public-data"; import { deriveBadges, lifecycleStatus, sortWeightOf } from "@/lib/models/badges"; import { formatContext, formatPrice } from "@/lib/models/format"; import type { PolyModel } from "@/lib/ai/core/types"; import type { BadgeContext } from "@/lib/models/badges"; export const dynamic = "force-dynamic"; export const metadata: Metadata = { title: "AI model catalog — pricing, context windows and capabilities", description: "Every model PolyLLM supports across OpenAI, Anthropic, Google Gemini, xAI, Mistral, DeepSeek, Kimi, OpenRouter and Cerebras: input/output prices per million tokens, context windows, reasoning, vision, tools and lifecycle status — updated from the providers’ own listings.", alternates: { canonical: "/models" }, openGraph: { title: "AI model catalog — PolyLLM", description: "Prices, context windows and capabilities for every supported model.", url: "/models" }, }; function toRow(m: PolyModel, ctx: BadgeContext): CatalogRow { return { key: m.key, provider: m.provider, name: m.displayName, id: m.id, inPrice: formatPrice(m.pricing?.inputPerMillion), outPrice: formatPrice(m.pricing?.outputPerMillion), context: formatContext(m.limits?.contextTokens), maxOut: formatContext(m.limits?.maxOutputTokens), reasoning: m.capabilities.reasoning, vision: m.capabilities.vision, tools: m.capabilities.tools, json: m.capabilities.structuredOutput, lifecycle: lifecycleStatus(m, { ctx }), badges: deriveBadges(m, ctx), }; } export default async function PublicModelsPage() { const { models, ctx, ok } = await getPublicModels(); const visible = models.filter((m) => m.status !== "deprecated"); const groups = PROVIDER_ORDER.map((p) => ({ provider: p, list: visible.filter((m) => m.provider === p).sort((a, b) => sortWeightOf(b) - sortWeightOf(a) || a.displayName.localeCompare(b.displayName)) })).filter((g) => g.list.length); const popular = popularComparisons(models); return ( <>
Model catalog

Every model. One honest table.

{visible.length ? `${visible.length} models from ${groups.length} providers` : "Models from nine providers"} — prices per million tokens, context windows, reasoning, vision, tools and lifecycle status, merged from each provider’s live listing and documented catalogs. Bring your own keys and use any of them in one workspace.

{popular[0] ? ( ) : null}
{!ok || visible.length === 0 ? (

{ok ? "The catalog is being populated." : "The catalog is temporarily unavailable."}

Please check back in a moment.

) : (
{groups.map((g) => (

{PROVIDERS[g.provider].name}

{g.list.length} model{g.list.length === 1 ? "" : "s"} · {PROVIDERS[g.provider].description}

toRow(m, ctx))} />
))}
)} {popular.length ? (
Popular comparisons

Head to head

) : null}

Use any of them with your own keys.

Free interface, encrypted keys, real streaming, side-by-side Arena and usage analytics.

Prices are the providers’ published list prices in USD per million tokens at the last catalog audit; verify with the provider before relying on them. Model names are trademarks of their owners.

); }