Skip to content

Commit 3be3d5f

Browse files
authored
feat: Add "Open in ChatGPT/Claude" buttons for each page (#15428)
Besides the existing "Copy Page" and "View as Markdown", I've added two more buttons in the dropdown so users can open that page in ChatGPT or Claude and ask questions about it: <img width="714" height="505" alt="image" src="https://github.com/user-attachments/assets/427c877f-4afc-4708-b945-05c1a65a8ba9" /> Both buttons are static links that open ChatGPT / Claude with predefined prompt. Example: https://chatgpt.com/?hint=search&q=Read+from+https://docs.sentry.io/platforms/javascript/+so+I+can+ask+questions+about+its+contents
1 parent 11395f0 commit 3be3d5f

File tree

5 files changed

+117
-0
lines changed

5 files changed

+117
-0
lines changed

src/components/copyMarkdownButton.tsx

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import {Clipboard} from 'react-feather';
66
import Link from 'next/link';
77

88
import {usePlausibleEvent} from 'sentry-docs/hooks/usePlausibleEvent';
9+
import ChatGPT from 'sentry-docs/icons/chatgpt';
910
import Chevron from 'sentry-docs/icons/Chevron';
11+
import Claude from 'sentry-docs/icons/claude';
12+
import ExternalLink from 'sentry-docs/icons/external-link';
1013
import Markdown from 'sentry-docs/icons/Markdown';
1114

1215
interface CopyMarkdownButtonProps {
@@ -66,6 +69,16 @@ export function CopyMarkdownButton({pathname}: CopyMarkdownButtonProps) {
6669
setIsOpen(false);
6770
};
6871

72+
const handleOpenChatGPTClick = () => {
73+
emit('Open in ChatGPT', {props: {page: pathname, source: 'chatgpt_link'}});
74+
setIsOpen(false);
75+
};
76+
77+
const handleOpenClaudeClick = () => {
78+
emit('Open in Claude', {props: {page: pathname, source: 'claude_link'}});
79+
setIsOpen(false);
80+
};
81+
6982
const handleDropdownToggle = () => {
7083
setIsOpen(!isOpen);
7184
if (!isOpen) {
@@ -204,6 +217,46 @@ export function CopyMarkdownButton({pathname}: CopyMarkdownButtonProps) {
204217
</div>
205218
</div>
206219
</Link>
220+
221+
<a
222+
href={`https://chatgpt.com/?hint=search&q=${encodeURIComponent('Read from ' + window.location.href + ' so I can ask questions about its contents')}`}
223+
target="_blank"
224+
rel="noopener noreferrer"
225+
className={`${dropdownItemClass} no-underline`}
226+
onClick={handleOpenChatGPTClick}
227+
>
228+
<div className={iconContainerClass}>
229+
<ChatGPT width={14} height={14} />
230+
</div>
231+
<div className="flex-1">
232+
<div className="font-medium text-sm leading-5 text-gray-900 dark:text-[var(--foreground)]">
233+
Open in ChatGPT <ExternalLink aria-hidden="true" />
234+
</div>
235+
<div className="text-xs leading-4 text-gray-500 dark:text-[var(--foreground-secondary)]">
236+
Ask ChatGPT questions about this page
237+
</div>
238+
</div>
239+
</a>
240+
241+
<a
242+
href={`https://claude.ai/new?q=${encodeURIComponent('Read from ' + window.location.href + ' so I can ask questions about its contents')}`}
243+
target="_blank"
244+
rel="noopener noreferrer"
245+
className={`${dropdownItemClass} no-underline`}
246+
onClick={handleOpenClaudeClick}
247+
>
248+
<div className={iconContainerClass}>
249+
<Claude width={14} height={14} />
250+
</div>
251+
<div className="flex-1">
252+
<div className="font-medium text-sm leading-5 text-gray-900 dark:text-[var(--foreground)]">
253+
Open in Claude <ExternalLink aria-hidden="true" />
254+
</div>
255+
<div className="text-xs leading-4 text-gray-500 dark:text-[var(--foreground-secondary)]">
256+
Ask Claude questions about this page
257+
</div>
258+
</div>
259+
</a>
207260
</div>
208261
</div>,
209262
document.body

src/hooks/usePlausibleEvent.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ type PlausibleEventProps = {
2727
page: string;
2828
title: string;
2929
};
30+
['Open in ChatGPT']: {
31+
page: string;
32+
source: string;
33+
};
34+
['Open in Claude']: {
35+
page: string;
36+
source: string;
37+
};
3038
['Read Progress']: {
3139
page: string;
3240
readProgress: ReadProgressMilestone;

src/icons/chatgpt.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
function ChatGPT({width = 16, height = 16, ...props}: React.SVGAttributes<SVGElement>) {
2+
return (
3+
<svg
4+
fill="currentColor"
5+
fillRule="evenodd"
6+
height={height}
7+
viewBox="0 0 24 24"
8+
width={width}
9+
xmlns="http://www.w3.org/2000/svg"
10+
{...props}
11+
>
12+
<path d="M21.55 10.004a5.416 5.416 0 00-.478-4.501c-1.217-2.09-3.662-3.166-6.05-2.66A5.59 5.59 0 0010.831 1C8.39.995 6.224 2.546 5.473 4.838A5.553 5.553 0 001.76 7.496a5.487 5.487 0 00.691 6.5 5.416 5.416 0 00.477 4.502c1.217 2.09 3.662 3.165 6.05 2.66A5.586 5.586 0 0013.168 23c2.443.006 4.61-1.546 5.361-3.84a5.553 5.553 0 003.715-2.66 5.488 5.488 0 00-.693-6.497v.001zm-8.381 11.558a4.199 4.199 0 01-2.675-.954c.034-.018.093-.05.132-.074l4.44-2.53a.71.71 0 00.364-.623v-6.176l1.877 1.069c.02.01.033.029.036.05v5.115c-.003 2.274-1.87 4.118-4.174 4.123zM4.192 17.78a4.059 4.059 0 01-.498-2.763c.032.02.09.055.131.078l4.44 2.53c.225.13.504.13.73 0l5.42-3.088v2.138a.068.068 0 01-.027.057L9.9 19.288c-1.999 1.136-4.552.46-5.707-1.51h-.001zM3.023 8.216A4.15 4.15 0 015.198 6.41l-.002.151v5.06a.711.711 0 00.364.624l5.42 3.087-1.876 1.07a.067.067 0 01-.063.005l-4.489-2.559c-1.995-1.14-2.679-3.658-1.53-5.63h.001zm15.417 3.54l-5.42-3.088L14.896 7.6a.067.067 0 01.063-.006l4.489 2.557c1.998 1.14 2.683 3.662 1.529 5.633a4.163 4.163 0 01-2.174 1.807V12.38a.71.71 0 00-.363-.623zm1.867-2.773a6.04 6.04 0 00-.132-.078l-4.44-2.53a.731.731 0 00-.729 0l-5.42 3.088V7.325a.068.068 0 01.027-.057L14.1 4.713c2-1.137 4.555-.46 5.707 1.513.487.833.664 1.809.499 2.757h.001zm-11.741 3.81l-1.877-1.068a.065.065 0 01-.036-.051V6.559c.001-2.277 1.873-4.122 4.181-4.12.976 0 1.92.338 2.671.954-.034.018-.092.05-.131.073l-4.44 2.53a.71.71 0 00-.365.623l-.003 6.173v.002zm1.02-2.168L12 9.25l2.414 1.375v2.75L12 14.75l-2.415-1.375v-2.75z" />
13+
</svg>
14+
);
15+
}
16+
export default ChatGPT;

src/icons/claude.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function Claude({width = 16, height = 16, ...props}: React.SVGAttributes<SVGElement>) {
2+
return (
3+
<svg
4+
fill="currentColor"
5+
fillRule="evenodd"
6+
height={height}
7+
viewBox="0 0 24 24"
8+
width={width}
9+
xmlns="http://www.w3.org/2000/svg"
10+
{...props}
11+
>
12+
<title>Claude</title>
13+
<path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z" />
14+
</svg>
15+
);
16+
}
17+
export default Claude;

src/icons/external-link.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
function ExternalLink({
2+
width = 14,
3+
height = 14,
4+
...props
5+
}: React.SVGAttributes<SVGElement>) {
6+
return (
7+
<span className="icon icon-external-link">
8+
<svg
9+
viewBox="0 0 24 24"
10+
width={width}
11+
height={height}
12+
className="ml-1 inline"
13+
{...props}
14+
>
15+
<path
16+
fill="currentColor"
17+
d="M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z"
18+
/>
19+
</svg>
20+
</span>
21+
);
22+
}
23+
export default ExternalLink;

0 commit comments

Comments
 (0)