Skip to content

Commit e10863c

Browse files
committed
Keep MDX snippets on the client boundary
Compiled MDX calls createContext; as Server Components that hits the RSC React subset and breaks /ai. Wrap each snippet in a client leaf so the section shells can stay on the server.
1 parent a4377d5 commit e10863c

6 files changed

Lines changed: 110 additions & 40 deletions

File tree

‎src/app/(main)/ai/components/by-the-numbers.tsx‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { SectionLabel } from "@/app/conf/_design-system/section-label"
22
import { Anchor } from "@/app/conf/_design-system/anchor"
3-
import { snippetComponents } from "./snippets"
4-
import SchemaSnippet from "./snippets/numbers-schema.mdx"
5-
import IntrospectionSnippet from "./snippets/numbers-introspection.mdx"
6-
import ResponseSnippet from "./snippets/numbers-response.mdx"
3+
import {
4+
NumbersIntrospectionSnippet,
5+
NumbersResponseSnippet,
6+
NumbersSchemaSnippet,
7+
} from "./snippets"
78

89
const stats = [
910
{
@@ -159,9 +160,9 @@ export function ByTheNumbers() {
159160
to.
160161
</p>
161162
<div className="grid gap-4 lg:grid-cols-3">
162-
<SchemaSnippet components={snippetComponents} />
163-
<IntrospectionSnippet components={snippetComponents} />
164-
<ResponseSnippet components={snippetComponents} />
163+
<NumbersSchemaSnippet />
164+
<NumbersIntrospectionSnippet />
165+
<NumbersResponseSnippet />
165166
</div>
166167
</div>
167168
</section>

‎src/app/(main)/ai/components/how-it-works.tsx‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import SearchIcon from "@/app/conf/_design-system/pixelarticons/search.svg?svgr"
55
import CodeIcon from "@/app/conf/_design-system/pixelarticons/code.svg?svgr"
66
import PlayIcon from "@/app/conf/_design-system/pixelarticons/play.svg?svgr"
77
import CheckIcon from "@/app/conf/_design-system/pixelarticons/check.svg?svgr"
8-
import { snippetComponents } from "./snippets"
9-
import PromptSnippet from "./snippets/step-prompt.mdx"
10-
import IntrospectionSnippet from "./snippets/step-introspection.mdx"
11-
import QuerySnippet from "./snippets/step-query.mdx"
12-
import ResponseSnippet from "./snippets/step-response.mdx"
8+
import {
9+
StepIntrospectionSnippet,
10+
StepPromptSnippet,
11+
StepQuerySnippet,
12+
StepResponseSnippet,
13+
} from "./snippets"
1314

1415
const steps = [
1516
{
@@ -18,31 +19,31 @@ const steps = [
1819
icon: PlayIcon,
1920
description:
2021
'A user gives an AI agent a natural language instruction — "Show me Q4 revenue by region." The agent needs to access business data through an API to fulfill this request.',
21-
Snippet: PromptSnippet,
22+
Snippet: StepPromptSnippet,
2223
},
2324
{
2425
number: "02",
2526
title: "Agent introspects the API",
2627
icon: SearchIcon,
2728
description:
2829
"Using GraphQL introspection, the agent queries `__schema` and discovers the available types: `Product`, `Order`, `Region`, `RevenueMetrics`. It learns field names, arguments, and relationships automatically.",
29-
Snippet: IntrospectionSnippet,
30+
Snippet: StepIntrospectionSnippet,
3031
},
3132
{
3233
number: "03",
3334
title: "Agent composes a query",
3435
icon: CodeIcon,
3536
description:
3637
"The LLM maps the user's intent to the discovered schema. It constructs a precise GraphQL query that fetches exactly the right data — revenue by region, top 5 categories, all in a single request — with no over-fetching.",
37-
Snippet: QuerySnippet,
38+
Snippet: StepQuerySnippet,
3839
},
3940
{
4041
number: "04",
4142
title: "Structured response returned",
4243
icon: CheckIcon,
4344
description:
4445
"The response is JSON in the query's shape. A nullable field can still come back null with an `errors` entry, but the agent already knows the shape, so it can use a partial result as-is.",
45-
Snippet: ResponseSnippet,
46+
Snippet: StepResponseSnippet,
4647
},
4748
]
4849

@@ -99,7 +100,7 @@ export function HowItWorks() {
99100
"lg:flex lg:h-full lg:flex-col lg:[&>div]:flex lg:[&>div]:min-h-0 lg:[&>div]:flex-1 lg:[&>div]:flex-col lg:[&_pre]:min-h-0 lg:[&_pre]:flex-1",
100101
)}
101102
>
102-
<step.Snippet components={snippetComponents} />
103+
<step.Snippet />
103104
</div>
104105
</div>
105106
))}

