Skip to content

Commit be9979f

Browse files
committed
chore(demo): add posthog events and link to docs
1 parent 2ab0b98 commit be9979f

File tree

2 files changed

+140
-98
lines changed

2 files changed

+140
-98
lines changed

packages/web/src/app/[domain]/components/homepage/askSourcebotDemoCards.tsx

Lines changed: 129 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ContextItem, RepoContextItem, SearchContextItem } from "@/features/chat
99
import { DemoExamples, DemoSearchExample, DemoSearchContextExample, DemoSearchContext } from "@/types";
1010
import { cn, getCodeHostIcon } from "@/lib/utils";
1111
import { RepositoryQuery, SearchContextQuery } from "@/lib/types";
12+
import useCaptureEvent from "@/hooks/useCaptureEvent";
1213

1314
interface AskSourcebotDemoCardsProps {
1415
demoExamples: DemoExamples;
@@ -25,7 +26,14 @@ export const AskSourcebotDemoCards = ({
2526
searchContexts,
2627
repos,
2728
}: AskSourcebotDemoCardsProps) => {
29+
const captureEvent = useCaptureEvent();
30+
2831
const handleExampleClick = (example: DemoSearchExample) => {
32+
captureEvent('wa_demo_search_example_card_pressed', {
33+
exampleTitle: example.title,
34+
exampleUrl: example.url || '',
35+
});
36+
2937
if (example.url) {
3038
window.open(example.url, '_blank');
3139
}
@@ -63,6 +71,12 @@ export const AskSourcebotDemoCards = ({
6371
return;
6472
}
6573

74+
captureEvent('wa_demo_search_context_card_pressed', {
75+
contextType: context.type,
76+
contextName: context.value,
77+
contextDisplayName: context.displayName,
78+
});
79+
6680
const isDemoMode = process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo";
6781
const isSelected = selectedItems.some((item) => item.value === context.value);
6882
if (isSelected) {
@@ -109,112 +123,129 @@ export const AskSourcebotDemoCards = ({
109123
}
110124

111125
return (
112-
<div className="w-full mt-8 space-y-12 px-4 max-w-[1000px]">
113-
{/* Search Context Row */}
114-
<div className="space-y-4">
115-
<div className="text-center mb-8">
116-
<div className="flex items-center justify-center gap-2 mb-2">
117-
<Layers className="h-5 w-5 text-muted-foreground" />
118-
<h3 className="text-lg font-semibold">Search Contexts</h3>
126+
<>
127+
{process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === "demo" && (
128+
<p className="text-sm text-muted-foreground text-center mt-6">
129+
Interested in using Sourcebot on your code? Check out our{' '}
130+
<a
131+
href="https://docs.sourcebot.dev/docs/overview"
132+
target="_blank"
133+
rel="noopener noreferrer"
134+
className="text-primary hover:underline"
135+
onClick={() => captureEvent('wa_demo_docs_link_pressed', {})}
136+
>
137+
docs
138+
</a>
139+
</p>
140+
)}
141+
142+
<div className="w-full mt-8 space-y-12 px-4 max-w-[1000px]">
143+
{/* Search Context Row */}
144+
<div className="space-y-4">
145+
<div className="text-center mb-8">
146+
<div className="flex items-center justify-center gap-2 mb-2">
147+
<Layers className="h-5 w-5 text-muted-foreground" />
148+
<h3 className="text-lg font-semibold">Search Contexts</h3>
149+
</div>
150+
<p className="text-sm text-muted-foreground">Select the context you want to ask questions about</p>
119151
</div>
120-
<p className="text-sm text-muted-foreground">Select the context you want to ask questions about</p>
121-
</div>
122-
<div className="flex flex-wrap justify-center gap-3">
123-
{demoExamples.searchContextExamples.map((contextExample) => {
124-
const context = demoExamples.searchContexts.find((context) => context.id === contextExample.searchContext)
125-
if (!context) {
126-
console.error(`Search context ${contextExample.searchContext} not found on handleContextClick`);
127-
return null;
128-
}
129-
130-
const isSelected = selectedItems.some(
131-
(selected) => (selected.type === 'context' && selected.value === context.value) ||
132-
(selected.type === 'repo' && selected.value === context.value)
133-
);
134-
135-
const searchContext = searchContexts.find((item) => item.name === context.value);
136-
const numRepos = searchContext ? searchContext.repoNames.length : undefined;
137-
return (
138-
<Card
139-
key={context.value}
140-
className={`cursor-pointer transition-all duration-200 hover:shadow-md hover:scale-105 group w-full max-w-[280px] ${isSelected ? "border-primary bg-primary/5 shadow-sm" : "hover:border-primary/50"
141-
}`}
142-
onClick={() => handleContextClick(demoExamples.searchContexts, contextExample)}
143-
>
144-
<CardContent className="p-4">
145-
<div className="flex items-start gap-3">
146-
<div
147-
className={`flex-shrink-0 p-2 rounded-lg transition-transform group-hover:scale-105`}
148-
>
149-
{getContextIcon(context)}
150-
</div>
151-
<div className="flex-1 min-w-0">
152-
<div className="flex items-center gap-2 mb-1">
153-
<h4
154-
className={`font-medium text-sm transition-colors ${isSelected ? "text-primary" : "group-hover:text-primary"
155-
}`}
156-
>
157-
{context.displayName}
158-
</h4>
159-
{numRepos && (
160-
<Badge className="text-[10px] px-1.5 py-0.5 h-4">
161-
{numRepos} repos
162-
</Badge>
163-
)}
152+
<div className="flex flex-wrap justify-center gap-3">
153+
{demoExamples.searchContextExamples.map((contextExample) => {
154+
const context = demoExamples.searchContexts.find((context) => context.id === contextExample.searchContext)
155+
if (!context) {
156+
console.error(`Search context ${contextExample.searchContext} not found on handleContextClick`);
157+
return null;
158+
}
159+
160+
const isSelected = selectedItems.some(
161+
(selected) => (selected.type === 'context' && selected.value === context.value) ||
162+
(selected.type === 'repo' && selected.value === context.value)
163+
);
164+
165+
const searchContext = searchContexts.find((item) => item.name === context.value);
166+
const numRepos = searchContext ? searchContext.repoNames.length : undefined;
167+
return (
168+
<Card
169+
key={context.value}
170+
className={`cursor-pointer transition-all duration-200 hover:shadow-md hover:scale-105 group w-full max-w-[280px] ${isSelected ? "border-primary bg-primary/5 shadow-sm" : "hover:border-primary/50"
171+
}`}
172+
onClick={() => handleContextClick(demoExamples.searchContexts, contextExample)}
173+
>
174+
<CardContent className="p-4">
175+
<div className="flex items-start gap-3">
176+
<div
177+
className={`flex-shrink-0 p-2 rounded-lg transition-transform group-hover:scale-105`}
178+
>
179+
{getContextIcon(context)}
180+
</div>
181+
<div className="flex-1 min-w-0">
182+
<div className="flex items-center gap-2 mb-1">
183+
<h4
184+
className={`font-medium text-sm transition-colors ${isSelected ? "text-primary" : "group-hover:text-primary"
185+
}`}
186+
>
187+
{context.displayName}
188+
</h4>
189+
{numRepos && (
190+
<Badge className="text-[10px] px-1.5 py-0.5 h-4">
191+
{numRepos} repos
192+
</Badge>
193+
)}
194+
</div>
195+
<p className="text-xs text-muted-foreground">{contextExample.description}</p>
164196
</div>
165-
<p className="text-xs text-muted-foreground">{contextExample.description}</p>
166197
</div>
167-
</div>
168-
</CardContent>
169-
</Card>
170-
)
171-
})}
198+
</CardContent>
199+
</Card>
200+
)
201+
})}
202+
</div>
172203
</div>
173-
</div>
174204

175-
{/* Example Searches Row */}
176-
<div className="space-y-4">
177-
<div className="text-center mb-8">
178-
<div className="flex items-center justify-center gap-2 mb-2">
179-
<Search className="h-5 w-5 text-muted-foreground" />
180-
<h3 className="text-lg font-semibold">Community Ask Results</h3>
205+
{/* Example Searches Row */}
206+
<div className="space-y-4">
207+
<div className="text-center mb-8">
208+
<div className="flex items-center justify-center gap-2 mb-2">
209+
<Search className="h-5 w-5 text-muted-foreground" />
210+
<h3 className="text-lg font-semibold">Community Ask Results</h3>
211+
</div>
212+
<p className="text-sm text-muted-foreground">Check out these featured ask results from the community</p>
181213
</div>
182-
<p className="text-sm text-muted-foreground">Check out these featured ask results from the community</p>
183-
</div>
184-
<div className="flex flex-wrap justify-center gap-3">
185-
{demoExamples.searchExamples.map((example) => {
186-
const searchContexts = demoExamples.searchContexts.filter((context) => example.searchContext.includes(context.id))
187-
return (
188-
<Card
189-
key={example.url}
190-
className="cursor-pointer transition-all duration-200 hover:shadow-md hover:scale-105 hover:border-primary/50 group w-full max-w-[350px]"
191-
onClick={() => handleExampleClick(example)}
192-
>
193-
<CardContent className="p-4">
194-
<div className="space-y-3">
195-
<div className="flex items-center justify-between">
196-
{searchContexts.map((context) => (
197-
<Badge key={context.value} variant="secondary" className="text-[10px] px-1.5 py-0.5 h-4 flex items-center gap-1">
198-
{getContextIcon(context, 12)}
199-
{context.displayName}
200-
</Badge>
201-
))}
202-
</div>
203-
<div className="space-y-1">
204-
<h4 className="font-semibold text-sm group-hover:text-primary transition-colors line-clamp-2">
205-
{example.title}
206-
</h4>
207-
<p className="text-xs text-muted-foreground line-clamp-3 leading-relaxed">
208-
{example.description}
209-
</p>
214+
<div className="flex flex-wrap justify-center gap-3">
215+
{demoExamples.searchExamples.map((example) => {
216+
const searchContexts = demoExamples.searchContexts.filter((context) => example.searchContext.includes(context.id))
217+
return (
218+
<Card
219+
key={example.url}
220+
className="cursor-pointer transition-all duration-200 hover:shadow-md hover:scale-105 hover:border-primary/50 group w-full max-w-[350px]"
221+
onClick={() => handleExampleClick(example)}
222+
>
223+
<CardContent className="p-4">
224+
<div className="space-y-3">
225+
<div className="flex items-center justify-between">
226+
{searchContexts.map((context) => (
227+
<Badge key={context.value} variant="secondary" className="text-[10px] px-1.5 py-0.5 h-4 flex items-center gap-1">
228+
{getContextIcon(context, 12)}
229+
{context.displayName}
230+
</Badge>
231+
))}
232+
</div>
233+
<div className="space-y-1">
234+
<h4 className="font-semibold text-sm group-hover:text-primary transition-colors line-clamp-2">
235+
{example.title}
236+
</h4>
237+
<p className="text-xs text-muted-foreground line-clamp-3 leading-relaxed">
238+
{example.description}
239+
</p>
240+
</div>
210241
</div>
211-
</div>
212-
</CardContent>
213-
</Card>
214-
)
215-
})}
242+
</CardContent>
243+
</Card>
244+
)
245+
})}
246+
</div>
216247
</div>
217248
</div>
218-
</div>
249+
</>
219250
);
220251
};

packages/web/src/lib/posthogEvents.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,5 +282,16 @@ export type PosthogEventMap = {
282282
chatId: string,
283283
messageId: string,
284284
},
285+
//////////////////////////////////////////////////////////////////
286+
wa_demo_docs_link_pressed: {},
287+
wa_demo_search_context_card_pressed: {
288+
contextType: string,
289+
contextName: string,
290+
contextDisplayName: string,
291+
},
292+
wa_demo_search_example_card_pressed: {
293+
exampleTitle: string,
294+
exampleUrl: string,
295+
},
285296
}
286297
export type PosthogEvent = keyof PosthogEventMap;

0 commit comments

Comments
 (0)