Skip to content

Commit 991fd0c

Browse files
committed
basic mock for cookbook
1 parent 3777b51 commit 991fd0c

File tree

2 files changed

+378
-646
lines changed

2 files changed

+378
-646
lines changed

fern/components/cookbooks.tsx

Lines changed: 368 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,368 @@
1+
import React, { useState, useEffect } from 'react';
2+
3+
interface TagCategories {
4+
useCases: string[];
5+
endpoints: string[];
6+
techStack: string[];
7+
}
8+
9+
const ALL_TAGS: TagCategories = {
10+
useCases: [
11+
'RAG', 'Agents', 'Search', 'Embeddings', 'Tool Use',
12+
'Reranking', 'Fine-tuning', 'Summarization', 'Classification',
13+
'Text Generation', 'Multi-step', 'Semantic Search'
14+
],
15+
endpoints: ['Chat', 'Embed', 'Rerank', 'Finetuning'],
16+
techStack: ['Langchain', 'LlamaIndex', 'Pinecone', 'Weaviate', 'CrewAI']
17+
};
18+
19+
interface Cookbook {
20+
title: string;
21+
description: string;
22+
imageSrc: string;
23+
tags: {
24+
useCases: string[];
25+
endpoints: string[];
26+
techStack: string[];
27+
};
28+
href: string;
29+
author?: {
30+
name: string;
31+
image: string;
32+
};
33+
}
34+
35+
const CARD_COLORS = ['bg-[#EEF0EF]', 'bg-[#FDF2F0]', 'bg-[#F8F1F9]', 'bg-[#F0F2FB]'];
36+
37+
// Replace the existing tag style constants with these:
38+
const tagButtonClass = "px-2 py-1 text-[12px] rounded-full transition-colors cursor-pointer font-normal";
39+
40+
const selectedTagClass = "bg-[#333293] text-white hover:bg-[#333293]/90";
41+
const unselectedTagClass = "bg-white text-[#666666] border border-[#E5E5E5] hover:bg-gray-50";
42+
43+
export const Cookbooks: React.FC = () => {
44+
const [searchQuery, setSearchQuery] = useState('');
45+
const [selectedTags, setSelectedTags] = useState<{
46+
useCases: string[];
47+
endpoints: string[];
48+
techStack: string[];
49+
}>({
50+
useCases: [],
51+
endpoints: [],
52+
techStack: []
53+
});
54+
55+
// Base cookbook data
56+
const baseCookbooks: Cookbook[] = [
57+
{
58+
title: "Agentic Multi-Stage RAG with Cohere Tools API",
59+
description: "This cookbook demonstrates how to build a powerful, multi-stage agent with the Cohere platform that can retrieve documents in multiple steps.",
60+
imageSrc: "https://via.placeholder.com/400x200?text=Agentic+RAG",
61+
tags: {
62+
useCases: ['RAG', 'Agents', 'Tool Use'],
63+
endpoints: ['Chat', 'Rerank'],
64+
techStack: ['Langchain', 'Weaviate']
65+
},
66+
href: '/page/agentic-multi-stage-rag',
67+
author: {
68+
name: "Jason Jung",
69+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/0803e3d-Jason_Jung.jpg"
70+
}
71+
},
72+
{
73+
title: "Agentic RAG for PDFs with mixed data",
74+
description: "Learn how to build a powerful, multi-step chatbot with Cohere's models that can process PDFs containing both text and tables.",
75+
imageSrc: "https://via.placeholder.com/400x200?text=Mixed+Data+RAG",
76+
tags: {
77+
useCases: ['RAG', 'Agents', 'Tool Use'],
78+
endpoints: ['Chat', 'Embed', 'Rerank'],
79+
techStack: ['LlamaIndex', 'Pinecone']
80+
},
81+
href: '/page/agentic-rag-mixed-data',
82+
author: {
83+
name: "Shaan Desai",
84+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/d17fc44-Shaan.jpg"
85+
}
86+
},
87+
{
88+
title: "Analysis of Financial Forms",
89+
description: "Use Cohere's large language models to build an agent able to analyze financial forms like a 10-K or a 10-Q.",
90+
imageSrc: "https://via.placeholder.com/400x200?text=Financial+Analysis",
91+
tags: {
92+
useCases: ['RAG', 'Embeddings', 'Classification'],
93+
endpoints: ['Embed', 'Finetuning'],
94+
techStack: ['CrewAI', 'Weaviate']
95+
},
96+
href: '/page/analysis-of-financial-forms',
97+
author: {
98+
name: "Alex Barbet",
99+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/bf2c763-Alex.jpg"
100+
}
101+
},
102+
{
103+
title: "Analyzing Hacker News with Cohere",
104+
description: "Build a generative-AI powered tool to analyze headlines with Cohere's language models.",
105+
imageSrc: "https://via.placeholder.com/400x200?text=Hacker+News+Analysis",
106+
tags: {
107+
useCases: ['Embeddings', 'Classification', 'Summarization'],
108+
endpoints: ['Chat', 'Rerank'],
109+
techStack: ['Langchain', 'LlamaIndex']
110+
},
111+
href: '/page/analyzing-hacker-news',
112+
author: {
113+
name: "Ania Bialas",
114+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/c5dc5a3-Ania.jpg"
115+
}
116+
},
117+
{
118+
title: "Article Recommender with Text Embedding",
119+
description: "Build a generative-AI tool to recommend articles with Cohere's embedding and classification capabilities.",
120+
imageSrc: "https://via.placeholder.com/400x200?text=Article+Recommender",
121+
tags: {
122+
useCases: ['Embeddings', 'Classification', 'Search'],
123+
endpoints: ['Embed', 'Rerank'],
124+
techStack: ['Pinecone', 'CrewAI']
125+
},
126+
href: '/page/article-recommender-with-text-embeddings',
127+
author: {
128+
name: "Giannis Chatziveroglou",
129+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/73153cb-giannis.jpeg"
130+
}
131+
},
132+
{
133+
title: "Basic Multi-Step Tool Use with Cohere",
134+
description: "Create a multi-step, tool-using AI agent with Cohere's tool use functionality.",
135+
imageSrc: "https://via.placeholder.com/400x200?text=Multi-Step+Tool+Use",
136+
tags: {
137+
useCases: ['Agents', 'Tool Use', 'Multi-step'],
138+
endpoints: ['Chat', 'Finetuning'],
139+
techStack: ['Weaviate', 'Langchain']
140+
},
141+
href: '/page/basic-multi-step',
142+
author: {
143+
name: "Komal Teru",
144+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/7026fcc-komal-headshot.jpg"
145+
}
146+
},
147+
{
148+
title: "Basic RAG: Retrieval-Augmented Generation",
149+
description: "Learn how to work with Cohere's basic retrieval-augmented generation functionality.",
150+
imageSrc: "https://via.placeholder.com/400x200?text=Basic+RAG",
151+
tags: {
152+
useCases: ['RAG', 'Embeddings', 'Text Generation'],
153+
endpoints: ['Chat', 'Embed'],
154+
techStack: ['LlamaIndex', 'Pinecone']
155+
},
156+
href: '/page/basic-rag',
157+
author: {
158+
name: "Youran Qi",
159+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/929cb1c-youran-headshot.jpg"
160+
}
161+
},
162+
{
163+
title: "Basic Semantic Search with Cohere Models",
164+
description: "Implement basic semantic search with Cohere's embedding models.",
165+
imageSrc: "https://via.placeholder.com/400x200?text=Semantic+Search",
166+
tags: {
167+
useCases: ['Search', 'Embeddings', 'Semantic Search'],
168+
endpoints: ['Embed', 'Rerank'],
169+
techStack: ['Weaviate', 'CrewAI']
170+
},
171+
href: '/page/basic-semantic-search',
172+
author: {
173+
name: "Mike Mao",
174+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/d514b09-mike-headshot.jpg"
175+
}
176+
},
177+
{
178+
title: "Calendar Agent with Native Multi Step Tool",
179+
description: "Use Cohere Chat API with list_calendar_events and create_calendar_event tools to book appointments.",
180+
imageSrc: "https://via.placeholder.com/400x200?text=Calendar+Agent",
181+
tags: {
182+
useCases: ['Agents', 'Tool Use', 'Multi-step'],
183+
endpoints: ['Chat', 'Finetuning'],
184+
techStack: ['Langchain', 'LlamaIndex']
185+
},
186+
href: '/page/calendar-agent',
187+
author: {
188+
name: "Aal Patankar",
189+
image: "https://fern-image-hosting.s3.amazonaws.com/cohere/d48e622-Aal.jpg"
190+
}
191+
},
192+
];
193+
194+
// Create an array of 27 cookbooks by spreading the base cookbooks three times
195+
const cookbooks: Cookbook[] = [
196+
...baseCookbooks,
197+
...baseCookbooks.map(cookbook => ({
198+
...cookbook,
199+
href: `${cookbook.href}-2`, // Add suffix to make hrefs unique
200+
})),
201+
...baseCookbooks.map(cookbook => ({
202+
...cookbook,
203+
href: `${cookbook.href}-3`, // Add suffix to make hrefs unique
204+
}))
205+
];
206+
207+
// Filter cookbooks based on search query and selected tags
208+
const filteredCookbooks = cookbooks.filter(cookbook => {
209+
const matchesQuery = searchQuery === '' ||
210+
cookbook.title.toLowerCase().includes(searchQuery.toLowerCase());
211+
212+
const matchesUseCases = selectedTags.useCases.length === 0 ||
213+
selectedTags.useCases.every(tag => cookbook.tags.useCases.includes(tag));
214+
215+
const matchesEndpoints = selectedTags.endpoints.length === 0 ||
216+
selectedTags.endpoints.every(tag => cookbook.tags.endpoints.includes(tag));
217+
218+
const matchesTechStack = selectedTags.techStack.length === 0 ||
219+
selectedTags.techStack.every(tag => cookbook.tags.techStack.includes(tag));
220+
221+
return matchesQuery && matchesUseCases && matchesEndpoints && matchesTechStack;
222+
});
223+
224+
// Function to get random color from array
225+
const getRandomColor = (index: number) => {
226+
return CARD_COLORS[index % CARD_COLORS.length];
227+
};
228+
229+
// Helper function to check if a tag is selected
230+
const isTagSelected = (category: keyof TagCategories, tag: string) => {
231+
return selectedTags[category].includes(tag);
232+
};
233+
234+
// Helper function to toggle a tag
235+
const toggleTag = (category: keyof TagCategories, tag: string) => {
236+
setSelectedTags(prev => ({
237+
...prev,
238+
[category]: prev[category].includes(tag)
239+
? prev[category].filter(t => t !== tag)
240+
: [...prev[category], tag]
241+
}));
242+
};
243+
244+
return (
245+
<div className="w-full">
246+
{/* Sidebar and main content container */}
247+
<div className="flex flex-col md:flex-row gap-8">
248+
{/* Sidebar */}
249+
<div className="w-full md:w-64 flex-shrink-0">
250+
<div className="sticky top-4">
251+
{/* Use Cases */}
252+
<div className="mb-6">
253+
<h3 className="text-sm font-medium mb-4">Use Cases</h3>
254+
<div className="flex flex-wrap gap-2">
255+
{ALL_TAGS.useCases.map(tag => (
256+
<button
257+
key={tag}
258+
onClick={() => toggleTag('useCases', tag)}
259+
className={`${tagButtonClass} ${
260+
isTagSelected('useCases', tag) ? selectedTagClass : unselectedTagClass
261+
}`}
262+
>
263+
{tag}
264+
</button>
265+
))}
266+
</div>
267+
</div>
268+
269+
{/* Endpoints */}
270+
<div className="mb-6">
271+
<h3 className="text-sm font-medium mb-4">Endpoints</h3>
272+
<div className="flex flex-wrap gap-2">
273+
{ALL_TAGS.endpoints.map(tag => (
274+
<button
275+
key={tag}
276+
onClick={() => toggleTag('endpoints', tag)}
277+
className={`${tagButtonClass} ${
278+
isTagSelected('endpoints', tag) ? selectedTagClass : unselectedTagClass
279+
}`}
280+
>
281+
{tag}
282+
</button>
283+
))}
284+
</div>
285+
</div>
286+
287+
{/* Tools */}
288+
<div className="mb-6">
289+
<h3 className="text-sm font-medium mb-4">Tools</h3>
290+
<div className="flex flex-wrap gap-2">
291+
{ALL_TAGS.techStack.map(tag => (
292+
<button
293+
key={tag}
294+
onClick={() => toggleTag('techStack', tag)}
295+
className={`${tagButtonClass} ${
296+
isTagSelected('techStack', tag) ? selectedTagClass : unselectedTagClass
297+
}`}
298+
>
299+
{tag}
300+
</button>
301+
))}
302+
</div>
303+
</div>
304+
</div>
305+
</div>
306+
307+
{/* Main content */}
308+
<div className="flex-1">
309+
<div className="flex flex-col md:flex-row justify-between items-start md:items-center mb-6 gap-4">
310+
<div className="w-full">
311+
<div className="relative">
312+
<input
313+
type="text"
314+
placeholder="Search"
315+
value={searchQuery}
316+
onChange={(e) => setSearchQuery(e.target.value)}
317+
className="w-full px-4 py-2 pl-10 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
318+
/>
319+
<div className="absolute left-3 top-1/2 transform -translate-y-1/2">
320+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="text-gray-400" viewBox="0 0 16 16">
321+
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
322+
</svg>
323+
</div>
324+
</div>
325+
</div>
326+
</div>
327+
328+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
329+
{filteredCookbooks.map((cookbook, index) => (
330+
<a
331+
key={index}
332+
href={cookbook.href}
333+
className={`block border border-gray-200 rounded-lg hover:shadow-md transition-shadow ${getRandomColor(index)}`}
334+
>
335+
<div className="p-6">
336+
<h3 className="text-base font-medium text-gray-800 mb-3">{cookbook.title}</h3>
337+
338+
{cookbook.author && (
339+
<div className="flex items-center mb-4">
340+
<img
341+
src={cookbook.author.image}
342+
alt={cookbook.author.name}
343+
className="w-5 h-5 rounded-full mr-2"
344+
/>
345+
<span className="text-xs text-gray-600">{cookbook.author.name}</span>
346+
</div>
347+
)}
348+
349+
{/* Display only endpoint tags */}
350+
<div className="flex flex-wrap gap-1.5">
351+
{cookbook.tags.endpoints.map((tag, tagIndex) => (
352+
<span
353+
key={tagIndex}
354+
className="px-1.5 py-0.5 text-[10px] text-gray-600 bg-white/50 rounded-full"
355+
>
356+
{tag}
357+
</span>
358+
))}
359+
</div>
360+
</div>
361+
</a>
362+
))}
363+
</div>
364+
</div>
365+
</div>
366+
</div>
367+
);
368+
};

0 commit comments

Comments
 (0)