Add GraphQL & AI subpage (/ai) with interactive demos - #2469
Conversation
New /ai route showcasing GraphQL for AI systems (MCP servers, RAG, agents & tool calling). Includes hero with canvas particle network, interactive Star Wars GraphQL demo executing real queries client-side, syntax-highlighted code blocks, by-the-numbers stats, and CTA. - src/app/(main)/ai/: page + 9 components (hero, interactive-demo, how-it-works, why-graphql-ai, use-cases, by-the-numbers, cta-community, syntax-highlight) - src/pages/_meta.tsx: add 'ai' nav entry pointing to /ai - src/globals.css: add @Keyframes fadeInUp used by interactive demo - package.json + pnpm-lock.yaml: add sharp dependency
|
@aexol is attempting to deploy a commit to the The GraphQL Foundation Team on Vercel. A member of the Team first needs to authorize it. |
Run `prettier --write` on the 7 files flagged by `pnpm format:check` to unblock the CI prettier check on the feat/ai-subpage branch. No behavioral changes — formatting only.
| rest: "ad-hoc", | ||
| restDesc: "no guarantees", | ||
| explanation: | ||
| "GraphQL responses match the query shape exactly — validated against the schema at runtime. REST responses offer no structural guarantees, forcing LLMs to handle arbitrary JSON shapes.", |
There was a problem hiding this comment.
This is somewhat disingenuous considering that OpenAPI exists, and that most programming languages are fully typed.
I would suggest that this breaks down for agents specifically when they need to remember very complex types with deep relationships.
It's not the types that make the difference. It's that you don't need to know all of them at the same time when dealing with graph data.
| rest: "manual", | ||
| restDesc: "per endpoint", | ||
| explanation: | ||
| "Every GraphQL API includes built-in introspection. Agents can discover available types, fields, and arguments automatically. REST tool calling requires hand-crafted JSON Schema definitions for every endpoint.", |
There was a problem hiding this comment.
It doesn't have to be hand-crafted. Nearly every REST framework has automatic OpenAPI auto-creation capability built-in, so I don't think this is a point in GraphQL's favor.
You have to tell the agent where that schema is produced. It's built-in to the spec in GraphQL, so GraphQL is plug-in-play.
Similarly - and not mentioned here - is how easy it is to add per-field, per class, and per query documentation which can also be introspected.
So you need only a graphql schema instead of needing an AGENT.md + RAML + API in order to have things work with AI, and you don't need to tell an agent how to get to all three things; you only need one thing.
Type safety: REST is also typed (OpenAPI), so claiming 'no structural guarantees' was disingenuous. Both now show 100%; the real GraphQL edge for agents is graph traversal — no need to hold the entire type graph in context at once. Tool definitions: REST frameworks auto-generate OpenAPI, so 'hand-crafted' was inaccurate. The genuine advantage is plug-and-play: introspection and per-field/per-type/per-query docs are built into the spec and discoverable from one endpoint. With REST an agent needs the API + schema + an instruction file (AGENT.md), and you must point it to each. One GraphQL schema replaces all three (REST now shows '3' files to wire).
| graphQLDesc: "typed responses", | ||
| rest: "ad-hoc", | ||
| restDesc: "no guarantees", | ||
| rest: "100%", |
There was a problem hiding this comment.
Maybe you shouldn't make it 100% considering the statement?
There was a problem hiding this comment.
ok let me think more about this one
| restDesc: "files to wire", | ||
| explanation: | ||
| "Every GraphQL API includes built-in introspection. Agents can discover available types, fields, and arguments automatically. REST tool calling requires hand-crafted JSON Schema definitions for every endpoint.", | ||
| "REST frameworks can auto-generate OpenAPI, so this isn't about hand-writing schemas. The edge is plug-and-play: GraphQL's introspection and per-field, per-type, and per-query documentation are built into the spec and discoverable from one endpoint. With REST, an agent needs the API, its schema, and an instruction file (AGENT.md) — and you must point it to each. One GraphQL schema replaces all three.", |
There was a problem hiding this comment.
If you're including this in the description, it might be a good idea to also include examples of comment documentation embedded into a schema and queryable.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…layout - Add 'Docs live in the schema' subsection under the stats with three side-by-side code panes: a schema with embedded """ descriptions, the built-in __type introspection query, and the response returning those docs — proving documentation is queryable, not a separate file. Verified against the real graphql package (introspection returns the embedded descriptions). - Rebuild the GraphQL vs REST comparison from heavy stateful StatCards (IntersectionObserver count-up, 96px numbers, gradient bars, per-card callouts) into a compact, stateless table (Metric | GraphQL | REST | Why). Drop unused React hooks and ArrowUpIcon imports. - Make the comparison responsive: stacked compact panels on mobile (md:hidden) where the 4-column table was unusably tall (1868px), full table on desktop (hidden md:block). Reduces mobile section height by ~1360px. - Address reviewer feedback: REST is also typed, so Type safety now shows 'if used with correct tooling' instead of 'via OpenAPI'; Tool definitions already reframed around plug-and-play introspection vs wiring API + schema + AGENT.md. - Tighten section padding (lg:py-16 xl:py-24 -> lg:py-12 xl:py-16) and docs subsection gap (mt-16 -> mt-10).
| @@ -0,0 +1,297 @@ | |||
| "use client" | |||
There was a problem hiding this comment.
hey, the codebase already includes a GraphQL syntax highlighter used on other pages
should this really be added? maybe zero dependency isn't really a worthwhile goal to pursue if the design consistency is lost code grows with multiple solutions for one problem?
@aexol wdyt about using the mask image blur blobs the other pages used to make the stripes fade out and keep text readable |
|
@saihaj made changes to number section in the last commit |
|
@saihaj and I will take your design suggestions into account |
Reviewer feedback: the hero's pink stripe decoration used bright pri-light/pri-lighter (80-90% L) gradients at up to 0.6 opacity, producing washed-out bright pink blocks. The light secondary/tertiary buttons sat on those bright regions and became nearly invisible. Replace the bright gradients with darker ones that fade to transparent downward — pri-darker (20% L) + neu-900 — matching the fade-to- transparent stripe approach used on not-found, blog, and conf hero pages. Add dark: variants so the lines stay visible on the darker dark-mode bg (pri-light at low opacity + neu-0). Keep bg-pri-dark as the base: darkening it to pri-darker would drop the near-black primary CTA's contrast further (2.34:1 -> ~1.6:1). Concentrating the overlay at the top and clearing it over the button row gives the light buttons a darker surface to sit on. Verified via Playwright pixel sampling: behind-button surface luminance is now ~0.084 (dark), vs the previous bright-pink wash.
Reviewer feedback: the 'Or type your own prompt…' input box could not be
typed into usefully — custom prompts were keyword-matched against the 6
predefined demos and silently fell back to the first demo when unmatched,
so free text did not do what users expected.
Remove the input field and its Play button, along with the now-dead
runCustom function, customPrompt state, and the Button/PlayIcon imports.
Update the idle-state placeholder copy ('Select an example prompt or
type your own' -> 'Select an example prompt to begin') so it no longer
references the removed input. The 6 selectable demo prompt buttons and
their runDemo execution path are unchanged.
Change the navbar entry from the bordered 'GraphQL & AI' Emphasis (shared with the GraphQLConf entry) to a compact 'AI' pill badge so it stands out from the plain menu items while taking less space. Add a dedicated AIEmphasis component: rounded-full, pri-tinted background, bold uppercase tracking-wide text in pri-dark/pri-light. Kept separate from the shared Emphasis to avoid touching the GraphQLConf styling. Verified contrast: badge text (pri-dark #990069) over the composited pink-tinted background reads 5.90:1 (WCAG AA passes for normal text).
Reviewer feedback: the /ai hero rendered StripesDecoration unmasked, so the dark stripe overlay sat behind the centered headline, copy, and buttons across the whole hero. Other pages (not-found, blog, day/2026 hero) wrap the stripes in a container with a maskImage blur blob so the stripes concentrate in one region and fade out where text lives. Wrap the hero's StripesDecoration in a pointer-events-none absolute inset-0 container masked with the blog-page blur-bean.webp (a wide horizontal blob), maskSize: cover, maskPosition: center top, no-repeat. This fades the stripe overlay out toward the text/button region and keeps the readable pri-dark base background dominant there, while the stripes still read along the top edge. Verified via Playwright: maskImage/WebkitMaskImage are applied to the wrapper, the text region now sits on a uniform pri-dark surface (luminance ~0.076) instead of stripe-modulated variation, and white text contrast remains strong (~8.4:1).
Reported bug: the schema pane rendered 'stock: type">Int!' instead of 'stock: Int!' — the word 'type' from a span class attribute (sh-type) was leaking into the visible output as 'type">'. Root cause: highlightGraphQL and highlightGraphQLSchema ran a sequence of regex string-replacements on an already-built HTML string, so later passes matched keywords/types inside span attributes. The keyword regex \b(type|...)\b matched 'type' in class="sh-type", corrupting it into '<span class="sh-<span class="sh-keyword">type</span>">', and the same class of bug also broke triple-quoted block strings and let later passes inject spans inside string content. Rewrite all four highlighters (GraphQL, GraphQLSchema, JSON, Prompt) as single-pass tokenizers that build the HTML output while walking the escaped source left-to-right, so no pass ever mutates an injected span. Also fix a latent no-useless-escape (\[ in a char class) and the prompt highlighter (escape-before-match broke the > marker line wrapping).
The hero opens directly on the headline now — the small 'GraphQL + AI' eyebrow badge (SectionLabel) is removed along with its now-unused import. The rest of the hero (headline, copy, highlight list, CTA buttons) is unchanged.






New /ai route showcasing GraphQL for AI systems (MCP servers, RAG, agents & tool calling). Includes hero with canvas particle network, interactive Star Wars GraphQL demo executing real queries client-side, syntax-highlighted code blocks, by-the-numbers stats, and CTA.
Closes #
Description