Skip to content

Commit aa4bfd6

Browse files
authored
feat(docs): add DocsGPT widget to documentation site (#22513)
## Summary - Adds the `docsgpt-react` widget to the docs site as a Docusaurus client module - Provides an AI assistant chat widget for developer questions about Aztec protocol - Configured with Aztec branding (dark theme, Aztec colors and avatar) ## Test plan - [ ] Run `yarn start` in `docs/` and verify the widget appears on the page - [ ] Click the widget button and confirm the chat interface opens - [ ] Ask a question and verify responses are returned from the DocsGPT backend - [ ] Update `apiHost` to point to production before merging
2 parents b4b3fcc + 166f6fa commit aa4bfd6

16 files changed

Lines changed: 1796 additions & 2734 deletions

File tree

docs/docusaurus.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ const config = {
289289
],
290290
// ["./src/plugins/plugin-embed-code", {}],
291291
],
292+
clientModules: [
293+
'./src/clientModules/docsgpt.js',
294+
],
292295
customFields: {},
293296
themeConfig:
294297
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */

docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
"test:preprocess": "node --test src/preprocess/__tests__/*.test.js"
2222
},
2323
"dependencies": {
24-
"@cookbookdev/docsbot": "^4.25.15",
2524
"@docusaurus/core": "3.9.1",
2625
"@docusaurus/plugin-content-docs": "3.9.1",
2726
"@docusaurus/plugin-ideal-image": "3.9.1",
@@ -36,6 +35,7 @@
3635
"react-markdown": "6.0.3",
3736
"react-player": "^2.16.1",
3837
"rehype-katex": "7",
38+
"remark-gfm": "^1.0.0",
3939
"remark-math": "6"
4040
},
4141
"devDependencies": {

docs/src/clientModules/docsgpt.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
2+
3+
if (ExecutionEnvironment.canUseDOM) {
4+
const React = require('react');
5+
const ReactDOM = require('react-dom/client');
6+
const AztecDocsWidget = require('@site/src/components/AztecDocsWidget').default;
7+
8+
const container = document.createElement('div');
9+
container.id = 'docsgpt-widget';
10+
document.body.appendChild(container);
11+
12+
const root = ReactDOM.createRoot(container);
13+
root.render(
14+
React.createElement(AztecDocsWidget, {
15+
apiHost: 'https://aztec.adjacentpossible.dev',
16+
apiKey: '44420ab5-6be3-4b30-af35-559c38bfce6d',
17+
title: 'Ask about Aztec',
18+
heroTitle: 'Aztec Docs Assistant',
19+
heroDescription:
20+
'Searches Aztec v4.2.0 developer docs, Aztec.nr, aztec.js SDK, protocol circuits, and more.',
21+
theme: 'ink',
22+
accent: 'chartreuse',
23+
buttonStyle: 'symbol',
24+
size: 'roomy',
25+
position: 'br',
26+
motif: true,
27+
}),
28+
);
29+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import React from "react";
2+
import { AztecMark, Icons } from "./Icons";
3+
4+
export default function Hero({
5+
heroTitle,
6+
heroDescription,
7+
suggestedPrompts,
8+
motif,
9+
tokens,
10+
onSuggest,
11+
}) {
12+
const { isInk, accentColor, panelFg, panelFg2, panelSurface, panelSurface2 } =
13+
tokens;
14+
return (
15+
<div
16+
style={{
17+
padding: "28px 24px 20px",
18+
textAlign: "left",
19+
position: "relative",
20+
}}
21+
>
22+
{motif && (
23+
<div
24+
style={{
25+
position: "absolute",
26+
right: -10,
27+
top: -30,
28+
opacity: isInk ? 0.12 : 0.18,
29+
pointerEvents: "none",
30+
}}
31+
>
32+
<AztecMark size={180} color={accentColor} />
33+
</div>
34+
)}
35+
<div style={{ position: "relative" }}>
36+
<div
37+
style={{
38+
display: "inline-flex",
39+
alignItems: "center",
40+
gap: 8,
41+
padding: "4px 10px",
42+
border: `1px solid ${panelFg2}`,
43+
color: panelFg2,
44+
fontFamily: "var(--azw-font-mono)",
45+
fontSize: 11,
46+
letterSpacing: "0.1em",
47+
textTransform: "uppercase",
48+
marginBottom: 18,
49+
}}
50+
>
51+
<span
52+
style={{
53+
width: 6,
54+
height: 6,
55+
borderRadius: 999,
56+
background: accentColor,
57+
boxShadow: `0 0 8px ${accentColor}`,
58+
}}
59+
/>
60+
Aztec Docs · AI
61+
</div>
62+
<h2
63+
style={{
64+
fontFamily: "var(--azw-font-display)",
65+
fontWeight: 300,
66+
fontSize: 32,
67+
lineHeight: 1.0,
68+
letterSpacing: "-0.03em",
69+
color: panelFg,
70+
margin: "0 0 10px",
71+
}}
72+
>
73+
{heroTitle}
74+
</h2>
75+
<p
76+
style={{
77+
fontFamily: "var(--azw-font-sans)",
78+
fontWeight: 400,
79+
fontSize: 14,
80+
lineHeight: 1.4,
81+
color: panelFg2,
82+
margin: "0 0 22px",
83+
maxWidth: "92%",
84+
letterSpacing: "-0.01em",
85+
}}
86+
>
87+
{heroDescription}
88+
</p>
89+
90+
{suggestedPrompts?.length > 0 && (
91+
<>
92+
<div
93+
style={{
94+
fontFamily: "var(--azw-font-mono)",
95+
fontSize: 10,
96+
letterSpacing: "0.12em",
97+
textTransform: "uppercase",
98+
color: panelFg2,
99+
marginBottom: 10,
100+
}}
101+
>
102+
Try asking —
103+
</div>
104+
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
105+
{suggestedPrompts.map((p) => (
106+
<button
107+
key={p}
108+
onClick={() => onSuggest(p)}
109+
style={{
110+
display: "flex",
111+
alignItems: "center",
112+
justifyContent: "space-between",
113+
textAlign: "left",
114+
padding: "10px 12px",
115+
background: panelSurface,
116+
color: panelFg,
117+
border: `1px solid ${isInk ? "rgba(242,238,225,0.12)" : "var(--azw-ink-tint-1)"}`,
118+
fontFamily: "var(--azw-font-sans)",
119+
fontSize: 13,
120+
fontWeight: 500,
121+
cursor: "pointer",
122+
borderRadius: 0,
123+
transition:
124+
"background 120ms var(--azw-ease), border-color 120ms var(--azw-ease)",
125+
}}
126+
onMouseEnter={(e) => {
127+
e.currentTarget.style.background = panelSurface2;
128+
e.currentTarget.style.borderColor = accentColor;
129+
}}
130+
onMouseLeave={(e) => {
131+
e.currentTarget.style.background = panelSurface;
132+
e.currentTarget.style.borderColor = isInk
133+
? "rgba(242,238,225,0.12)"
134+
: "var(--azw-ink-tint-1)";
135+
}}
136+
>
137+
<span>{p}</span>
138+
<Icons.arrowUpRight size={12} />
139+
</button>
140+
))}
141+
</div>
142+
</>
143+
)}
144+
</div>
145+
</div>
146+
);
147+
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import React from "react";
2+
3+
export function AztecMark({ size = 24, color = "currentColor", stroke = 0 }) {
4+
const c = size / 2;
5+
const rings = [0.96, 0.7, 0.44, 0.2];
6+
return (
7+
<svg
8+
width={size}
9+
height={size}
10+
viewBox={`0 0 ${size} ${size}`}
11+
aria-hidden="true"
12+
style={{ display: "block" }}
13+
>
14+
{rings.map((r, i) => {
15+
const half = (size * r) / 2;
16+
const d = `M ${c} ${c - half} L ${c + half} ${c} L ${c} ${c + half} L ${c - half} ${c} Z`;
17+
return (
18+
<path
19+
key={i}
20+
d={d}
21+
fill={i % 2 === 0 ? color : "none"}
22+
stroke={i % 2 === 0 ? "none" : color}
23+
strokeWidth={stroke || Math.max(1, size * 0.04)}
24+
/>
25+
);
26+
})}
27+
</svg>
28+
);
29+
}
30+
31+
export const Icons = {
32+
close: (p) => (
33+
<svg
34+
viewBox="0 0 24 24"
35+
width={p.size || 18}
36+
height={p.size || 18}
37+
fill="none"
38+
stroke="currentColor"
39+
strokeWidth="2"
40+
strokeLinecap="round"
41+
strokeLinejoin="round"
42+
>
43+
<path d="M18 6L6 18" />
44+
<path d="M6 6l12 12" />
45+
</svg>
46+
),
47+
send: (p) => (
48+
<svg
49+
viewBox="0 0 24 24"
50+
width={p.size || 18}
51+
height={p.size || 18}
52+
fill="none"
53+
stroke="currentColor"
54+
strokeWidth="2"
55+
strokeLinecap="round"
56+
strokeLinejoin="round"
57+
>
58+
<path d="M5 12h14" />
59+
<path d="M13 6l6 6-6 6" />
60+
</svg>
61+
),
62+
chat: (p) => (
63+
<svg
64+
viewBox="0 0 24 24"
65+
width={p.size || 22}
66+
height={p.size || 22}
67+
fill="none"
68+
stroke="currentColor"
69+
strokeWidth="2"
70+
strokeLinecap="round"
71+
strokeLinejoin="round"
72+
>
73+
<path d="M21 12a8 8 0 0 1-11.5 7.2L3 20l1-4.8A8 8 0 1 1 21 12z" />
74+
</svg>
75+
),
76+
refresh: (p) => (
77+
<svg
78+
viewBox="0 0 24 24"
79+
width={p.size || 14}
80+
height={p.size || 14}
81+
fill="none"
82+
stroke="currentColor"
83+
strokeWidth="2"
84+
strokeLinecap="round"
85+
strokeLinejoin="round"
86+
>
87+
<path d="M3 12a9 9 0 0 1 15-6.7L21 8" />
88+
<path d="M21 3v5h-5" />
89+
<path d="M21 12a9 9 0 0 1-15 6.7L3 16" />
90+
<path d="M3 21v-5h5" />
91+
</svg>
92+
),
93+
arrowUpRight: (p) => (
94+
<svg
95+
viewBox="0 0 24 24"
96+
width={p.size || 12}
97+
height={p.size || 12}
98+
fill="none"
99+
stroke="currentColor"
100+
strokeWidth="2"
101+
strokeLinecap="round"
102+
strokeLinejoin="round"
103+
>
104+
<path d="M7 17L17 7" />
105+
<path d="M8 7h9v9" />
106+
</svg>
107+
),
108+
doc: (p) => (
109+
<svg
110+
viewBox="0 0 24 24"
111+
width={p.size || 12}
112+
height={p.size || 12}
113+
fill="none"
114+
stroke="currentColor"
115+
strokeWidth="2"
116+
strokeLinecap="round"
117+
strokeLinejoin="round"
118+
>
119+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
120+
<path d="M14 2v6h6" />
121+
</svg>
122+
),
123+
expand: (p) => (
124+
<svg
125+
viewBox="0 0 24 24"
126+
width={p.size || 14}
127+
height={p.size || 14}
128+
fill="none"
129+
stroke="currentColor"
130+
strokeWidth="2"
131+
strokeLinecap="round"
132+
strokeLinejoin="round"
133+
>
134+
<path d="M15 3h6v6" />
135+
<path d="M9 21H3v-6" />
136+
<path d="M21 3l-7 7" />
137+
<path d="M3 21l7-7" />
138+
</svg>
139+
),
140+
collapse: (p) => (
141+
<svg
142+
viewBox="0 0 24 24"
143+
width={p.size || 14}
144+
height={p.size || 14}
145+
fill="none"
146+
stroke="currentColor"
147+
strokeWidth="2"
148+
strokeLinecap="round"
149+
strokeLinejoin="round"
150+
>
151+
<path d="M4 14h6v6" />
152+
<path d="M20 10h-6V4" />
153+
<path d="M14 10l7-7" />
154+
<path d="M3 21l7-7" />
155+
</svg>
156+
),
157+
};

0 commit comments

Comments
 (0)