Live notes are at https://docs.google.com/document/d/1hJO6U7daYvcNcQ3FBKnh3v4R256ers6M8IGyqRpY_kE/edit?usp=sharing","location":"https://zoom.us/j/91078840351","creator":{"email":"benjie@graphile.com"},"organizer":{"email":"linuxfoundation.org_ik79t9uuj2p32i3r203dgv5mo8@group.calendar.google.com","displayName":"GraphQL Foundation - Public","self":true},"start":"2025-12-18T12:00:00-05:00","end":"2025-12-18T13:00:00-05:00","recurringEventId":"kkc5tt01ovrjv8fki1lo31g5hj","originalStartTime":{"dateTime":"2025-12-18T12:00:00-05:00","timeZone":"Europe/Berlin"},"iCalUID":"kkc5tt01ovrjv8fki1lo31g5hj@google.com","sequence":1,"eventType":"default"}
{"kind":"calendar#event","etag":"\"3500694996844990\"","id":"2ffd8o32sh77kd3mtccrtg887n_20251218T183000Z","status":"confirmed","htmlLink":"https://www.google.com/calendar/event?eid=MmZmZDhvMzJzaDc3a2QzbXRjY3J0Zzg4N25fMjAyNTEyMThUMTgzMDAwWiBsaW51eGZvdW5kYXRpb24ub3JnX2lrNzl0OXV1ajJwMzJpM3IyMDNkZ3Y1bW84QGc","created":"2025-05-01T19:23:48.000Z","updated":"2025-06-19T15:38:18.422Z","summary":"GraphQL WG - Secondary (EU)","description":"Zoom password: graphqlwg","location":"https://zoom.us/j/593263740","creator":{"email":"benjie@graphile.com"},"organizer":{"email":"linuxfoundation.org_ik79t9uuj2p32i3r203dgv5mo8@group.calendar.google.com","displayName":"GraphQL Foundation - Public","self":true},"start":"2025-12-18T13:30:00-05:00","end":"2025-12-18T15:00:00-05:00","recurringEventId":"2ffd8o32sh77kd3mtccrtg887n","originalStartTime":{"dateTime":"2025-12-18T13:30:00-05:00","timeZone":"America/Los_Angeles"},"iCalUID":"2ffd8o32sh77kd3mtccrtg887n@google.com","sequence":0,"eventType":"default"}
+{"kind":"calendar#event","etag":"\"3517067971709790\"","id":"f7cvs5ala9jtt147l3mik2mlvl_20251222T160000Z","status":"confirmed","htmlLink":"https://www.google.com/calendar/event?eid=ZjdjdnM1YWxhOWp0dDE0N2wzbWlrMm1sdmxfMjAyNTEyMjJUMTYwMDAwWiBsaW51eGZvdW5kYXRpb24ub3JnX2lrNzl0OXV1ajJwMzJpM3IyMDNkZ3Y1bW84QGc","created":"2024-01-29T15:14:17.000Z","updated":"2025-09-22T09:39:45.854Z","summary":"Conference & Community Committee Meeting - Fortnightly Recurring","description":"\nYou have been invited to a recurring meeting for GraphQL Foundation\n\nWeekly Sync and Coordination Meeting for Conference Committee participants. Notes Document: https://docs.google.com/document/d/19-alP5jywnXzgN_1zYLBTRWh-4CaXzGakEZdTBFwNAc/edit\n\nWays to join meeting:\n\n1. Join from PC, Mac, iPad, or Android\n\nhttps://zoom-lfx.platform.linuxfoundation.org/meeting/96286151238?password=ff267735-efbd-4be4-a89c-b927b596190a\n\n2. Join via audio\n\nOne tap mobile:\nUS: +12532158782,,96286151238# or +13462487799,,96286151238\n\nOr dial:\nUS: +1 253 215 8782 or +1 346 248 7799 or +1 669 900 6833 or +1 301 715 8592 or +1 312 626 6799 or +1 646 374 8656 or 877 369 0926 (Toll Free) or 855 880 1246 (Toll Free)\nCanada: +1 647 374 4685 or +1 647 558 0588 or +1 778 907 2071 or +1 204 272 7920 or +1 438 809 7799 or +1 587 328 1099 or 855 703 8985 (Toll Free)\n\nMeeting ID: 96286151238\n\nMeeting Passcode: 986182\n\n\nInternational numbers: https://zoom.us/u/alwnPIaVT\n","location":"https://zoom-lfx.platform.linuxfoundation.org/meeting/96286151238?password=ff267735-efbd-4be4-a89c-b927b596190a","creator":{"email":"benjie@graphile.com"},"organizer":{"email":"linuxfoundation.org_ik79t9uuj2p32i3r203dgv5mo8@group.calendar.google.com","displayName":"GraphQL Foundation - Public","self":true},"start":"2025-12-22T11:00:00-05:00","end":"2025-12-22T12:00:00-05:00","recurringEventId":"f7cvs5ala9jtt147l3mik2mlvl","originalStartTime":{"dateTime":"2025-12-22T11:00:00-05:00","timeZone":"America/New_York"},"iCalUID":"f7cvs5ala9jtt147l3mik2mlvl@google.com","sequence":2,"guestsCanInviteOthers":false,"eventType":"default"}
+{"kind":"calendar#event","etag":"\"3524923598591262\"","id":"s9agipg1r702pfngano7pol2h5_20251225T170000Z","status":"confirmed","htmlLink":"https://www.google.com/calendar/event?eid=czlhZ2lwZzFyNzAycGZuZ2Fubzdwb2wyaDVfMjAyNTEyMjVUMTcwMDAwWiBsaW51eGZvdW5kYXRpb24ub3JnX2lrNzl0OXV1ajJwMzJpM3IyMDNkZ3Y1bW84QGc","created":"2024-01-12T09:56:07.000Z","updated":"2025-11-06T20:43:19.295Z","summary":"Composite schemas WG - Weekly 4","description":"The weekly "secondary" meeting of the composite schemas WG: https://github.com/graphql/composite-schemas-wg
Meeting password is "composite"
Live notes are at https://docs.google.com/document/d/1hJO6U7daYvcNcQ3FBKnh3v4R256ers6M8IGyqRpY_kE/edit?usp=sharing","location":"https://zoom.us/j/91078840351","creator":{"email":"benjie@graphile.com"},"organizer":{"email":"linuxfoundation.org_ik79t9uuj2p32i3r203dgv5mo8@group.calendar.google.com","displayName":"GraphQL Foundation - Public","self":true},"start":"2025-12-25T12:00:00-05:00","end":"2025-12-25T13:00:00-05:00","recurringEventId":"s9agipg1r702pfngano7pol2h5","originalStartTime":{"dateTime":"2025-12-25T12:00:00-05:00","timeZone":"Europe/Berlin"},"iCalUID":"s9agipg1r702pfngano7pol2h5@google.com","sequence":1,"eventType":"default"}
+{"kind":"calendar#event","etag":"\"3524923550687710\"","id":"4igp67o2j2nkso49c1d6nbv040_20251225T180000Z","status":"confirmed","htmlLink":"https://www.google.com/calendar/event?eid=NGlncDY3bzJqMm5rc280OWMxZDZuYnYwNDBfMjAyNTEyMjVUMTgwMDAwWiBsaW51eGZvdW5kYXRpb24ub3JnX2lrNzl0OXV1ajJwMzJpM3IyMDNkZ3Y1bW84QGc","created":"2025-04-15T10:29:33.000Z","updated":"2025-11-06T20:42:55.343Z","summary":"GraphQL OTel WG","description":"Zoom password: otel
)
}
diff --git a/src/components/learn-aggregator/assets/books.svg b/src/components/learn-aggregator/assets/books.svg
new file mode 100644
index 0000000000..08ba62271a
--- /dev/null
+++ b/src/components/learn-aggregator/assets/books.svg
@@ -0,0 +1,19 @@
+
diff --git a/src/components/learn-aggregator/assets/checkbox.svg b/src/components/learn-aggregator/assets/checkbox.svg
new file mode 100644
index 0000000000..432abbaee5
--- /dev/null
+++ b/src/components/learn-aggregator/assets/checkbox.svg
@@ -0,0 +1,16 @@
+
diff --git a/src/components/learn-aggregator/assets/circuit.svg b/src/components/learn-aggregator/assets/circuit.svg
new file mode 100644
index 0000000000..2324822e55
--- /dev/null
+++ b/src/components/learn-aggregator/assets/circuit.svg
@@ -0,0 +1,19 @@
+
diff --git a/src/components/learn-aggregator/assets/cog-double.svg b/src/components/learn-aggregator/assets/cog-double.svg
new file mode 100644
index 0000000000..0e8f272a77
--- /dev/null
+++ b/src/components/learn-aggregator/assets/cog-double.svg
@@ -0,0 +1,29 @@
+
diff --git a/src/components/learn-aggregator/assets/computer.svg b/src/components/learn-aggregator/assets/computer.svg
new file mode 100644
index 0000000000..2ea9a797c6
--- /dev/null
+++ b/src/components/learn-aggregator/assets/computer.svg
@@ -0,0 +1,19 @@
+
diff --git a/src/components/learn-aggregator/assets/construction.svg b/src/components/learn-aggregator/assets/construction.svg
new file mode 100644
index 0000000000..a3a332693e
--- /dev/null
+++ b/src/components/learn-aggregator/assets/construction.svg
@@ -0,0 +1,22 @@
+
diff --git a/src/components/learn-aggregator/assets/dna.svg b/src/components/learn-aggregator/assets/dna.svg
new file mode 100644
index 0000000000..bdf4234af5
--- /dev/null
+++ b/src/components/learn-aggregator/assets/dna.svg
@@ -0,0 +1,22 @@
+
diff --git a/src/components/learn-aggregator/assets/globe.svg b/src/components/learn-aggregator/assets/globe.svg
new file mode 100644
index 0000000000..731792c5a9
--- /dev/null
+++ b/src/components/learn-aggregator/assets/globe.svg
@@ -0,0 +1,25 @@
+
diff --git a/src/components/learn-aggregator/assets/hierarchy.svg b/src/components/learn-aggregator/assets/hierarchy.svg
new file mode 100644
index 0000000000..ed0bcc4767
--- /dev/null
+++ b/src/components/learn-aggregator/assets/hierarchy.svg
@@ -0,0 +1,25 @@
+
diff --git a/src/components/learn-aggregator/assets/key.svg b/src/components/learn-aggregator/assets/key.svg
new file mode 100644
index 0000000000..74eb5cb72a
--- /dev/null
+++ b/src/components/learn-aggregator/assets/key.svg
@@ -0,0 +1,22 @@
+
diff --git a/src/components/learn-aggregator/assets/layer.svg b/src/components/learn-aggregator/assets/layer.svg
new file mode 100644
index 0000000000..2730903094
--- /dev/null
+++ b/src/components/learn-aggregator/assets/layer.svg
@@ -0,0 +1,24 @@
+
diff --git a/src/components/learn-aggregator/assets/nav-left-circle.svg b/src/components/learn-aggregator/assets/nav-left-circle.svg
new file mode 100644
index 0000000000..395b0b562e
--- /dev/null
+++ b/src/components/learn-aggregator/assets/nav-left-circle.svg
@@ -0,0 +1,22 @@
+
diff --git a/src/components/learn-aggregator/assets/note.svg b/src/components/learn-aggregator/assets/note.svg
new file mode 100644
index 0000000000..90b81e393d
--- /dev/null
+++ b/src/components/learn-aggregator/assets/note.svg
@@ -0,0 +1,19 @@
+
diff --git a/src/components/learn-aggregator/assets/product-check.svg b/src/components/learn-aggregator/assets/product-check.svg
new file mode 100644
index 0000000000..b5ffbd2670
--- /dev/null
+++ b/src/components/learn-aggregator/assets/product-check.svg
@@ -0,0 +1,16 @@
+
diff --git a/src/components/learn-aggregator/assets/safe.svg b/src/components/learn-aggregator/assets/safe.svg
new file mode 100644
index 0000000000..093727d0de
--- /dev/null
+++ b/src/components/learn-aggregator/assets/safe.svg
@@ -0,0 +1,19 @@
+
diff --git a/src/components/learn-aggregator/assets/search.svg b/src/components/learn-aggregator/assets/search.svg
new file mode 100644
index 0000000000..3f824bc454
--- /dev/null
+++ b/src/components/learn-aggregator/assets/search.svg
@@ -0,0 +1,16 @@
+
diff --git a/src/components/learn-aggregator/assets/share.svg b/src/components/learn-aggregator/assets/share.svg
new file mode 100644
index 0000000000..af002cf99c
--- /dev/null
+++ b/src/components/learn-aggregator/assets/share.svg
@@ -0,0 +1,25 @@
+
diff --git a/src/components/learn-aggregator/assets/solve.svg b/src/components/learn-aggregator/assets/solve.svg
new file mode 100644
index 0000000000..0705b3eba7
--- /dev/null
+++ b/src/components/learn-aggregator/assets/solve.svg
@@ -0,0 +1,17 @@
+
diff --git a/src/components/learn-aggregator/assets/startup.svg b/src/components/learn-aggregator/assets/startup.svg
new file mode 100644
index 0000000000..2fa142a43b
--- /dev/null
+++ b/src/components/learn-aggregator/assets/startup.svg
@@ -0,0 +1,23 @@
+
diff --git a/src/components/learn-aggregator/assets/sync-square.svg b/src/components/learn-aggregator/assets/sync-square.svg
new file mode 100644
index 0000000000..d6d9b7b34b
--- /dev/null
+++ b/src/components/learn-aggregator/assets/sync-square.svg
@@ -0,0 +1,16 @@
+
diff --git a/src/components/learn-aggregator/assets/zoom-page.svg b/src/components/learn-aggregator/assets/zoom-page.svg
new file mode 100644
index 0000000000..81e62c9a4f
--- /dev/null
+++ b/src/components/learn-aggregator/assets/zoom-page.svg
@@ -0,0 +1,19 @@
+
diff --git a/src/components/learn-aggregator/common-questions.tsx b/src/components/learn-aggregator/common-questions.tsx
new file mode 100644
index 0000000000..d3013c7de9
--- /dev/null
+++ b/src/components/learn-aggregator/common-questions.tsx
@@ -0,0 +1,55 @@
+import { clsx } from "clsx"
+
+import { Eyebrow } from "@/_design-system/eyebrow"
+import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.svg?svgr"
+import { Anchor } from "@/app/conf/_design-system/anchor"
+
+export function CommonQuestionsSection(
+ props: React.HTMLAttributes,
+) {
+ return (
+
+ FAQ
+
Common questions
+
+ Find answers to the most common questions about GraphQL — from getting
+ started to advanced use cases. This also covers frontend concerns and
+ info about the official specification.
+
+ {!showingMore && (
+ showMore(true)}
+ >
+ {/* we don't display "Show less" because scroll restoriation is not worth the effort, and the user already scrolled to the next section */}
+ Show more
+
+ )}
+
+ )
+}
diff --git a/src/components/learn-aggregator/learn-blur-bean.webp b/src/components/learn-aggregator/learn-blur-bean.webp
new file mode 100644
index 0000000000..65b680af5b
Binary files /dev/null and b/src/components/learn-aggregator/learn-blur-bean.webp differ
diff --git a/src/components/learn-aggregator/learn-pages.tsx b/src/components/learn-aggregator/learn-pages.tsx
new file mode 100644
index 0000000000..36fb291e90
--- /dev/null
+++ b/src/components/learn-aggregator/learn-pages.tsx
@@ -0,0 +1,174 @@
+import meta from "../../pages/learn/_meta"
+
+type LearnPagePath = Exclude
+
+interface LearnPageItem {
+ title: string
+ description: string
+ icon: string
+ section: "getting-started" | "best-practices"
+ href: string
+}
+
+const _items: Record<
+ LearnPagePath,
+ Omit | null
+> = {
+ introduction: {
+ description:
+ "Get a high-level overview of GraphQL and how it enables flexible, versionless APIs powered by a strong type system.",
+ icon: new URL("./assets/computer.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ schema: {
+ description:
+ "Learn how GraphQL’s schema language defines the shape of your data using types.",
+ icon: new URL("./assets/hierarchy.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ queries: {
+ description:
+ "Understand how to structure GraphQL queries to request exactly the data you need — including fields, variables and fragments.",
+ icon: new URL("./assets/search.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ mutations: {
+ description:
+ "Explore how to modify data with mutations, including how to update and remove records through your schema.",
+ icon: new URL("./assets/dna.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ subscriptions: {
+ description:
+ "Discover how GraphQL supports real-time data with subscriptions and how to use them effectively at scale.",
+ icon: new URL("./assets/sync-square.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ validation: {
+ description:
+ "See how GraphQL ensures query correctness through validation rules and how common errors are detected early.",
+ icon: new URL("./assets/checkbox.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ execution: {
+ description:
+ "Learn how resolvers power GraphQL execution and how the server processes and returns data for each query.",
+ icon: new URL("./assets/cog-double.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ response: {
+ description:
+ "Explore how GraphQL structures its responses, including data, errors and extensions for custom metadata.",
+ icon: new URL("./assets/nav-left-circle.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ introspection: {
+ description:
+ "Use introspection to explore the schema itself — a powerful way to inspect types and fields dynamically.",
+ icon: new URL("./assets/zoom-page.svg", import.meta.url).href,
+ section: "getting-started",
+ },
+ // ---
+ "best-practices": null,
+ "thinking-in-graphs": {
+ description:
+ "Learn how to shift your mindset from RESTful endpoints to graph-based thinking, aligning your schema with business logic and legacy systems.",
+ icon: new URL("./assets/share.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ "serving-over-http": {
+ description:
+ "Explore how GraphQL operates over HTTP, including methods, headers, status codes and API endpoint design.",
+ icon: new URL("./assets/globe.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ "file-uploads": {
+ description:
+ "Handle file uploads in GraphQL by wrapping them as mutations. Learn the recommended approach for integrating file handling into your API.",
+ icon: new URL("./assets/note.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ authorization: {
+ description:
+ "Understand how to secure your GraphQL APIs with type- and field-level authorization patterns.",
+ icon: new URL("./assets/key.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ pagination: {
+ description:
+ "Discover different pagination strategies in GraphQL, from simple slicing to fully connected edges and nodes.",
+ icon: new URL("./assets/layer.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ "schema-design": {
+ description:
+ "Learn how to design clear, adaptable schemas — including versioning and thoughtful use of nullability.",
+ icon: new URL("./assets/solve.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ "global-object-identification": {
+ description:
+ "Use globally unique IDs and the Node interface to enable caching, refetching, and efficient schema traversal.",
+ icon: new URL("./assets/product-check.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ caching: {
+ description:
+ "Explore caching techniques and ID strategies that make client-side performance and object reuse more effective.",
+ icon: new URL("./assets/books.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ performance: {
+ description:
+ "Get practical tips for improving GraphQL performance — from preventing N+1 problems to monitoring and compression.",
+ icon: new URL("./assets/startup.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ security: {
+ description:
+ "Protect your GraphQL API with best practices for query limits, input validation, introspection control and more.",
+ icon: new URL("./assets/safe.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ federation: {
+ description:
+ "Learn how GraphQL federation enables modular, scalable APIs by composing services into a unified schema.",
+ icon: new URL("./assets/circuit.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+ "debug-errors": {
+ description:
+ "Learn about common 'graphql-http' errors and how to debug them.",
+ icon: new URL("./assets/construction.svg", import.meta.url).href,
+ section: "best-practices",
+ },
+}
+
+const learnPages = _items as Record
+
+const pagesBySection: Record = {
+ "getting-started": [],
+ "best-practices": [],
+}
+
+for (const path in learnPages) {
+ const page = learnPages[path as LearnPagePath]
+ if (page === null) continue
+ const metaEntry = meta[path as keyof typeof meta]
+
+ if (typeof metaEntry === "string") {
+ page.title =
+ metaEntry ||
+ path.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase())
+ } else if (typeof metaEntry === "object" && "title" in metaEntry) {
+ page.title = metaEntry.title
+ } else {
+ page.title = path.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase())
+ }
+
+ page.href = `/learn/${path}`
+
+ pagesBySection[page.section].push(page)
+}
+
+export { learnPages, pagesBySection }
diff --git a/src/components/learn-aggregator/looking-for-more.tsx b/src/components/learn-aggregator/looking-for-more.tsx
new file mode 100644
index 0000000000..95c719ad66
--- /dev/null
+++ b/src/components/learn-aggregator/looking-for-more.tsx
@@ -0,0 +1,37 @@
+import { clsx } from "clsx"
+import ArrowDownIcon from "@/app/conf/_design-system/pixelarticons/arrow-down.svg?svgr"
+
+export function LookingForMore(props: React.HTMLAttributes) {
+ return (
+
+
+
+
Looking for more?
+
+ Learning is just the beginning. Discover tools and other resources —
+ or connect with the GraphQL community around the world.
+
Learn about GraphQL, how it works, and how to use it
-
-GraphQL is a query language for your API, and a server-side runtime for executing queries using a type system you define for your data. The [GraphQL specification](https://spec.graphql.org/) was open-sourced in 2015 and has since been implemented in a variety of programming languages. GraphQL isn't tied to any specific database or storage engine—it is backed by your existing code and data.
-
-If you're already familiar with GraphQL and would like to read documentation on how to build a GraphQL service, then there are libraries to help you implement GraphQL in [many different languages](/community/tools-and-libraries/?tags=server). There are also many libraries available that allow [client applications to query existing GraphQL APIs](/community/tools-and-libraries/?tags=client).
-
-## Describe your API with a type system
-
-A GraphQL service is created by [defining types and their fields](/learn/schema/), and then writing a function for each field to [provide the required data](/learn/execution/). For example, a GraphQL service that tells you the name of a logged-in user might look like this:
-
-```graphql
-type Query {
- me: User
-}
-
-type User {
- name: String
-}
-```
-
-Along with functions for each field on each type:
-
-```js
-// Resolver for the `me` field on the `Query` type
-function resolveQueryMe(_parent, _args, context, _info) {
- return context.request.auth.user;
-}
-
-// Resolver for the `name` field on the `User` type
-function resolveUserName(user, _args, context, _info) {
- return context.db.getUserFullName(user.id);
-}
-```
-
-In the example above, the function that provides data for the `me` field on the `Query` type uses information about the authenticated user who made the request, while the `name` field on the `User` type is populated by using that user's ID to fetch their full name from a database.
-
-## Query exactly what you need
-
-After a GraphQL service is running (typically at a URL on a web service), it can receive [GraphQL queries](/learn/queries/) to validate and execute from clients. The service first checks a query to ensure it only refers to the types and fields defined for the API and then runs the provided functions to produce a result.
-
-For example, the query:
-
-```graphql
-{
- me {
- name
+---
+title: Learn
+---
+
+import { Button } from '@/app/conf/_design-system/button';
+
+import { NavbarFixed } from '../../components/navbar/navbar-fixed'
+import { TocHero, TocHeroContents } from '../../components/toc-hero';
+import { TeaserSection, LearnHeroStripes } from '../../components/learn-aggregator'
+import { pagesBySection } from '../../components/learn-aggregator/learn-pages'
+import { CommonQuestionsSection } from '../../components/learn-aggregator/common-questions'
+import { TrainingCoursesSection } from '../../components/learn-aggregator/training-courses'
+import { LookingForMore } from "../../components/learn-aggregator/looking-for-more"
+
+
+
+ Get hands-on with the fundamentals of GraphQL. Start with the basics and see how it compares to other technologies.
+ {" "}
+ Then move on to best practices for designing better APIs.
+ >
}
-}
-```
-
-Could produce the following JSON result:
-
-```json
-{
- "data": {
- "me": {
- "name": "Luke Skywalker"
- }
+ decoration={}
+>
+
+ Start with the basics
+
+
+
+
+
+ Start learning
+
}
-}
-```
-
-With even a simple query, we can see some of the key features that make GraphQL so powerful. The client can make queries to the API that mirror the structure of the data that they need and then receive just that data in the expected shape with a single request—and without having to worry about which underlying data sources provided it.
-
-## Evolve your API without versioning
-
-Client requirements change over time and GraphQL allows your API to evolve in response to those needs and without the overhead of managing different API versions. For example, if a new feature calls for more specific name values to be available, then the `User` type could be updated as follows:
-
-```graphql
-type User {
- fullName: String
- nickname: String
- name: String @deprecated(reason: "Use `fullName`.")
-}
-```
-
-Client tooling will encourage developers to use the new fields and remove usage of the deprecated `name` field. The field can be removed once it is determined it is no longer used; in the meantime GraphQL will continue to provide its data as expected.
-
-## Try it out!
-
-The best way to learn GraphQL is to start writing queries. The query editors used throughout this guide are **interactive**, so try adding an `id` and `appearsIn` fields to the `hero` object to see an updated result:
-
-```graphql
-# { "graphiql": true }
-{
- hero {
- name
- # add additional fields here!
+ firstIconsEager
+ items={pagesBySection["getting-started"]}
+/>
+
+
+ Explore all best practices
+
}
-}
-```
-
-
-The examples in this guide are based on [a modified version of the SWAPI GraphQL schema](https://github.com/graphql/graphql.github.io/blob/source/src/components/interactive-code-block/swapi-schema.tsx). Because these queries are designed for illustrative purposes, they will not run on the full version of the SWAPI GraphQL API due to differences between the two schemas. [You can try the full version of the API here.](https://graphql.org/swapi-graphql/)
-
+ items={pagesBySection["best-practices"]}
+/>
-## Next steps
+
-Now that you know some key GraphQL concepts, you're ready to learn about all of the different aspects of its [type system](/learn/schema/).
+
-For an in-depth learning experience with practical tutorials, see [the available training courses](/community/resources/training-courses).
+
diff --git a/src/pages/learn/introduction.mdx b/src/pages/learn/introduction.mdx
new file mode 100644
index 0000000000..2a2003033c
--- /dev/null
+++ b/src/pages/learn/introduction.mdx
@@ -0,0 +1,105 @@
+import { Callout } from "nextra/components"
+
+# Introduction to GraphQL
+
+
Learn about GraphQL, how it works, and how to use it
+
+GraphQL is a query language for your API, and a server-side runtime for executing queries using a type system you define for your data. The [GraphQL specification](https://spec.graphql.org/) was open-sourced in 2015 and has since been implemented in a variety of programming languages. GraphQL isn't tied to any specific database or storage engine—it is backed by your existing code and data.
+
+If you're already familiar with GraphQL and would like to read documentation on how to build a GraphQL service, then there are libraries to help you implement GraphQL in [many different languages](/community/tools-and-libraries/?tags=server). There are also many libraries available that allow [client applications to query existing GraphQL APIs](/community/tools-and-libraries/?tags=client).
+
+## Describe your API with a type system
+
+A GraphQL service is created by [defining types and their fields](/learn/schema/), and then writing a function for each field to [provide the required data](/learn/execution/). For example, a GraphQL service that tells you the name of a logged-in user might look like this:
+
+```graphql
+type Query {
+ me: User
+}
+
+type User {
+ name: String
+}
+```
+
+Along with functions for each field on each type:
+
+```js
+// Resolver for the `me` field on the `Query` type
+function resolveQueryMe(_parent, _args, context, _info) {
+ return context.request.auth.user;
+}
+
+// Resolver for the `name` field on the `User` type
+function resolveUserName(user, _args, context, _info) {
+ return context.db.getUserFullName(user.id);
+}
+```
+
+In the example above, the function that provides data for the `me` field on the `Query` type uses information about the authenticated user who made the request, while the `name` field on the `User` type is populated by using that user's ID to fetch their full name from a database.
+
+## Query exactly what you need
+
+After a GraphQL service is running (typically at a URL on a web service), it can receive [GraphQL queries](/learn/queries/) to validate and execute from clients. The service first checks a query to ensure it only refers to the types and fields defined for the API and then runs the provided functions to produce a result.
+
+For example, the query:
+
+```graphql
+{
+ me {
+ name
+ }
+}
+```
+
+Could produce the following JSON result:
+
+```json
+{
+ "data": {
+ "me": {
+ "name": "Luke Skywalker"
+ }
+ }
+}
+```
+
+With even a simple query, we can see some of the key features that make GraphQL so powerful. The client can make queries to the API that mirror the structure of the data that they need and then receive just that data in the expected shape with a single request—and without having to worry about which underlying data sources provided it.
+
+## Evolve your API without versioning
+
+Client requirements change over time and GraphQL allows your API to evolve in response to those needs and without the overhead of managing different API versions. For example, if a new feature calls for more specific name values to be available, then the `User` type could be updated as follows:
+
+```graphql
+type User {
+ fullName: String
+ nickname: String
+ name: String @deprecated(reason: "Use `fullName`.")
+}
+```
+
+Client tooling will encourage developers to use the new fields and remove usage of the deprecated `name` field. The field can be removed once it is determined it is no longer used; in the meantime GraphQL will continue to provide its data as expected.
+
+## Try it out!
+
+The best way to learn GraphQL is to start writing queries. The query editors used throughout this guide are **interactive**, so try adding an `id` and `appearsIn` fields to the `hero` object to see an updated result:
+
+```graphql
+# { "graphiql": true }
+{
+ hero {
+ name
+ # add additional fields here!
+ }
+}
+```
+
+
+The examples in this guide are based on [a modified version of the SWAPI GraphQL schema](https://github.com/graphql/graphql.github.io/blob/source/src/components/interactive-code-block/swapi-schema.tsx). Because these queries are designed for illustrative purposes, they will not run on the full version of the SWAPI GraphQL API due to differences between the two schemas. [You can try the full version of the API here.](https://graphql.org/swapi-graphql/)
+
+
+## Next steps
+
+Now that you know some key GraphQL concepts, you're ready to learn about all of the different aspects of its [type system](/learn/schema/).
+
+For an in-depth learning experience with practical tutorials, see [the available training courses](/community/resources/training-courses).
diff --git a/test/e2e/graphql-interactive.spec.ts b/test/e2e/graphql-interactive.spec.ts
index fe6c26a16b..ed5a503d83 100644
--- a/test/e2e/graphql-interactive.spec.ts
+++ b/test/e2e/graphql-interactive.spec.ts
@@ -65,7 +65,7 @@ test.describe("Learn", () => {
test("adds appearsIn field to hero query and gets correct response", async ({
page,
}) => {
- await page.goto("/learn")
+ await page.goto("/learn/introduction")
await page.waitForSelector(".cm-editor", { timeout: 10000 })
const heroEditor = await findEditorByContent(page, "hero")
diff --git a/vercel.json b/vercel.json
index ebc5d887e0..244e7c6f2c 100644
--- a/vercel.json
+++ b/vercel.json
@@ -602,7 +602,7 @@
},
{
"source": "/docs",
- "destination": "/learn",
+ "destination": "/learn/introduction/",
"permanent": true
},
{