Skip to content

Commit 3c1ffd1

Browse files
committed
fix(models): leave evaluation models out of prompt tools; landing page structure
- Context windows, the pricing tools, and comparisons skip evaluation-only models (native state and questions, not prompts) - Token counter labels an OpenAI count as an estimate when exact encoding fails - New model pages: desktop-first breakpoints, named props interfaces, section ids and labels, sr-only hero summaries; TSDoc on exported comparison helpers
1 parent 2cae14f commit 3c1ffd1

13 files changed

Lines changed: 178 additions & 80 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ export default async function ModelPage({
282282
<nav aria-labelledby='model-comparisons-heading' className='px-6 py-10'>
283283
<h2
284284
id='model-comparisons-heading'
285-
className='mb-6 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
285+
className='mb-6 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
286286
>
287287
Compare {model.displayName}
288288
</h2>

‎apps/sim/app/(landing)/models/(shell)/compare/[pair]/page.tsx‎

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ export async function generateStaticParams() {
4949
return MODEL_COMPARISONS.map((comparison) => ({ pair: comparison.slug }))
5050
}
5151

52-
export async function generateMetadata({
53-
params,
54-
}: {
52+
interface ModelComparisonPageProps {
5553
params: Promise<{ pair: string }>
56-
}): Promise<Metadata> {
54+
}
55+
56+
export async function generateMetadata({ params }: ModelComparisonPageProps): Promise<Metadata> {
5757
const { pair } = await params
5858
const comparison = getModelComparisonBySlug(pair)
5959

@@ -95,11 +95,7 @@ export async function generateMetadata({
9595
}
9696
}
9797

98-
export default async function ModelComparisonPage({
99-
params,
100-
}: {
101-
params: Promise<{ pair: string }>
102-
}) {
98+
export default async function ModelComparisonPage({ params }: ModelComparisonPageProps) {
10399
const { pair } = await params
104100
const comparison = getModelComparisonBySlug(pair)
105101

@@ -181,8 +177,18 @@ export default async function ModelComparisonPage({
181177
<JsonLd data={itemListJsonLd} />
182178
<JsonLd data={faqJsonLd} />
183179

184-
<section className='bg-[var(--bg)]'>
180+
<section
181+
id='model-comparison'
182+
aria-labelledby='comparison-heading'
183+
className='bg-[var(--bg)]'
184+
>
185185
<div className={cn(LANDING_CONTENT_WIDTH, LANDING_GUTTER, 'pt-[112px] max-sm:pt-20')}>
186+
<p className='sr-only'>
187+
Sim is the open-source AI workspace where teams build, deploy, and manage AI agents.
188+
This page compares {a.model.displayName} and {b.model.displayName} on API pricing per 1M
189+
tokens, context window, max output, and capabilities. Both models are available in the
190+
Sim Agent block, and each Agent block in a Sim agent can use a different model.
191+
</p>
186192
<div className='mb-6'>
187193
<BackLink href='/models' label='Back to Models' />
188194
</div>
@@ -206,7 +212,7 @@ export default async function ModelComparisonPage({
206212
</p>
207213
<h1
208214
id='comparison-heading'
209-
className='text-[28px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] sm:text-[36px] lg:text-[44px]'
215+
className='text-[44px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-sm:text-[28px] max-lg:text-[36px]'
210216
>
211217
{comparison.title}
212218
</h1>
@@ -236,11 +242,11 @@ export default async function ModelComparisonPage({
236242

237243
<div className={cn(LANDING_CONTENT_WIDTH, LANDING_GUTTER)}>
238244
<div className='border-[var(--border)] border-x'>
239-
<section aria-labelledby='comparison-specs-heading'>
245+
<section id='comparison-specs' aria-labelledby='comparison-specs-heading'>
240246
<div className='px-6 pt-10 pb-4'>
241247
<h2
242248
id='comparison-specs-heading'
243-
className='mb-2 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
249+
className='mb-2 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
244250
>
245251
Pricing, context window, and capabilities
246252
</h2>
@@ -257,10 +263,14 @@ export default async function ModelComparisonPage({
257263

258264
<div className='h-px w-full bg-[var(--border)]' />
259265

260-
<section aria-labelledby='comparison-build-heading' className='px-6 py-10'>
266+
<section
267+
id='comparison-build'
268+
aria-labelledby='comparison-build-heading'
269+
className='px-6 py-10'
270+
>
261271
<h2
262272
id='comparison-build-heading'
263-
className='mb-2 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
273+
className='mb-2 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
264274
>
265275
Use {a.model.displayName} or {b.model.displayName} in a Sim agent
266276
</h2>
@@ -297,7 +307,7 @@ export default async function ModelComparisonPage({
297307
<nav aria-labelledby='related-comparisons-heading' className='px-6 py-10'>
298308
<h2
299309
id='related-comparisons-heading'
300-
className='mb-6 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
310+
className='mb-6 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
301311
>
302312
Related comparisons
303313
</h2>
@@ -308,10 +318,14 @@ export default async function ModelComparisonPage({
308318

309319
<div className='h-px w-full bg-[var(--border)]' />
310320

311-
<section aria-labelledby='comparison-faq-heading' className='px-6 py-10'>
321+
<section
322+
id='comparison-faq'
323+
aria-labelledby='comparison-faq-heading'
324+
className='px-6 py-10'
325+
>
312326
<h2
313327
id='comparison-faq-heading'
314-
className='mb-8 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
328+
className='mb-8 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
315329
>
316330
Frequently asked questions
317331
</h2>

‎apps/sim/app/(landing)/models/(shell)/context-windows/page.tsx‎

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,26 @@ export default function ContextWindowsPage() {
117117
<JsonLd data={itemListJsonLd} />
118118
<JsonLd data={faqJsonLd} />
119119

120-
<section className='bg-[var(--bg)]'>
120+
<section
121+
id='context-windows'
122+
aria-labelledby='context-windows-heading'
123+
className='bg-[var(--bg)]'
124+
>
121125
<div className={cn(LANDING_CONTENT_WIDTH, LANDING_GUTTER, 'pt-[112px] max-sm:pt-20')}>
126+
<p className='sr-only'>
127+
Sim is the open-source AI workspace where teams build, deploy, and manage AI agents.
128+
This page ranks the context windows and max output tokens of{' '}
129+
{CONTEXT_WINDOW_MODELS.length} models from {CONTEXT_WINDOW_PROVIDER_COUNT} providers,
130+
including Claude, GPT, Gemini, and Grok, with API prices per 1M tokens. Every model
131+
listed is available in the Sim Agent block.
132+
</p>
122133
<div className='mb-6'>
123134
<BackLink href='/models' label='Back to Models' />
124135
</div>
125136

126137
<h1
127138
id='context-windows-heading'
128-
className='mb-6 text-[28px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[40px]'
139+
className='mb-6 text-[40px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[28px]'
129140
>
130141
LLM context window comparison
131142
</h1>
@@ -145,11 +156,11 @@ export default function ContextWindowsPage() {
145156

146157
<div className={cn(LANDING_CONTENT_WIDTH, LANDING_GUTTER)}>
147158
<div className='border-[var(--border)] border-x'>
148-
<section aria-labelledby='largest-by-provider-heading'>
159+
<section id='largest-by-provider' aria-labelledby='largest-by-provider-heading'>
149160
<div className='px-6 pt-10 pb-4'>
150161
<h2
151162
id='largest-by-provider-heading'
152-
className='mb-2 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
163+
className='mb-2 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
153164
>
154165
Largest context window by provider
155166
</h2>
@@ -175,11 +186,11 @@ export default function ContextWindowsPage() {
175186

176187
<div className='h-px w-full bg-[var(--border)]' />
177188

178-
<section aria-labelledby='all-context-windows-heading'>
189+
<section id='all-context-windows' aria-labelledby='all-context-windows-heading'>
179190
<div className='px-6 pt-10 pb-4'>
180191
<h2
181192
id='all-context-windows-heading'
182-
className='mb-2 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
193+
className='mb-2 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
183194
>
184195
Every model by context window
185196
</h2>
@@ -193,10 +204,14 @@ export default function ContextWindowsPage() {
193204

194205
<div className='h-px w-full bg-[var(--border)]' />
195206

196-
<section aria-labelledby='context-windows-faq-heading' className='px-6 py-10'>
207+
<section
208+
id='context-windows-faq'
209+
aria-labelledby='context-windows-faq-heading'
210+
className='px-6 py-10'
211+
>
197212
<h2
198213
id='context-windows-faq-heading'
199-
className='mb-8 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
214+
className='mb-8 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
200215
>
201216
Frequently asked questions
202217
</h2>

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ export default async function ModelsPage({
228228
</>
229229
)}
230230

231-
<nav aria-label='Free tools' className='flex flex-col sm:flex-row'>
231+
<nav aria-label='Free tools' className='flex max-sm:flex-col'>
232232
{Object.values(MODEL_TOOLS).map((tool) => (
233233
<ModelToolLink
234234
key={tool.href}
@@ -244,10 +244,14 @@ export default async function ModelsPage({
244244

245245
<div className='h-px w-full bg-[var(--border)]' />
246246

247-
<section aria-labelledby='head-to-head-heading' className='px-6 py-10'>
247+
<section
248+
id='head-to-head'
249+
aria-labelledby='head-to-head-heading'
250+
className='px-6 py-10'
251+
>
248252
<h2
249253
id='head-to-head-heading'
250-
className='mb-2 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
254+
className='mb-2 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
251255
>
252256
Head-to-head comparisons
253257
</h2>

‎apps/sim/app/(landing)/models/(shell)/pricing-calculator/page.tsx‎

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,11 @@ export async function generateMetadata(): Promise<Metadata> {
112112
}
113113
}
114114

115-
export default async function PricingCalculatorPage({
116-
searchParams,
117-
}: {
115+
interface PricingCalculatorPageProps {
118116
searchParams: Promise<SearchParams>
119-
}) {
117+
}
118+
119+
export default async function PricingCalculatorPage({ searchParams }: PricingCalculatorPageProps) {
120120
await pricingCalculatorSearchParamsCache.parse(searchParams)
121121

122122
const breadcrumbJsonLd = {
@@ -167,8 +167,19 @@ export default async function PricingCalculatorPage({
167167
<JsonLd data={applicationJsonLd} />
168168
<JsonLd data={faqJsonLd} />
169169

170-
<section className='bg-[var(--bg)]' aria-labelledby='pricing-calculator-heading'>
170+
<section
171+
id='pricing-calculator'
172+
aria-labelledby='pricing-calculator-heading'
173+
className='bg-[var(--bg)]'
174+
>
171175
<div className={cn(LANDING_CONTENT_WIDTH, LANDING_GUTTER, 'pt-[112px] max-sm:pt-20')}>
176+
<p className='sr-only'>
177+
Sim is the open-source AI workspace where teams build, deploy, and manage AI agents. The
178+
free Sim LLM API pricing calculator estimates cost per request, per day, and per month
179+
for {TOOL_MODELS.length} OpenAI, Anthropic Claude, Google Gemini, and other models,
180+
using the same rates and long-context tier rules Sim uses to cost model calls in its
181+
execution logs.
182+
</p>
172183
<div className='mb-6'>
173184
<BackLink href='/models' label='Back to models' />
174185
</div>
@@ -177,7 +188,7 @@ export default async function PricingCalculatorPage({
177188
</p>
178189
<h1
179190
id='pricing-calculator-heading'
180-
className='text-balance text-[28px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[40px]'
191+
className='text-balance text-[40px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[28px]'
181192
>
182193
LLM API pricing calculator
183194
</h1>
@@ -203,10 +214,14 @@ export default async function PricingCalculatorPage({
203214

204215
<div className='h-px w-full bg-[var(--border)]' />
205216

206-
<section aria-labelledby='cost-drivers-heading' className='px-6 py-10'>
217+
<section
218+
id='cost-drivers'
219+
aria-labelledby='cost-drivers-heading'
220+
className='px-6 py-10'
221+
>
207222
<h2
208223
id='cost-drivers-heading'
209-
className='mb-3 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
224+
className='mb-3 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
210225
>
211226
What drives LLM API cost
212227
</h2>
@@ -227,7 +242,7 @@ export default async function PricingCalculatorPage({
227242

228243
<div className='h-px w-full bg-[var(--border)]' />
229244

230-
<nav aria-label='Related resources' className='flex flex-col sm:flex-row'>
245+
<nav aria-label='Related resources' className='flex max-sm:flex-col'>
231246
<ModelToolLink
232247
href={MODEL_TOOLS.tokenCounter.href}
233248
title={MODEL_TOOLS.tokenCounter.name}
@@ -247,10 +262,10 @@ export default async function PricingCalculatorPage({
247262

248263
<div className='h-px w-full bg-[var(--border)]' />
249264

250-
<section aria-labelledby='faq-heading' className='px-6 py-10'>
265+
<section id='faq' aria-labelledby='faq-heading' className='px-6 py-10'>
251266
<h2
252267
id='faq-heading'
253-
className='mb-8 text-[20px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] lg:text-[24px]'
268+
className='mb-8 text-[24px] text-[var(--text-primary)] leading-[100%] tracking-[-0.02em] max-lg:text-[20px]'
254269
>
255270
Frequently asked questions
256271
</h2>

‎apps/sim/app/(landing)/models/(shell)/token-counter/components/token-counter/token-counter.tsx‎

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,25 @@ export function TokenCounter() {
4747
const selectedModels = useMemo(() => resolveToolModels(modelIds), [modelIds])
4848

4949
const rows = useMemo(() => {
50-
const exactCountByEncoding = new Map<string, number>()
50+
const exactCountByEncoding = new Map<string, number | null>()
5151
const countExact = (activeTokenizer: AccurateTokenizer, modelId: string) => {
5252
const encodingName = activeTokenizer.resolveEncodingName(modelId)
53-
let count = exactCountByEncoding.get(encodingName)
54-
if (count === undefined) {
55-
count = activeTokenizer.getAccurateTokenCount(deferredText, modelId)
56-
exactCountByEncoding.set(encodingName, count)
53+
if (!exactCountByEncoding.has(encodingName)) {
54+
exactCountByEncoding.set(
55+
encodingName,
56+
activeTokenizer.getExactTokenCount(deferredText, modelId)
57+
)
5758
}
58-
return count
59+
return exactCountByEncoding.get(encodingName) ?? null
5960
}
6061

6162
return selectedModels.map((model) => {
62-
const exact = tokenizer !== null && EXACT_TOKENIZER_PROVIDER_IDS.has(model.providerId)
63-
const tokens = exact
64-
? countExact(tokenizer, model.id)
65-
: estimateTokenCount(deferredText, model.providerId).count
63+
const exactTokens =
64+
tokenizer !== null && EXACT_TOKENIZER_PROVIDER_IDS.has(model.providerId)
65+
? countExact(tokenizer, model.id)
66+
: null
67+
const exact = exactTokens !== null
68+
const tokens = exactTokens ?? estimateTokenCount(deferredText, model.providerId).count
6669
const inputCost = priceTokenUsage(model.pricing, { input: tokens, output: 0 }).total
6770
return { model, exact, tokens, inputCost }
6871
})

0 commit comments

Comments
 (0)