‎src/app/(main)/ai/components/snippets/index.ts‎

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"use client"
2+
3+
import { Code } from "nextra/components"
4+
5+
import { Pre } from "@/components/pre"
6+
7+
import NumbersIntrospection from "./numbers-introspection.mdx"
8+
import NumbersResponse from "./numbers-response.mdx"
9+
import NumbersSchema from "./numbers-schema.mdx"
10+
import StepIntrospection from "./step-introspection.mdx"
11+
import StepPrompt from "./step-prompt.mdx"
12+
import StepQuery from "./step-query.mdx"
13+
import StepResponse from "./step-response.mdx"
14+
import UseCaseAgents from "./use-case-agents.mdx"
15+
import UseCaseMcp from "./use-case-mcp.mdx"
16+
import UseCaseRag from "./use-case-rag.mdx"
17+
import WhyComposable from "./why-composable.mdx"
18+
import WhySelfDescribing from "./why-self-describing.mdx"
19+
import WhyStronglyTyped from "./why-strongly-typed.mdx"
20+
21+
const components = { pre: Pre, code: Code }
22+
23+
export function NumbersSchemaSnippet() {
24+
return <NumbersSchema components={components} />
25+
}
26+
27+
export function NumbersIntrospectionSnippet() {
28+
return <NumbersIntrospection components={components} />
29+
}
30+
31+
export function NumbersResponseSnippet() {
32+
return <NumbersResponse components={components} />
33+
}
34+
35+
export function StepPromptSnippet() {
36+
return <StepPrompt components={components} />
37+
}
38+
39+
export function StepIntrospectionSnippet() {
40+
return <StepIntrospection components={components} />
41+
}
42+
43+
export function StepQuerySnippet() {
44+
return <StepQuery components={components} />
45+
}
46+
47+
export function StepResponseSnippet() {
48+
return <StepResponse components={components} />
49+
}
50+
51+
export function UseCaseMcpSnippet() {
52+
return <UseCaseMcp components={components} />
53+
}
54+
55+
export function UseCaseRagSnippet() {
56+
return <UseCaseRag components={components} />
57+
}
58+
59+
export function UseCaseAgentsSnippet() {
60+
return <UseCaseAgents components={components} />
61+
}
62+
63+
export function WhySelfDescribingSnippet() {
64+
return <WhySelfDescribing components={components} />
65+
}
66+
67+
export function WhyStronglyTypedSnippet() {
68+
return <WhyStronglyTyped components={components} />
69+
}
70+
71+
export function WhyComposableSnippet() {
72+
return <WhyComposable components={components} />
73+
}

‎src/app/(main)/ai/components/use-cases.tsx‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.sv
44
import MCPIcon from "@/app/conf/_design-system/pixelarticons/modem.svg?svgr"
55
import SearchIcon from "@/app/conf/_design-system/pixelarticons/search.svg?svgr"
66
import CodeIcon from "@/app/conf/_design-system/pixelarticons/code.svg?svgr"
7-
import { snippetComponents } from "./snippets"
8-
import McpSnippet from "./snippets/use-case-mcp.mdx"
9-
import RagSnippet from "./snippets/use-case-rag.mdx"
10-
import AgentsSnippet from "./snippets/use-case-agents.mdx"
7+
import {
8+
UseCaseAgentsSnippet,
9+
UseCaseMcpSnippet,
10+
UseCaseRagSnippet,
11+
} from "./snippets"
1112

