'use client' import { useEffect, useState } from 'react' const PRICING_API = 'https://pricing.hanzo.ai/v1/pricing' interface ModelPricing { name: string tier?: string context?: number | null specs?: { params?: string; arch?: string } pricing: { input: number | null output: number | null } | null } interface PricingData { hanzoModels: ModelPricing[] } function fmtPrice(p: number | null | undefined): string { if (p == null) return '--' if (p >= 1) return `$${p.toFixed(2)}` if (p >= 0.01) return `$${p.toFixed(2)}` return `$${p.toFixed(p >= 0.001 ? 3 : 4)}` } function fmtCtx(ctx: number | null | undefined): string { if (!ctx) return '--' if (ctx >= 1_000_000) return `${Math.round(ctx / 1000)}K` if (ctx >= 1000) return `${Math.round(ctx / 1000)}K` return `${ctx}` } /** * Renders a dynamically-fetched pricing table for Zen models. * * Props: * generation - "zen4" | "zen3" | "all" (default "all") * showArch - show Architecture column (default false) * showContext - show Context column (default true) * showTier - show Tier column (default false) * showParams - show Parameters column (default false) * linkPrefix - base path for model links (default "/docs/models/") * compact - fewer columns for index pages */ export function DynamicModelTable({ generation = 'all', showArch = false, showContext = true, showTier = false, showParams = false, linkPrefix = '/docs/models/', compact = false, }: { generation?: 'zen4' | 'zen3' | 'all' showArch?: boolean showContext?: boolean showTier?: boolean showParams?: boolean linkPrefix?: string compact?: boolean }) { const [data, setData] = useState(null) const [error, setError] = useState(false) useEffect(() => { fetch(PRICING_API) .then((r) => { if (!r.ok) throw new Error(); return r.json() }) .then(setData) .catch(() => setError(true)) }, []) if (error) { return (

Unable to load live pricing. See pricing docs for current rates.

) } if (!data) { return

Loading pricing...

} let models = data.hanzoModels.filter((m) => m.pricing && !m.pricing.input === false) if (generation === 'zen4') { models = models.filter((m) => m.name.startsWith('zen4')) } else if (generation === 'zen3') { models = models.filter((m) => m.name.startsWith('zen3')) } if (compact) { return (
{showArch && } {models.map((m) => ( {showArch && } ))}
ModelArchitectureInput $/1M Output $/1M
{m.name}{m.specs?.arch}{fmtPrice(m.pricing?.input)} {fmtPrice(m.pricing?.output)}
) } return (
{showParams && } {showArch && } {showContext && } {showTier && } {models.map((m) => ( {showParams && ( )} {showArch && ( )} {showContext && ( )} {showTier && ( )} ))}
ModelParametersArchitectureContextTierInput $/1M Output $/1M
{m.name} {m.specs?.params} {m.specs?.arch} {fmtCtx(m.context)} {m.tier} {fmtPrice(m.pricing?.input)} {fmtPrice(m.pricing?.output)}
) } /** * Cost examples calculated from live pricing data. */ export function DynamicCostExamples() { const [data, setData] = useState(null) useEffect(() => { fetch(PRICING_API) .then((r) => { if (!r.ok) throw new Error(); return r.json() }) .then(setData) .catch(() => {}) }, []) if (!data) return null const find = (name: string) => data.hanzoModels.find((m) => m.name === name) const mini = find('zen4-mini') const coderFlash = find('zen4-coder-flash') const embed = find('zen3-embedding') const flagship = find('zen4') const vl = find('zen3-vl') const examples = [ mini && { task: '100 chat messages', model: 'zen4-mini', tokens: '50K in + 50K out', cost: ((mini.pricing?.input ?? 0) * 0.05 + (mini.pricing?.output ?? 0) * 0.05) }, coderFlash && { task: '1,000 code completions', model: 'zen4-coder-flash', tokens: '500K in + 500K out', cost: ((coderFlash.pricing?.input ?? 0) * 0.5 + (coderFlash.pricing?.output ?? 0) * 0.5) }, embed && { task: '10K embeddings', model: 'zen3-embedding', tokens: '1M in', cost: (embed.pricing?.input ?? 0) }, flagship && { task: 'Heavy daily usage', model: 'zen4', tokens: '1M in + 1M out', cost: ((flagship.pricing?.input ?? 0) + (flagship.pricing?.output ?? 0)) }, vl && { task: 'Vision analysis (1K images)', model: 'zen3-vl', tokens: '500K in + 200K out', cost: ((vl.pricing?.input ?? 0) * 0.5 + (vl.pricing?.output ?? 0) * 0.2) }, ].filter(Boolean) as Array<{ task: string; model: string; tokens: string; cost: number }> return (
{examples.map((ex) => ( ))}
Task Model ~Tokens ~Cost
{ex.task} {ex.model} {ex.tokens} ${ex.cost.toFixed(2)}
) }