Skip to content

Commit 589dd4f

Browse files
committed
fix(models): address PR review feedback
Correct model structured-data price bounds, remove dead code in the models catalog helpers, and harden OG font loading with graceful fallbacks. Made-with: Cursor
1 parent 5d1ee47 commit 589dd4f

4 files changed

Lines changed: 63 additions & 27 deletions

File tree

apps/sim/app/(landing)/models/[provider]/[model]/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
formatTokenCount,
2020
formatUpdatedAt,
2121
getModelBySlug,
22+
getPricingBounds,
2223
getProviderBySlug,
2324
getRelatedModels,
2425
} from '../../utils'
@@ -100,6 +101,7 @@ export default async function ModelPage({
100101

101102
const faqs = buildModelFaqs(provider, model)
102103
const capabilityFacts = buildModelCapabilityFacts(model)
104+
const pricingBounds = getPricingBounds(model.pricing)
103105
const relatedModels = getRelatedModels(model, 6)
104106

105107
const breadcrumbJsonLd = {
@@ -129,8 +131,8 @@ export default async function ModelPage({
129131
offers: {
130132
'@type': 'AggregateOffer',
131133
priceCurrency: 'USD',
132-
lowPrice: Math.min(model.pricing.input, model.pricing.output).toString(),
133-
highPrice: Math.max(model.pricing.input, model.pricing.output).toString(),
134+
lowPrice: pricingBounds.lowPrice.toString(),
135+
highPrice: pricingBounds.highPrice.toString(),
134136
},
135137
}
136138

apps/sim/app/(landing)/models/og-utils.tsx

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,27 @@ function getTitleFontSize(title: string): number {
1919
return TITLE_FONT_SIZE.large
2020
}
2121

22-
async function loadGoogleFont(font: string, weights: string, text: string): Promise<ArrayBuffer> {
23-
const url = `https://fonts.googleapis.com/css2?family=${font}:wght@${weights}&text=${encodeURIComponent(text)}`
24-
const css = await (await fetch(url)).text()
25-
const resource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/)
22+
async function loadGoogleFont(
23+
font: string,
24+
weights: string,
25+
text: string
26+
): Promise<ArrayBuffer | null> {
27+
try {
28+
const url = `https://fonts.googleapis.com/css2?family=${font}:wght@${weights}&text=${encodeURIComponent(text)}`
29+
const css = await (await fetch(url)).text()
30+
const resource = css.match(/src: url\(([^)]+)\) format\('(opentype|truetype|woff2?)'\)/)
2631

27-
if (resource) {
28-
const response = await fetch(resource[1])
29-
if (response.status === 200) {
30-
return await response.arrayBuffer()
32+
if (resource) {
33+
const response = await fetch(resource[1])
34+
if (response.status === 200) {
35+
return await response.arrayBuffer()
36+
}
3137
}
38+
} catch {
39+
return null
3240
}
3341

34-
throw new Error('Failed to load font data')
42+
return null
3543
}
3644

3745
function SimLogoFull() {
@@ -71,7 +79,10 @@ export async function createModelsOgImage({
7179
domainLabel = 'sim.ai/models',
7280
}: ModelsOgImageProps) {
7381
const text = `${eyebrow}${title}${subtitle}${pills.join('')}${domainLabel}`
74-
const fontData = await loadGoogleFont('Geist', '400;500;600', text)
82+
const [regularFontData, mediumFontData] = await Promise.all([
83+
loadGoogleFont('Geist', '400', text),
84+
loadGoogleFont('Geist', '500', text),
85+
])
7586

7687
return new ImageResponse(
7788
<div
@@ -170,11 +181,26 @@ export async function createModelsOgImage({
170181
{
171182
...size,
172183
fonts: [
173-
{
174-
name: 'Geist',
175-
data: fontData,
176-
style: 'normal',
177-
},
184+
...(regularFontData
185+
? [
186+
{
187+
name: 'Geist',
188+
data: regularFontData,
189+
style: 'normal' as const,
190+
weight: 400,
191+
},
192+
]
193+
: []),
194+
...(mediumFontData
195+
? [
196+
{
197+
name: 'Geist',
198+
data: mediumFontData,
199+
style: 'normal' as const,
200+
weight: 500,
201+
},
202+
]
203+
: []),
178204
],
179205
}
180206
)

apps/sim/app/(landing)/models/page.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { LandingFAQ } from '@/app/(landing)/components/landing-faq'
55
import { ModelDirectory } from './components/model-directory'
66
import { ModelCard, ProviderCard } from './components/model-primitives'
77
import {
8+
getPricingBounds,
89
MODEL_CATALOG_PROVIDERS,
910
MODEL_PROVIDERS_WITH_CATALOGS,
1011
TOP_MODEL_PROVIDERS,
@@ -120,8 +121,8 @@ export default function ModelsPage() {
120121
offers: {
121122
'@type': 'AggregateOffer',
122123
priceCurrency: 'USD',
123-
lowPrice: Math.min(model.pricing.input, model.pricing.output).toString(),
124-
highPrice: Math.max(model.pricing.input, model.pricing.output).toString(),
124+
lowPrice: getPricingBounds(model.pricing).lowPrice.toString(),
125+
highPrice: getPricingBounds(model.pricing).highPrice.toString(),
125126
},
126127
},
127128
})),

apps/sim/app/(landing)/models/utils.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,12 @@ export function formatPrice(price?: number | null): string {
155155
return 'N/A'
156156
}
157157

158+
const maximumFractionDigits = price > 0 && price < 0.001 ? 4 : 3
159+
158160
return `$${trimTrailingZeros(
159161
new Intl.NumberFormat('en-US', {
160162
minimumFractionDigits: 0,
161-
maximumFractionDigits: 3,
163+
maximumFractionDigits,
162164
}).format(price)
163165
)}`
164166
}
@@ -310,10 +312,7 @@ function formatModelDisplayName(providerId: string, modelId: string): string {
310312
)
311313
.join(' ')
312314

313-
return displayName
314-
.replace(/^GPT (\d[\w.]*)/i, 'GPT-$1')
315-
.replace(/^GPT (\d[\w.]*) (Mini|Nano|Pro|Chat)/i, 'GPT-$1 $2')
316-
.replace(/\bGpt\b/g, 'GPT')
315+
return displayName.replace(/^GPT (\d[\w.]*)/i, 'GPT-$1').replace(/\bGpt\b/g, 'GPT')
317316
}
318317

319318
function buildCapabilityTags(capabilities: ModelCapabilities): string[] {
@@ -565,13 +564,21 @@ export const TOTAL_MODELS = ALL_CATALOG_MODELS.length
565564
export const MAX_CONTEXT_WINDOW = Math.max(
566565
...ALL_CATALOG_MODELS.map((model) => model.contextWindow ?? 0)
567566
)
568-
export const MODELS_WITH_REASONING = ALL_CATALOG_MODELS.filter(
569-
(model) => model.capabilities.reasoningEffort || model.capabilities.thinking
570-
).length
571567
export const TOP_MODEL_PROVIDERS = MODEL_PROVIDERS_WITH_CATALOGS.slice(0, 8).map(
572568
(provider) => provider.name
573569
)
574570

571+
export function getPricingBounds(pricing: PricingInfo): { lowPrice: number; highPrice: number } {
572+
return {
573+
lowPrice: Math.min(
574+
pricing.input,
575+
pricing.output,
576+
...(pricing.cachedInput !== undefined ? [pricing.cachedInput] : [])
577+
),
578+
highPrice: Math.max(pricing.input, pricing.output),
579+
}
580+
}
581+
575582
export function getProviderBySlug(providerSlug: string): CatalogProvider | null {
576583
return MODEL_CATALOG_PROVIDERS.find((provider) => provider.slug === providerSlug) ?? null
577584
}

0 commit comments

Comments
 (0)