1213
const useCases = [
1314
{
@@ -20,7 +21,7 @@ const useCases = [
2021
"Type-safe inputs and structured outputs",
2122
"One MCP server exposes your entire API surface",
2223
],
23-
Snippet: McpSnippet,
24+
Snippet: UseCaseMcpSnippet,
2425
href: "/blog/2025-10-14-announcing-ai-wg/",
2526
cta: "Join the AI Working Group",
2627
},
@@ -34,7 +35,7 @@ const useCases = [
3435
"Join data across collections and sources",
3536
"Minimize context window waste with field selection",
3637
],
37-
Snippet: RagSnippet,
38+
Snippet: UseCaseRagSnippet,
3839
href: "/resources/ai",
3940
cta: "Explore AI resources",
4041
},
@@ -48,7 +49,7 @@ const useCases = [
4849
"Real-time subscriptions for streaming agents",
4950
"Single endpoint for all data operations",
5051
],
51-
Snippet: AgentsSnippet,
52+
Snippet: UseCaseAgentsSnippet,
5253
href: "/blog/2025-07-03-graphql-supercharging-ai/",
5354
cta: "Read the blog post",
5455
},
@@ -84,7 +85,7 @@ export function UseCases() {
8485
</p>
8586

8687
<div className="mt-5">
87-
<useCase.Snippet components={snippetComponents} />
88+
<useCase.Snippet />
8889
</div>
8990

9091
<ul className="typography-body-sm mt-5 flex flex-col gap-1.5">

‎src/app/(main)/ai/components/why-graphql-ai.tsx‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import CheckIcon from "@/app/conf/_design-system/pixelarticons/check.svg?svgr"
33
import SearchIcon from "@/app/conf/_design-system/pixelarticons/search.svg?svgr"
44
import ZapIcon from "@/app/conf/_design-system/pixelarticons/zap.svg?svgr"
55
import SlidersIcon from "@/app/conf/_design-system/pixelarticons/sliders.svg?svgr"
6-
import { snippetComponents } from "./snippets"
7-
import SelfDescribingSnippet from "./snippets/why-self-describing.mdx"
8-
import StronglyTypedSnippet from "./snippets/why-strongly-typed.mdx"
9-
import ComposableSnippet from "./snippets/why-composable.mdx"
6+
import {
7+
WhyComposableSnippet,
8+
WhySelfDescribingSnippet,
9+
WhyStronglyTypedSnippet,
10+
} from "./snippets"
1011
import { Eyebrow } from "@/_design-system/eyebrow"
1112

1213
const benefits = [
@@ -16,7 +17,7 @@ const benefits = [
1617
icon: SearchIcon,
1718
description:
1819
"Every GraphQL API ships with a built-in type system. AI agents query `__schema` and immediately understand what data is available, what arguments each field accepts, and how types relate — no hand-written tool descriptions needed.",
19-
Snippet: SelfDescribingSnippet,
20+
Snippet: WhySelfDescribingSnippet,
2021
bullets: [
2122
"Auto-generated tool definitions for LLMs",
2223
"Agents discover capabilities at runtime",
@@ -29,7 +30,7 @@ const benefits = [
2930
icon: ZapIcon,
3031
description:
3132
"Every field has a known, validated type. LLMs can reason about inputs and outputs with confidence. A wrong guess comes back as a named validation error the agent can correct, rather than a 200 with the wrong data in it.",
32-
Snippet: StronglyTypedSnippet,
33+
Snippet: WhyStronglyTypedSnippet,
3334
bullets: [
3435
"LLMs understand data shapes natively",
3536
"Validated responses prevent parsing errors",
@@ -42,7 +43,7 @@ const benefits = [
4243
icon: SlidersIcon,
4344
description:
4445
"Request exactly what you need, nothing more. GraphQL lets AI agents compose precise queries on the fly — requesting nested data, using aliases, and applying filters. One endpoint serves any data access pattern without client-side stitching.",
45-
Snippet: ComposableSnippet,
46+
Snippet: WhyComposableSnippet,
4647
bullets: [
4748
"Response size tracks the query, not the endpoint",
4849
"Dynamic query composition by AI agents",
@@ -83,7 +84,7 @@ export function WhyGraphQLAI() {
8384
</p>
8485

8586
<div className="mt-5">
86-
<benefit.Snippet components={snippetComponents} />
87+
<benefit.Snippet />
8788
</div>
8889

8990
<ul className="typography-body-sm flex flex-col gap-2 pt-5">

0 commit comments

Comments
 (0)