Skip to content

Commit 2c8944a

Browse files
authored
small usability fixes for workers ai (cloudflare#21317)
* pricing in one line * sorting models by creation_date * added company svgs * pinning models at the top * added pinned model emoji * linting
1 parent 0448403 commit 2c8944a

File tree

7 files changed

+72
-14
lines changed

7 files changed

+72
-14
lines changed
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

src/components/ModelCatalog.tsx

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect, useState, useMemo } from "react";
22
import ModelInfo from "./models/ModelInfo";
33
import ModelBadges from "./models/ModelBadges";
44
import { authorData } from "./models/data";
@@ -19,6 +19,37 @@ const ModelCatalog = ({ models }: { models: WorkersAIModelsSchema[] }) => {
1919
capabilities: [],
2020
});
2121

22+
// List of model names to pin at the top
23+
const pinnedModelNames = [
24+
"@cf/meta/llama-3.3-70b-instruct-fp8-fast",
25+
"@cf/meta/llama-3.1-8b-instruct-fast",
26+
];
27+
28+
// Sort models by pinned status first, then by created_at date
29+
const sortedModels = useMemo(() => {
30+
return [...models].sort((a, b) => {
31+
// First check if either model is pinned
32+
const isPinnedA = pinnedModelNames.includes(a.name);
33+
const isPinnedB = pinnedModelNames.includes(b.name);
34+
35+
// If pinned status differs, prioritize pinned models
36+
if (isPinnedA && !isPinnedB) return -1;
37+
if (!isPinnedA && isPinnedB) return 1;
38+
39+
// If both are pinned, sort by position in pinnedModelNames array (for manual ordering)
40+
if (isPinnedA && isPinnedB) {
41+
return (
42+
pinnedModelNames.indexOf(a.name) - pinnedModelNames.indexOf(b.name)
43+
);
44+
}
45+
46+
// If neither is pinned, sort by created_at date (newest first)
47+
const dateA = a.created_at ? new Date(a.created_at) : new Date(0);
48+
const dateB = b.created_at ? new Date(b.created_at) : new Date(0);
49+
return dateB.getTime() - dateA.getTime();
50+
});
51+
}, [models]);
52+
2253
useEffect(() => {
2354
const params = new URLSearchParams(window.location.search);
2455

@@ -35,7 +66,7 @@ const ModelCatalog = ({ models }: { models: WorkersAIModelsSchema[] }) => {
3566
});
3667
}, []);
3768

38-
const mapped = models.map((model) => ({
69+
const mapped = sortedModels.map((model) => ({
3970
model: {
4071
...model,
4172
capabilities: model.properties
@@ -237,13 +268,19 @@ const ModelCatalog = ({ models }: { models: WorkersAIModelsSchema[] }) => {
237268

238269
const author = model.model.name.split("/")[1];
239270
const authorInfo = authorData[author];
271+
const isPinned = pinnedModelNames.includes(model.model.name);
240272

241273
return (
242274
<a
243275
key={model.model.id}
244-
className="mb-3 block w-full self-start rounded-md border border-solid border-gray-200 p-3 !text-inherit no-underline hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800 lg:w-[48%]"
276+
className="relative mb-3 block w-full self-start rounded-md border border-solid border-gray-200 p-3 !text-inherit no-underline hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800 lg:w-[48%]"
245277
href={`/workers-ai/models/${model.model_display_name}`}
246278
>
279+
{isPinned && (
280+
<span className="absolute right-2 top-1" title="Pinned model">
281+
📌
282+
</span>
283+
)}
247284
<div className="-mb-1 flex items-center">
248285
{authorInfo?.logo ? (
249286
<img

src/components/models/ModelFeatures.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,19 @@ const ModelFeatures = ({ model }: { model: WorkersAIModelsSchema }) => {
110110
<td>Yes</td>
111111
</tr>
112112
)}
113-
{properties.price &&
114-
properties.price.map(
115-
(price: { price: number; unit: string }) => (
116-
<tr key={price.price}>
117-
<td>Pricing</td>
118-
<td>
119-
{currencyFormatter.format(price.price)} {price.unit}
120-
</td>
121-
</tr>
122-
),
123-
)}
113+
{properties.price && properties.price.length > 0 && (
114+
<tr>
115+
<td>Unit Pricing</td>
116+
<td>
117+
{properties.price
118+
.map(
119+
(price: { price: number; unit: string }) =>
120+
`${currencyFormatter.format(price.price)} ${price.unit}`,
121+
)
122+
.join(", ")}
123+
</td>
124+
</tr>
125+
)}
124126
</tbody>
125127
</table>
126128
</>

src/components/models/data.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import mistral from "../../assets/images/workers-ai/mistralai.svg";
55
import stabilityai from "../../assets/images/workers-ai/stabilityai.svg";
66
import huggingface from "../../assets/images/workers-ai/huggingface.svg";
77
import google from "../../assets/images/workers-ai/google.svg";
8+
import deepseek from "../../assets/images/workers-ai/deepseek.svg";
9+
import qwen from "../../assets/images/workers-ai/qwen.svg";
10+
import blackforestlabs from "../../assets/images/workers-ai/blackforestlabs.svg";
811

912
export const authorData: Record<string, { name: string; logo: string }> = {
1013
openai: {
@@ -39,4 +42,16 @@ export const authorData: Record<string, { name: string; logo: string }> = {
3942
name: "Google",
4043
logo: google.src,
4144
},
45+
"deepseek-ai": {
46+
name: "DeepSeek",
47+
logo: deepseek.src,
48+
},
49+
qwen: {
50+
name: "Qwen",
51+
logo: qwen.src,
52+
},
53+
"black-forest-labs": {
54+
name: "Black Forest Labs",
55+
logo: blackforestlabs.src,
56+
},
4257
};

src/schemas/workers-ai-models.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const workersAiModelsSchema = z.object({
1212
name: z.string(),
1313
description: z.string(),
1414
}),
15+
created_at: z.string().optional(),
1516
tags: z.string().array().optional(),
1617
properties: z
1718
.object({

0 commit comments

Comments
 (0)