diff --git a/package.json b/package.json
index b89ca0f75d..1da4947359 100644
--- a/package.json
+++ b/package.json
@@ -17,8 +17,10 @@
"postbuild": "next-sitemap",
"prebuild": "tsx src/get-github-info.ts",
"serve": "pnpx serve out",
- "test": "playwright test",
+ "test": "playwright test && pnpm test:unit",
+ "test:e2e": "playwright test",
"test:ui": "playwright test --ui",
+ "test:unit": "node --import=tsx --test 'src/**/*.test.tsx'",
"validate:snippets": "node scripts/validate-snippets.js"
},
"dependencies": {
diff --git a/scripts/sync-sched/schedule-2025.json b/scripts/sync-sched/schedule-2025.json
index 6fc636e055..5fe42530b1 100644
--- a/scripts/sync-sched/schedule-2025.json
+++ b/scripts/sync-sched/schedule-2025.json
@@ -8,7 +8,7 @@
"event_end": "2025-09-07 17:00",
"event_type": "Breaks / Networking / Special Events",
"description": "GraphQLConf Canal Cruise - Separate Registration Required\n\nJoin us on Sunday 7 September for this pre GraphQLConf'25 event, a must-do activity in Amsterdam; a wonderful canal cruise in the historical city centre of Amsterdam.\n\nInitiative by the local Amsterdam GraphQL Meetup group.\n\nA great opportunity to meet your peer-attendees of the GraphQLConf'25 during this great sight-seeing activity.\n\nPlease RSVP by Wednesday September 3rd!\n\nLocation: in the city centre (tba exact location)\nDuration of the canal cruise: 16:00-17:00 on Sunday 7 September\nPlease be 15:45 at the location (to buy the ticket etc).\n\nCost per person: 10-15 euro* (depending on the number of attendees)\n*not included in the conference ticket",
- "goers": "0",
+ "goers": "1",
"seats": "0",
"invite_only": "N",
"id": "04a893e9dfa070fae1dfa767608ad0c0",
@@ -113,7 +113,7 @@
"event_start": "2025-09-08 09:00",
"event_end": "2025-09-08 09:05",
"event_type": "Keynote Sessions",
- "goers": "6",
+ "goers": "8",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -159,7 +159,7 @@
"event_start": "2025-09-08 09:05",
"event_end": "2025-09-08 09:15",
"event_type": "Keynote Sessions",
- "goers": "7",
+ "goers": "8",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -206,7 +206,7 @@
"event_end": "2025-09-08 09:30",
"event_type": "Keynote Sessions",
"description": "Even ten years in, GraphQL continues to evolve—not just in code, but in connection. This year the Foundation has doubled down on transparency, support, and shared leadership: board minutes are now public, Subject Matter Experts have helped shape the conference agenda, and we'll be launching a new program live on stage! There are also updates on our existing initiatives including community grants and GraphQL Locals.\n\nThis talk is a thank you to the people behind the progress and a celebration of our growing constellation of contributors. It's also an invitation to step forward and get involved—one of the best ways to do that is by joining our new Community Working Group, giving passionate community members a voice in shaping the Foundation's directions and initiatives for the next ten years of GraphQL.",
- "goers": "7",
+ "goers": "8",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -266,7 +266,7 @@
"event_end": "2025-09-08 09:45",
"event_type": "Keynote Sessions",
"description": "Meet the new developer journey: Ask AI → Generate code → Iterate → Ship. This fundamental shift in how developers work demands we rethink every touchpoint of our GraphQL APIs. This talk focuses on the developer experience layer—how to design schemas that are self-explanatory, structure documentation so AI gives accurate answers about your API, and build tools that feel like pair programming with a senior engineer.",
- "goers": "5",
+ "goers": "6",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -311,7 +311,7 @@
"event_end": "2025-09-08 10:00",
"event_type": "Keynote Sessions",
"description": "A peek behind the curtain revealing how GraphQL is used at Meta. We will explore how everything from culture, development process, client and server implementations, schema patterns and conventions, advanced tooling and more work together to allow GraphQL to enable great user and developer experiences at Meta.",
- "goers": "6",
+ "goers": "7",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -357,7 +357,7 @@
"event_end": "2025-09-08 10:15",
"event_type": "Keynote Sessions",
"description": "As developers build with AI agents, we face a challenge: how do we provide these agents with reliable, flexible access to our distributed data? GraphQL's graph-based approach makes it the ideal language for AI. Join Matt DeBergalis, CEO and Co-founder of Apollo GraphQL, to explore how \"thinking in graphs\" fundamentally transforms API orchestration from procedural code to declarative queries – creating the composable data layer that AI-driven applications require.",
- "goers": "6",
+ "goers": "7",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -402,7 +402,7 @@
"event_start": "2025-09-08 10:15",
"event_end": "2025-09-08 10:20",
"event_type": "Keynote Sessions",
- "goers": "6",
+ "goers": "7",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -567,7 +567,7 @@
"event_end": "2025-09-08 11:15",
"event_type": "GraphQL in Production",
"description": "At Booking.com, we’re applying AI to uncover data blind spots in our GraphQL schema, specifically gaps between what’s exposed today and what still lives in our legacy Perl systems. As we continue modernizing our frontend architecture, one major challenge is identifying what data is already available, what’s duplicated, and what’s missing entirely from the graph. Using AI, we’ve begun introspecting legacy domains to map their data structures against the schema, surface PII fields for tagging and tracking, and inform where schema design can be improved. In this talk, we’ll share how we’re using AI to support schema modernization at scale, streamline developer experience, and bring more consistency to a graph that continues to grow and change across teams.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -675,12 +675,12 @@
"event_key": "925253",
"active": "Y",
"pinned": "N",
- "name": "Offset Pagination Is Dead! Meet Relative Cursors - Michael Staib, ChilliCream",
+ "name": "Lightning Talk: Offset Pagination Is Dead! Meet Relative Cursors - Michael Staib, ChilliCream",
"event_start": "2025-09-08 11:25",
"event_end": "2025-09-08 11:35",
"event_type": "Developer Experience",
"description": "What if you could keep traditional UI pagination concepts, but with the performance and reliability of cursor-based pagination? In this lightning talk, you’ll learn how relative cursors enable fast, consistent pagination while preserving familiar UX patterns like “jump to page.” It’s a smarter, more robust approach to navigating data—ideal for modern APIs and real-world apps.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -726,7 +726,7 @@
"event_end": "2025-09-08 11:55",
"event_type": "GraphQL in Production",
"description": "APIs give AI superpowers. The MCP protocol, introduced less than a year ago, has quickly become a popular method for connecting large language models (LLMs) with the outside world. But where does GraphQL fit in? It's structured, typed, and introspectable... so what's the catch?\n\nJoin our panel of experts as we delve into how to leverage GraphQL effectively and safely in AI applications. We'll discuss the trade-offs, potential pitfalls, and share insights into best practices and strategies. This interactive discussion will explore how combining GraphQL with MCP can unlock new superpowers for AI, offering attendees a chance to engage with thought leaders and gain valuable perspectives.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -801,7 +801,7 @@
"event_end": "2025-09-08 11:55",
"event_type": "GraphQL in Production",
"description": "After maintaining GraphQL Java for 10 years we learned what aspects of GraphQL are critical for optimal performance. \n \nWe we look at what users of GraphQL should consider and which aspects of the spec are critical for optimal performance.\n \nWe will look also closer into the aspects of operating GraphQL at scale including and what it means when the schema and requests continue to grow.",
- "goers": "3",
+ "goers": "4",
"seats": "0",
"invite_only": "N",
"venue": "Studio - 5th Floor",
@@ -842,12 +842,12 @@
"event_key": "925279",
"active": "Y",
"pinned": "N",
- "name": "See the Graph in GraphQL: Graph Visualization in Action - Ivan Goncharov, KeenEthics",
+ "name": "Lightning Talk: See the Graph in GraphQL: Graph Visualization in Action - Ivan Goncharov, KeenEthics",
"event_start": "2025-09-08 11:45",
"event_end": "2025-09-08 11:55",
"event_type": "Developer Experience",
"description": "Despite having \"Graph\" in its name, GraphQL schemas are rarely visualized as actual graphs.\n\nThis lightning talk explores the untapped potential of graph visualization for GraphQL schemas based on lessons learned while working on graphql-voyager.\n\nWe'll explore the theory behind effective schema visualization, share key insights from my 9 years of experience in this field, and discuss current challenges in representing complex schemas.\n\nI'll also present experimental approaches that go beyond existing libraries, pushing the boundaries of how we understand and interact with GraphQL schemas.\n\nJoin me for a visual journey that reveals what makes the \"Graph\" in GraphQL truly powerful, potentially reshaping how we design and understand our APIs.",
- "goers": "3",
+ "goers": "4",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -893,7 +893,7 @@
"event_end": "2025-09-08 12:35",
"event_type": "GraphQL in Production",
"description": "Abstract\nDiscover how we transformed Jira's issue view to GraphQL and Relay—handling billions of monthly interactions across 100+ field types while meeting enterprise compliance and reliability agreements. With hundreds of developers and teams modifying a decade-old codebase daily in a frontend monorepo, we faced unique challenges in technical design and execution.\nWe'll share:\n- GraphQL schema design for scale\n- Bridging Redux, Sweet State, and Relay in a multi-team environment\n- Incremental rollout strategies with feature flags for safe migration\n- Field-by-field adoption approaches maintaining workflow and compliance\n- Performance optimization under enterprise-scale load\n- Testing approaches at scale\n- Developer experience takeaways\n\nImpact & Takeaways\n- Performance metrics during incremental migration\n- Developer experience improvements\n- Cross-team collaboration\n- Production-proven strategies for state management in existing codebase\n\nThis isn't about building new—it's about modernizing Jira's critical interface while maintaining compliance for enterprise customers. Ideal for leaders coordinating teams and architects planning GraphQL adoption in regulated organizations.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -946,7 +946,7 @@
"event_end": "2025-09-08 12:35",
"event_type": "GraphQL in Production",
"description": "@defer allows you to specify which parts of your operation are urgent, and which can be delayed. However, there is still a contract with @defer: all your data will always be returned, at some later point.\n\nThis poses a problem for certain classes of product: if only 10% of your operation will ever be on consumed, but you don't know exactly which 10% that will be, defer can introduce substantial hidden costs. To improve performance and reduce compute costs, Meta created @async to ensure products only ask for data when it's needed.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "Studio - 5th Floor",
@@ -1219,7 +1219,7 @@
"event_end": "2025-09-08 14:55",
"event_type": "Developer Experience",
"description": "GraphQL federation has changed how we think about data and it's time to adopt that thinking to how we build UIs and component systems. In this talk, Gabe will share his deep experience from building design systems at Apple, Netflix and now StubHub to help you design yours.\n \nWhat are the advantages GraphQL brings to a traditional React component system? How can fragments optimize the composability of your components? How to reduce duplication while reducing the time you need to ship new features?\n \nWe will provide guidance on how to build and leverage a federated component system along-side your design system. \n \nFinally, we will cover how we've leveraged AI to speedup the creation of our design system and federated components at StuHub. Join to learn more!",
- "goers": "4",
+ "goers": "5",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -1410,7 +1410,7 @@
"event_end": "2025-09-08 15:35",
"event_type": "GraphQL in Production",
"description": "The Member Experience Core Systems team at Netflix is entrusted with orchestrating every facet of the member experience. From the intricacies of the profiles screen to the dynamic homepage and the seamless search for your favorite shows, our robust API layer is the backbone that supports it all.\n\nOperating at an astronomical scale, our two principal Subgraph Services collectively manage over a million GraphQL queries per second. This immense scale, coupled with the diverse queries our systems accommodate, ensures that even the most minute edge cases are brought to light.\n\nIn this presentation, we will delve into two significant production bugs that emerged at scale. The first involved a federation-based solution at the query planning layer, which culminated in a 20% reduction in requests per second and yielded substantial cost savings amounting to hundreds of thousands of dollars. The second, a subgraph service specific enhancement, remarkably doubled the efficiency of our entire fleet.\n\nBy sharing our journey of identifying and resolving these issues, we aspire to provide insights that will directly enhance your day-to-day endeavors using GraphQL.",
- "goers": "3",
+ "goers": "4",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -1538,7 +1538,7 @@
"event_end": "2025-09-08 16:25",
"event_type": "Developer Experience",
"description": "Over the past few years, GraphQL has fallen out of favor for developers looking to build full-stack typescript applications. With projects like TRPC and NextJS, many people have started to pigeonhole GraphQL into an enterprise-shaped box. But this doesn't have to be the case! In this talk, Alec will give a practical introduction with live coding to Houdini, a GraphQL-first application framework and demonstrate how to rapidly move from idea to creation with a state-of-the-art developer experience that brings GraphQL back as a contender for the best choice for smaller applications.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "Studio - 5th Floor",
@@ -1579,12 +1579,12 @@
"event_key": "924335",
"active": "Y",
"pinned": "N",
- "name": "The Federated GraphQL Subscriptions Zoo - Tom Houlé, Grafbase",
+ "name": "Lightning Talk: The Federated GraphQL Subscriptions Zoo - Tom Houlé, Grafbase",
"event_start": "2025-09-08 15:55",
"event_end": "2025-09-08 16:05",
"event_type": "GraphQL in Production",
- "description": "Subscriptions are not like queries and mutations. They require specific thinking and care in any implementation strategy.\nFederation adds a layer of infrastructure that can complicate subscriptions in two ways:\n \n- scaling, because the federation gateway may have to resolve many subscription streams at the same time,\n- translation, because each subgraph has the protocols it supports, and they may not overlap with the protocol used by the clients.\n \nThis lightning talk dives into the challenges of translation we encountered in concrete scenarios:\n \n- How websocket init payloads map, or not, to http headers\n- How to translate SSE requests to websocket requests\n- Alternatives like multipart streams\n- Websocket subprotocols",
- "goers": "0",
+ "description": "Subscriptions are not like queries and mutations. They require specific thinking and care in any implementation strategy.\nFederation adds a layer of infrastructure that can complicate subscriptions in two ways:\n\n- scaling, because the federation gateway may have to resolve many subscription streams at the same time,\n- translation, because each subgraph has the protocols it supports, and they may not overlap with the protocol used by the clients.\n\nThis lightning talk dives into the challenges of translation we encountered in concrete scenarios:\n\n- How websocket init payloads map, or not, to http headers\n- How to translate SSE requests to websocket requests\n- Alternatives like multipart streams\n- Websocket subprotocols",
+ "goers": "1",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -1671,12 +1671,12 @@
"event_key": "924336",
"active": "Y",
"pinned": "N",
- "name": "Authorization in Federated GraphQL - Tom Houlé, Grafbase",
+ "name": "Lightning Talk: Authorization in Federated GraphQL - Tom Houlé, Grafbase",
"event_start": "2025-09-08 16:15",
"event_end": "2025-09-08 16:25",
"event_type": "GraphQL in Production",
- "description": "Adopting GraphQL federation creates a convenient place in your infrastructure to make authorization decisions:\n \n- It comes early in the request lifecycle, before any subgraph.\n- It has access to the whole client request, as well as the entirety of the federated graph.\n- Authorization can still be the responsibility of the subgraph teams, or a cross cutting concern.\n \nThis talk is about leveraging the special position of the federation gateway for authorization.\n \nWe'll cover the directives federation offers for authorization out of the box: `@authenticated`, `@requiresScopes`, `@policy`. To cover a more advanced use case, we'll explore how to implement fine-grained authorization taking advantage of data from your federated graph by leveraging extensions in the open source Grafbase Gateway.",
- "goers": "0",
+ "description": "Adopting GraphQL federation creates a convenient place in your infrastructure to make authorization decisions:\n\n- It comes early in the request lifecycle, before any subgraph.\n- It has access to the whole client request, as well as the entirety of the federated graph.\n- Authorization can still be the responsibility of the subgraph teams, or a cross cutting concern.\n\nThis talk is about leveraging the special position of the federation gateway for authorization.\n\nWe'll cover the directives federation offers for authorization out of the box: `@authenticated`, `@requiresScopes`, `@policy`. To cover a more advanced use case, we'll explore how to implement fine-grained authorization taking advantage of data from your federated graph by leveraging extensions in the open source Grafbase Gateway.",
+ "goers": "1",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -1763,11 +1763,11 @@
"event_key": "925144",
"active": "Y",
"pinned": "N",
- "name": "Building an Open-Source Query Planner - Dotan Simha & Kamil Kisiela, The Guild",
+ "name": "Building an Open-Source Federation Query Planner & Router - Dotan Simha & Kamil Kisiela, The Guild",
"event_start": "2025-09-08 16:35",
"event_end": "2025-09-08 17:05",
"event_type": "GraphQL in Production",
- "description": "A talk covering the journey of The Guild building a query planner for the future. We are going to share our journey learnings, insights and real-life examples on how we built our open-source Federation query planner.\n\nIn this talk, we’ll cover:\n\n- The background and journey The Guild did (from composition to query planning)\n- An overview of our query planner architecture\n- Audit-based development\n- Why we build our query planner as a library\n- Next steps and the community can get involved",
+ "description": "A talk covering the journey of The Guild building our new Rust router and query planner.\n\nWe are going to share our years-long journey through learnings, insights and real-life examples on why and how we’ve built our open-source Federation Router and query planner.\n\nIn this talk, we’ll cover:
- The background and journey of the ecosystem’s different gateways and routers
- Benchmarks and Audit-based development
- Why we build our query planner as a library
- How we got it to be so performant
- Next steps and the community can get involved
",
"goers": "3",
"seats": "0",
"invite_only": "N",
@@ -1821,7 +1821,7 @@
"event_end": "2025-09-08 17:05",
"event_type": "GraphQL in Production",
"description": "alt title: Surviving Change Without Breaking Everything\n \nWhen we launched our new GraphQL API at Netflix, it felt perfect—destined to power hundreds of millions of devices. Yet, change is inevitable. Even if your schema seems flawless today (which it isn't), requirements will shift, new features will emerge, and regrets will follow.\n \nGraphQL promises evolvability, allowing us to move forward without multiple API versions. But how does this hold up in practice? We mark fields as @deprecated, but what happens next? How can we embrace experimentation without entombing technical debt in the API? Does federation complicate things? Evolving your schema without breaking clients is easy, right? Right??\n \nDrawing from experience with the Netflix API, this talk explores techniques for evolving your schema safely and painlessly. We'll cover the schema lifecycle—from experimentation to design, deprecation, and deletion.\n \nAttendees will leave with:\n- Schema design principles that facilitate change\n- Practical techniques for evolving GraphQL schemas\n- Strategies for managing a deprecation workflow\n \nJoin us as we learn to face the inevitability of change with confidence and serenity.",
- "goers": "5",
+ "goers": "7",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -1867,7 +1867,7 @@
"event_end": "2025-09-08 17:45",
"event_type": "GraphQL in Production",
"description": "Over the past six years, Viaduct has grown from Airbnb’s unified data access layer into a central platform for hosting business logic — now supporting over 1 million lines of code, 500+ monthly contributors, and 100+ teams.\n\nThat scale has brought a familiar risk: the slow creep toward monolith. Viaduct was never meant to be a microservices system, but we’ve had to make deliberate choices to preserve team autonomy, performance, and codebase sanity.\n\nThis talk shares the strategies we’re using — and actively evolving — to make that possible, including:\n\n* Tenant modules that define slices of the GraphQL schema alongside their implementation logic;\n* Relying on GraphQL fragments instead of service calls for inter-module communication;\n* Building ownership and attribution into the platform so teams can trace metrics and errors back to themselves.\n\nWe haven’t fully solved these challenges — but we’ve learned a lot about what works, what breaks, and what to watch for.",
- "goers": "4",
+ "goers": "6",
"seats": "0",
"invite_only": "N",
"venue": "Studio - 5th Floor",
@@ -2113,7 +2113,7 @@
"event_end": "2025-09-09 10:30",
"event_type": "Breaks / Networking / Special Events",
"description": "Help shape the future of GraphQL! Join GraphQL Foundation Board Members, TSC Members, and other community leaders for a public meeting about goals and priorities for 2026, and help us celebrate 2025's wins.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -2231,7 +2231,7 @@
"event_end": "2025-09-09 10:30",
"event_type": "Workshops",
"description": "This workshop proposes the development of a demo social media application, \"Y,\" using GraphQL, Relay, and React Server Components (RSC). The goal is to showcase the powerful synergy between Relay’s declarative data fetching and RSC’s server-side rendering, creating an ideal stack for scalable, performant web applications. \n \nThe demo will highlight: \n \n- Co-location of GraphQL fragments with React components for a modular, maintainable codebase. \n- Relay’s type-safe queries to efficiently fetch data for posts, comments, and user profiles. \n- React Server Components to optimize server-side rendering and enable React streaming for progressive UI rendering. \n- A fully functional social media app with interactive, real-time features. \n \nThrough this hands-on demo, we’ll illustrate how Relay’s fragment-based architecture and RSC’s streaming capabilities allow developers to build responsive, data-driven applications. This workshop will demonstrate the potential of these technologies for modern frontend development providing a compelling case for adopting this stack in production projects.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "Studio - 5th Floor",
@@ -2396,7 +2396,7 @@
"event_end": "2025-09-09 12:15",
"event_type": "Workshops",
"description": "In this workshop, we will look at different patterns to integrate various data sources in a federated graph using the Apollo Federation V2 spec, the Composite Schemas spec, WebAssembly with the recently released Component Model, and the Grafbase Gateway.\n\nGraphQL Federation is a fantastic pattern to combine APIs — called subgraphs — into a single schema while sharing types and declaratively depending from data from other subgraphs. In fact, it is too good to keep it to GraphQL subgraphs only — what if you could bring other kinds of APIs and data sources into your federated graph without having to write a dedicated GraphQL server in front of them?\n\nIn the course of the hands-on workshop, we will:- Integrate a REST API, a Postgres database and a Kafka instance using open source extensions,
- Use the gRPC extension and the MCP server to understand, integrate and query gRPC services over GraphQL,
- Build a new custom extension together
\nThe result will be a functioning GraphQL federated graph without GraphQL subgraphs, demonstrating that federation as a mechanism is useful beyond just GraphQL subgraphs.",
- "goers": "0",
+ "goers": "1",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -2449,7 +2449,7 @@
"event_end": "2025-09-09 12:15",
"event_type": "GraphQL Working Group",
"description": "The GraphQL community has come together to standardize how people can build distributed systems with GraphQL as an orchestrator. In this talk I will explain the general idea that we have for GraphQL as an Orchestrator in this space and how the new specification is tackling this. We will look at the progress we have made since last GraphQL Conf in the GraphQL composite schema working group and also get some sneak peaks at our early RFCs and prototypes. I will outline how this new specification is taking the best ideas of existing solutions in the market to make the next big leap towards mainstream adoption. This will allow anyone to build tooling by implementing the spec or parts of the spec that seamlessly integrate with other vendors.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -2536,7 +2536,7 @@
"event_end": "2025-09-09 14:55",
"event_type": "GraphQL Working Group",
"description": "Learn how to lower latency in your applications by streaming your GraphQL responses using the @defer and @stream directives. Learn the trade-offs of when to use these new directives and how they differ from GraphQL Subscriptions.\n\n@defer and @stream have been in development for some time now and have gone through many iterations. Learn about the motivation behind these changes and how they will lead to scalable GraphQL servers and efficient clients.",
- "goers": "2",
+ "goers": "4",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -2619,7 +2619,7 @@
"event_end": "2025-09-09 15:45",
"event_type": "Workshops",
"description": "Unleash the Power of Federation with Hive Gateway Discover the possibilities of your GraphQL APIs! Learn how to use GraphQL Federation to unite various services and get to know Hive Gateway, an open-source GraphQL router. During this practical exercise, you will configure a simple federated gateway and execute queries across merged schemas. Discover important features such as built-in monitoring with OpenTelemetry, automatic query batching for optimal efficiency, strong security choices like JWT authentication and rate limiting, and GraphQL Subscriptions for real-time data. Find out for yourself how Hive Gateway makes it easier to create scalable and maintainable GraphQL.",
- "goers": "2",
+ "goers": "4",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -2672,7 +2672,7 @@
"event_end": "2025-09-09 15:45",
"event_type": "GraphQL Working Group",
"description": "Curious about how observability is evolving in the GraphQL ecosystem? This session explores the current state of OpenTelemetry and its integration with GraphQL. We'll cover the fundamentals of OpenTelemetry, introduce the OpenTelemetry working group (https://github.com/graphql/otel-wg), and dive into tracing, logging, and metrics - all essential pillars of observability. You'll also learn how OpenTelemetry is being applied in distributed GraphQL architectures to improve performance monitoring and troubleshooting across services. Whether you're new to observability or looking to level up your GraphQL stack, this talk will bring you up to speed on where the community is heading.",
- "goers": "3",
+ "goers": "5",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -2754,7 +2754,7 @@
"event_end": "2025-09-09 16:40",
"event_type": "GraphQL Working Group",
"description": "Although the topic of namespacing has been brought up repeatedly in the GraphQL community over the last decade, there is an understandable worry that it would lead to anti-patterns in schema design. If namespacing is used as an excuse to avoid coordination between teams, this can result in a fragmented GraphQL schema that reflects current team boundaries as opposed to domain or client concerns.\n\nGraphQL Federation offers an alternative architecture: when coordination is enforced and consistency guaranteed, a large number of teams can contribute to a single, coherent GraphQL schema without the danger of stepping on each other's toes.\n\nEven with that architecture in place however, I believe there are still legitimate use cases for namespacing. In this talk, I will go over some of those use cases, and formulate a set of design principles that could guide the introduction of namespacing in GraphQL.",
- "goers": "4",
+ "goers": "5",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -2837,7 +2837,7 @@
"event_end": "2025-09-09 17:30",
"event_type": "Workshops",
"description": "GraphQL is evolving — and with the new Composite Schema Specification, building distributed GraphQL systems has never been more standardized, flexible, and interoperable.\n\nIn this workshop, we'll dive into the core principles behind the Composite Schema Specification and demonstrate how they enable modular, scalable GraphQL architectures across teams and services. Whether you're coming from Node.js, Java, .NET, or any other stack — this specification is designed to work with you, not against you.\n\nAt the heart of this new standard is a powerful idea: composing GraphQL APIs in a strongly typed way. No more hidden fields. No more untyped extensions or brittle conventions.\n\nYou'll learn how to:\n- Design and build a distributed GraphQL system using the Composite Schema Specification
- Compose services with clear ownership and type-safe contracts
- Evolve your composite schema over time without breaking a sweat
- Solve real-world challenges like shared types, or auth propagation
- Operate composed schemas with observability, continuous integration, and confidence
\nWhether you're building from scratch or evolving an existing monolith, this workshop will equip you with the tools and mental models to harness composition — the right way.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -2883,7 +2883,7 @@
"event_end": "2025-09-09 17:30",
"event_type": "GraphQL Working Group",
"description": "This session is an opportunity for working group members to discuss the topics raised in the working group talks earlier in the day, and brainstorm ideas for moving forward.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -2987,12 +2987,12 @@
"event_key": "929630",
"active": "Y",
"pinned": "N",
- "name": "Hello Graffle! A Modular Type Safe GraphQL Client - Jason Kuhrt, The Guild",
+ "name": "Lightning Talk: Hello Graffle! A Modular Type Safe GraphQL Client - Jason Kuhrt, The Guild",
"event_start": "2025-09-10 09:00",
"event_end": "2025-09-10 09:10",
"event_type": "Developer Experience",
"description": "Over the past year I have been evolving graphql-request into Graffle, a modular type safe GraphQL Client. Most of its features are realized as plugins so much so that it actually has fewer capabilities than graphql-request at its core! Graffle initially grew out of my desire to have a JS GraphQL client with a fully featured and type safe document builder which I couldn’t get from tools like GenQL or Zeus at the time.\n\nGraffle is still a mostly unknown work in progress but I am ready to begin talking about it and already some early adopters have taken to giving regular feedback. I think GraphQL can benefit from strengthened integrations with TypeScript. My past work on Nexus underscores that belief and I've been happy to see more recent tools enter the space like Pothos.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -3038,7 +3038,7 @@
"event_end": "2025-09-10 09:30",
"event_type": "GraphQL in Production",
"description": "What started as a single developer's passion project now powers mission-critical APIs for tech giants like Twitter/X, Netflix, Amazon, AirBnB, and Atlassian. As the engine behind Spring for GraphQL and with over 2.2 million monthly downloads, GraphQL Java has become the Java implementation of GraphQL.\n\nHow does a volunteer-driven open source project not just survive, but thrive for a decade? In this talk, we'll share the crucial technical decisions and community building strategies that transformed a hobby project into an industry standard. We'll share how we fostered contributions from over 250 volunteers while maintaining high code quality and project momentum. You'll walk away with actionable insights to help you lead any software project, whether it's open source or enterprise.\n\nAbout the speakers: we are the maintainers of GraphQL Java, who have guided the project from its first commit to becoming the industry standard.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -3091,7 +3091,7 @@
"event_end": "2025-09-10 09:30",
"event_type": "GraphQL in Production",
"description": "Hacking the Federation Query Planner Federation allows concurrent execution across services - but there’s an edge case! And when it occurs, it’s a big performance problem and potentially very hard to solve.\n\nThis talk showcases an edge case we ran into at Yelp, how we solved it in the short term, and the what the long term spec changes are (specifically within the Composite Schemas spec).",
- "goers": "0",
+ "goers": "1",
"seats": "0",
"invite_only": "N",
"venue": "Studio - 5th Floor",
@@ -3168,12 +3168,12 @@
"event_key": "929204",
"active": "Y",
"pinned": "N",
- "name": "What If GraphQL Knew Accessibility? - Vanessa Johnson, The New York Times",
+ "name": "Lightning Talk: What If GraphQL Knew Accessibility? - Vanessa Johnson, The New York Times",
"event_start": "2025-09-10 09:20",
"event_end": "2025-09-10 09:30",
"event_type": "Developer Experience",
"description": "What if your GraphQL schema could do more than provide data? What if it could help your app be more accessible from the start? In this lightning talk, we'll explore an innovative idea of embedding accessibility metadata directly into GraphQL schemas. Inspired by using Kotlin semantics in Jetpack Compose, imagine annotating fields with labels, roles, or screen reader hints that can be used to support screen readers, improve navigation, and even power automated accessibility testing. By adding custom accessibility annotations, tools could generate more accessible UI components, which enhances both the developer experience and the user experience. This is a call to rethink the developer experience and treat accessibility as a first-class concern. Let's reimagine GraphQL not just as a data layer, but as an inclusive design enabler.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -3219,7 +3219,7 @@
"event_end": "2025-09-10 10:10",
"event_type": "Developer Experience",
"description": "We will explore the novel static analysis approach used by Grats to enable a true implementation-first developer experience for building GraphQL servers in TypeScript. \n \nIf you are interested in compilers, type systems, static analysis and developer experience, this talk is for you!",
- "goers": "1",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -3265,7 +3265,7 @@
"event_end": "2025-09-10 10:10",
"event_type": "Developer Experience",
"description": "Managing separate API definitions for REST and GraphQL APIs that serve the same underlying data can be inefficient and lead to duplicated efforts. At Pinterest, we are streamlining our API definitions and unifying our data models with TypeSpec. TypeSpec allows us to define our API shapes once and generate API schemas in multiple forms such as OpenAPI, Protobuf, and now GraphQL!\n \nWe’ve developed an open-source TypeSpec GraphQL Emitter which generates valid GraphQL schemas directly from TypeSpec definitions.\n \nJoin us for an overview of how TypeSpec and the GraphQL Emitter can streamline your API workflow. We'll explore:\n \n* How TypeSpec's unified definition approach accelerates development across multiple API specs\n* The inner workings of our open-source GraphQL Emitter\n* Our wins and lessons learned while building the GraphQL Emitter\n \nThis talk will be perfect for anyone interested in GraphQL schema generation, unified API definitions, and vague Lord of the Rings references! See you there!",
- "goers": "3",
+ "goers": "5",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -3357,7 +3357,7 @@
"event_end": "2025-09-10 10:50",
"event_type": "Developer Experience",
"description": "In theory, data loaders solve most \"N+1\" problems in GraphQL. In practice, they can be hard to implement, so they’re typically used only in performance-critical situations and often reactively, once inefficiencies surface. To achieve better performance, batching needs to be applied wherever possible.\n \nThis talk introduces batch resolvers, a more developer-friendly alternative to data loaders. While traditional GraphQL resolvers take a single input and produce a single output, batching resolvers take a list of inputs and return a list of outputs. A batch resolver can simply call a batch service API without worrying about data loaders.\n \nWhen a developer provides a batch resolver, our GraphQL server automatically aggregates individual data fetches into a single call to that resolver. It can also apply heuristics to improve aggregation, for example by consolidating different selection sets for the same entity into a single input. This design not only makes application developers’ lives easier, but also allows the server to better optimize query execution by coordinating batch dispatching as part of a broader execution strategy.",
- "goers": "3",
+ "goers": "4",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -3398,12 +3398,12 @@
"event_key": "924215",
"active": "Y",
"pinned": "N",
- "name": "Next-Generation GraphQL Cache Management in Your Android and iOS Apps - Benoit Lubek, Apollo GraphQL",
+ "name": "Lightning Talk: Next-Generation GraphQL Cache Management in Your Android and iOS Apps - Benoit Lubek, Apollo GraphQL",
"event_start": "2025-09-10 10:20",
"event_end": "2025-09-10 10:30",
"event_type": "Developer Experience",
"description": "Effective caching is essential for building fast, resilient mobile apps especially when aiming for offline-first experiences. Apollo Kotlin and Apollo iOS offer a powerful Normalized Cache component tailored to GraphQL. In this lightning talk, we’ll showcase the latest advancements in both libraries, including support for pagination, cache expiration, and other new features designed to simplify and supercharge cache management on mobile.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -3497,12 +3497,12 @@
"event_key": "898726",
"active": "Y",
"pinned": "N",
- "name": "GraphQL Caching Lightning Talk - Emily Goodwin, Independent",
+ "name": "Lightning Talk: GraphQL Caching Lightning Talk - Emily Goodwin, Independent",
"event_start": "2025-09-10 10:40",
"event_end": "2025-09-10 10:50",
"event_type": "GraphQL in Production",
"description": "GraphQL provides flexibility in fetching data but this can prove challenging for caching. In this talk I cover the basics of caching in GraphQL such as layers you can cache at a high level. Layers such as the CDN, client side, server side, and database are touched upon with solutions from the community. The talk will also cover when to use each layer and what statistics to look at for improvement. I talk about how caching at multiple layers provides the best experience for the end user. By the end of this talk beginners will have a path forward to how they can cache at different layers for better performance.",
- "goers": "4",
+ "goers": "5",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -3584,7 +3584,7 @@
"event_end": "2025-09-10 11:45",
"event_type": "Developer Experience",
"description": "There are many aspects to consider when building a GraphQL API: Authentication, authorization, performance, schema design, and team workflow to name a few. Each aspect encompasses considerations, practices, and tools (or lack thereof). One aspect, documentation, can be easily neglected. This year at The Guild I spent time exploring that domain and prototyping an open source tool we’re calling Polen.\n\nI will present our thoughts on what characteristics and features we’d like to have from GraphQL documentation tooling and finish with a demo of how Polen tackled some of those things. I hope this session stimulates your own thinking about what documentation tools should include and tangible technical steps we might take to get there.",
- "goers": "2",
+ "goers": "1",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -3630,7 +3630,7 @@
"event_end": "2025-09-10 11:45",
"event_type": "GraphQL in Production",
"description": "Traditional GraphQL servers execute queries field by field with a depth-first algorithm as defined in the GraphQL specification. In contrast, GraphQL federation gateways need to partition the query and retrieve chunks of data from external data sources, creating new challenges. We'll present how we solved those challenges with a focus on performance.\n \nThe first, query planning, is to find the best possible plan with the multiple possibilities federation offers to unify your data and the various data sources with their requirements. We express this problem as a graph of possibilities and solve it as a Steiner Tree problem. The second challenge is performant execution. As we need to read and write overlapping chunks of the response in parallel, it's hard to be as efficient as a traditional GraphQL server writing a response iteratively with independent fields. We build an execution DAG with field dependencies, parallelizing work as much as possible without any lock on the response. We also pre-compute the expected data shape to ingest and validate incoming data into the response without any intermediate memory allocation.",
- "goers": "0",
+ "goers": "1",
"seats": "0",
"invite_only": "N",
"venue": "Studio - 5th Floor",
@@ -3676,7 +3676,7 @@
"event_end": "2025-09-10 11:45",
"event_type": "GraphQL in Production",
"description": "Last year we introduced strict error handling - with @throwOnFieldError as an example of how this can be accomplished. This year, we’ll discuss how to safely roll it out.\n \nYou’ve had a GraphQL codebase that weakly handled server-side errors for years. Now, you have the tools (directives, hooks, handlers, and language features) that let you treat field errors properly. However, it’s a daunting task to suddenly explode queries en-masse by flipping a switch. This move is powerful, but requires a thoughtful and data-driven approach to do safely.\n \nIn this talk we’ll cover:\n* Preparing the groundwork for migration to stricter error handling\n* Using data to make informed decisions about fragment/query behavior\n* Gating your change at a singular point\n* Scaling the rollout to a large codebase\n* How we’re approaching this rollout at Meta",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -3722,7 +3722,7 @@
"event_end": "2025-09-10 12:25",
"event_type": "Developer Experience",
"description": "One of the great achievements of GraphQL is composable, full-stack type safety: a strongly-typed schema, against which one writes client components, and from which minimal yet sufficient queries are generated. This seamless flow from database to UI, with immediate feedback, compile-time guarantees and great performance, represents an unmatched DevEx breakthrough.\n \nBut what if we use a full-stack client (like Isograph aims to be)? Or use a rich client in combination with a Hasura, Prisma or PostGraphile, and effectively write components against an SQL schema? Have both the GraphQL schema and its operation language become mere implementation details?\n \nIn this talk, I'll explore how GraphQL's apparent disappearance into tooling actually represents its ultimate victory. Even as GraphQL-the-syntax fades from view, its architectural innovations—fragment composability, full-stack type safety, document merging, persisted operations—become the invisible foundation of modern development.\n \nThe best way to honor this legacy isn't to protect its syntax — it's to let its principles be reborn in new forms, evolving as our tools evolve, making app development better for years to come.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -3803,6 +3803,12 @@
"start_time_ts": 1757498100,
"end_date": "2025-09-10",
"end_time": "12:25:00",
+ "files": [
+ {
+ "path": "https://static.sched.com/hosted_files/graphqlconf2025/43/Breaking the Monolith_ Our Journey from Proto to Federated GraphQL at Scale.pdf",
+ "name": "Breaking the Monolith_ Our Journey from Proto to Federated GraphQL at Scale.pdf"
+ }
+ ],
"event_subtype": "Federation and distributed systems"
},
{
@@ -3896,7 +3902,7 @@
"event_end": "2025-09-10 14:10",
"event_type": "Developer Experience",
"description": "`useQuery` is a powerful and simple abstraction, but there is so much more to Apollo Client today. In this talk we’ll re-introduce Apollo Client for this new era. Query preloading, suspense, fragment APIs, and data masking have given GraphQL practitioners a toolset to build sophisticated, scalable, and highly performant applications like never before. Learn about these new APIs, upgraded tooling, and how version 4.0 (and beyond) gives users a leaner, cleaner, and more capable open source GraphQL client.",
- "goers": "1",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -3942,7 +3948,7 @@
"event_end": "2025-09-10 14:10",
"event_type": "GraphQL in Production",
"description": "Imagine having a federated GraphQL query builder customized to meet unique software infrastructure requirements—have you ever dreamed of such a tool? If so, please join us for an exciting session where we uncover LinkedIn’s code first approach to querying entity-oriented data with federated GraphQL on top of backend gRPC services. Discover how our solution leverages the advanced capabilities of gRPC for enhanced performance, low latency, and multi-language support, while achieving seamless integration with our established Rest.li framework. We will dive into the motivations behind adopting this strategy, the intricate challenges encountered, and the significant improvements in developer experience and productivity it brings. With real-world examples and performance benchmarks, witness how this approach modernizes our service infrastructure, leading to more efficient and scalable solutions.",
- "goers": "0",
+ "goers": "2",
"seats": "0",
"invite_only": "N",
"venue": "Studio - 5th Floor",
@@ -4117,12 +4123,12 @@
"event_key": "924826",
"active": "Y",
"pinned": "N",
- "name": "\"Please Migrate Away From Field X To Field Y Before Z\" - A Story on Automating Our Deprecation Lifecycle - Rick Bijkerk, Bol",
+ "name": "Lightning Talk: \"Please Migrate Away From Field X To Field Y Before Z\" - A Story on Automating Our Deprecation Lifecycle - Rick Bijkerk, Bol",
"event_start": "2025-09-10 14:20",
"event_end": "2025-09-10 14:30",
"event_type": "GraphQL in Production",
"description": "Any company that wants to innovate deals with change. Within GraphQL that often means introducing new fields but also deprecating old fields & types.\nThe faster you can get rid of these old fields & types the less complex your architecture is and less complexity means an easier time building new features!\n\nWe saw this problem and got tired of the endless “please migrate away from field X to field Y before Z” emails, which were often not even sent to the right group of consumers!\n\nWe automated this process by building a slack bot that uses production analytical data to figure out what clients are using deprecated fields and automated the communication!",
- "goers": "1",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -4163,12 +4169,12 @@
"event_key": "929620",
"active": "Y",
"pinned": "N",
- "name": "Efficient Semantic Comparison of GraphQL Queries - Derek Kuc, Apollo GraphQL",
+ "name": "Lightning Talk: Efficient Semantic Comparison of GraphQL Queries - Derek Kuc, Apollo GraphQL",
"event_start": "2025-09-10 14:40",
"event_end": "2025-09-10 14:50",
"event_type": "Developer Experience",
"description": "Ever wondered if two seemingly different GraphQL queries actually return the same data? Or how to ensure that complex queries—packed with type conditions and directives like @skip/@include—still mean the same thing after a major refactor? In this talk, we’ll explore a novel static analysis technique that efficiently checks whether one query’s response is always a subset of another’s. By performing this subset test in both directions, we can reliably determine query equivalence—bringing new clarity to complex GraphQL operations.",
- "goers": "0",
+ "goers": "1",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -4306,7 +4312,7 @@
"event_end": "2025-09-10 15:30",
"event_type": "GraphQL in Production",
"description": "\"There are only two hard things in Computer Science: cache invalidation and naming things\".\n\nGraphQL provides many benefits over other query languages. Federation builds on top of this foundation to provide even more flexibility and power. But even with all that GraphQL has to offer, the problem of naming remains.\n\nIn this talk, Jeff Dolle, from The Guild, will share what he's learned about schema design: proven design philosophies, designing for forward compatibility, exposing errors through types, and tips for how to avoid ambiguous or misleading type names.\n\nTogether, we will then go through an example product design meeting: taking user stories and building a complete GraphQL schema.",
- "goers": "3",
+ "goers": "4",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -4388,7 +4394,7 @@
"event_end": "2025-09-10 16:20",
"event_type": "GraphQL in Production",
"description": "Plugging an LLM into GraphQL sounds simple—until it drowns in thousands of fields, types, and connections. Most models today can’t reason effectively over large APIs without brittle prompt hacks or hardcoded shortcuts.\n\nModel Context Protocol (MCP) is the cutting-edge solution for enabling seamless, dynamic interactions between LLMs and external tooling. It standardizes the way models interact with various tools, breaking down barriers between APIs and AI systems.\n\nIn this talk, you’ll discover how to turn any GraphQL endpoint into an MCP-compatible server with minimal overhead. Reuse your existing GraphQL infrastructure to avoid reinventing authorization, schema management, and validation enabling scalable, robust LLM integrations. We’ll compare existing tools and automated schema discovery against hand-crafted mappers based on benchmarks of public GraphQL APIs. Join us to learn about our experiences and recommendations for your next GenAI project, powered by GraphQL.",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "IJzaal - 5th Floor",
@@ -4487,7 +4493,7 @@
"event_end": "2025-09-10 16:45",
"event_type": "Keynote Sessions",
"description": "This talk will give attendees an overview of the structure of GraphQL's official organizations: The GraphQL Foundation and the GraphQL Specification Project. It will get specific about the governance and roadmaps of each organization and their specific priorities in 2025 and beyond.\n\nIn my time serving in these various institutions, I've noticed that even the most active GraphQL practitioners aren't fully aware of what they are and what they do. Attendees will learn about the GraphQL Working Group, the Technical Steering Committee, and the Foundation's Governing Board. We'll also touch upon the various technical working groups and the new Community Working Group. The talk culminates in a call to action for folks to get involved.",
- "goers": "4",
+ "goers": "5",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
@@ -4532,7 +4538,7 @@
"event_start": "2025-09-10 16:45",
"event_end": "2025-09-10 17:00",
"event_type": "Keynote Sessions",
- "goers": "2",
+ "goers": "3",
"seats": "0",
"invite_only": "N",
"venue": "Grote Zaal - 2nd Floor",
diff --git a/scripts/sync-sched/speakers.json b/scripts/sync-sched/speakers.json
index 42ecdf690b..e87f68ff22 100644
--- a/scripts/sync-sched/speakers.json
+++ b/scripts/sync-sched/speakers.json
@@ -82,7 +82,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "adam.sayah",
@@ -126,7 +126,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "aditi_rajawat",
@@ -212,7 +212,7 @@
2023,
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "alex_reilly.7ldur4l",
@@ -275,7 +275,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "amy1908",
@@ -350,7 +350,7 @@
2024,
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "andrei.bocan",
@@ -366,7 +366,7 @@
2024,
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "andrew.doyle1",
@@ -503,7 +503,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "ardatanrikulu",
@@ -528,7 +528,7 @@
2023,
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "arkenflame",
@@ -590,7 +590,7 @@
2024,
2025
],
- "~syncedDetailsAt": 1756472735600
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "benjamin154",
@@ -605,7 +605,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "benjie3",
@@ -646,7 +646,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "borisbesemer",
@@ -661,7 +661,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "brandon.r.minnick",
@@ -850,7 +850,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "danadajian",
@@ -885,7 +885,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "danielle.man",
@@ -930,7 +930,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "dkuc",
@@ -1147,7 +1147,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904595242
},
{
"username": "fbjork",
@@ -1206,7 +1206,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "gabrielschulhof",
@@ -1328,7 +1328,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "hello2358",
@@ -1413,7 +1413,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "jamie855",
@@ -1467,7 +1467,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "jared_cheney.7rad60v",
@@ -1656,7 +1656,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "jordaneldredge",
@@ -1695,7 +1695,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "juancarlosjr97",
@@ -1764,7 +1764,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "keerthan.ekbote",
@@ -2017,7 +2017,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "lyonwj1",
@@ -2081,7 +2081,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756283267177
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "mansi.mittal",
@@ -2092,11 +2092,16 @@
"location": "",
"url": "",
"avatar": "//avatars.sched.co/1/45/23098777/avatar.jpg.320x320px.jpg?d75",
- "socialurls": [],
+ "socialurls": [
+ {
+ "service": "LinkedIn",
+ "url": "https://www.linkedin.com/in/mansi-mit03/"
+ }
+ ],
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367508
+ "~syncedDetailsAt": 1756904598013
},
{
"username": "marco.reni",
@@ -2191,7 +2196,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367508
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "marybriskin",
@@ -2372,7 +2377,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367508
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "michael.bleigh",
@@ -2411,7 +2416,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367508
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "omribruchim",
@@ -2620,11 +2625,16 @@
"location": "San Francisco, USA",
"url": "",
"avatar": "//avatars.sched.co/4/a1/23098792/avatar.jpg.320x320px.jpg?a85",
- "socialurls": [],
+ "socialurls": [
+ {
+ "service": "LinkedIn",
+ "url": "https://www.linkedin.com/in/rstata/"
+ }
+ ],
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367508
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "rickbijkerk54",
@@ -2639,14 +2649,14 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367508
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "robert.balicki",
"company": "Pinterest",
"position": "Staff Engineer",
"name": "Robert Balicki",
- "about": "Robert is an engineer at Pinterest, where he helps the company adopt Relay and GraphQL. He was previously on the Relay team at Meta. Check out Isograph! https://isograph.dev",
+ "about": "Robert is an engineer at Pinterest, where he helps the company adopt Relay and GraphQL. He was previously on the Relay team at Meta. Check out Isograph! https://isograph.dev",
"location": "",
"url": "",
"avatar": "//avatars.sched.co/5/8b/18743858/avatar.jpg.320x320px.jpg?b95",
@@ -2727,7 +2737,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367508
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "saihajpreet.singh",
@@ -2766,7 +2776,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367509
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "sanvertarmur",
@@ -2781,7 +2791,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367509
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "sasanders26",
@@ -3047,7 +3057,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756284367509
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "suresh_muthu",
@@ -3154,7 +3164,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904601333
},
{
"username": "tim.hall.engr",
@@ -3189,11 +3199,16 @@
"location": "",
"url": "",
"avatar": "//avatars.sched.co/2/e2/23098807/avatar.jpg.320x320px.jpg?cff",
- "socialurls": [],
+ "socialurls": [
+ {
+ "service": "LinkedIn",
+ "url": "https://www.linkedin.com/in/tom-houlé/?locale=en_US"
+ }
+ ],
"_years": [
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "tristan119",
@@ -3318,7 +3333,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "vmjohnson999",
@@ -3369,7 +3384,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756472647128
+ "~syncedDetailsAt": 1756904606430
},
{
"username": "yaacovcr",
@@ -3453,7 +3468,7 @@
"_years": [
2025
],
- "~syncedDetailsAt": 1756282673957
+ "~syncedDetailsAt": 1756904595242
}
]
}
\ No newline at end of file
diff --git a/src/app/conf/2025/components/speaker-card.tsx b/src/app/conf/2025/components/speaker-card.tsx
index 0db943c8dd..0059a03b40 100644
--- a/src/app/conf/2025/components/speaker-card.tsx
+++ b/src/app/conf/2025/components/speaker-card.tsx
@@ -10,6 +10,7 @@ import { SpeakerLinks } from "./speaker-links"
import styles from "./speaker-card.module.css"
import { formatSpeakerPosition } from "./format-speaker-position"
+import { formatDescription } from "../schedule/[id]/format-description"
export interface SpeakerCardProps extends React.HTMLAttributes {
isReturning?: boolean
@@ -74,9 +75,12 @@ export function SpeakerCard({
{speaker.about && (
-
- {speaker.about}
-
+
)}
diff --git a/src/app/conf/2025/schedule/[id]/format-description.test.tsx b/src/app/conf/2025/schedule/[id]/format-description.test.tsx
new file mode 100644
index 0000000000..f6d4418dcf
--- /dev/null
+++ b/src/app/conf/2025/schedule/[id]/format-description.test.tsx
@@ -0,0 +1,52 @@
+import { it } from "node:test"
+import { strict as assert } from "node:assert"
+
+import { formatDescription } from "./format-description"
+
+it("does not double-wrap links", () => {
+ assert.equal(
+ formatDescription(`Check out Y! https://y.dev`),
+ `Check out Y! y.dev`,
+ )
+})
+
+it("enriches plain URLs", () => {
+ assert.equal(
+ formatDescription(`Visit https://example.com for more info`),
+ `Visit example.com for more info`,
+ )
+})
+
+it("adds attributes to existing links without URL content", () => {
+ assert.equal(
+ formatDescription(`Click here`),
+ `Click here`,
+ )
+})
+
+it("handles mixed content", () => {
+ assert.equal(
+ formatDescription(
+ `Check Y site and https://example.com`,
+ ),
+ `Check Y site and example.com`,
+ )
+})
+
+it("handles multiple URLs in one text", () => {
+ assert.equal(
+ formatDescription(
+ `Visit https://github.com and https://example.org for info`,
+ ),
+ `Visit github.com and example.org for info`,
+ )
+})
+
+it("handles existing link with existing class", () => {
+ assert.equal(
+ formatDescription(
+ `Click here`,
+ ),
+ `Click here`,
+ )
+})
diff --git a/src/app/conf/2025/schedule/[id]/format-description.tsx b/src/app/conf/2025/schedule/[id]/format-description.tsx
index a34c253d98..c528048547 100644
--- a/src/app/conf/2025/schedule/[id]/format-description.tsx
+++ b/src/app/conf/2025/schedule/[id]/format-description.tsx
@@ -1,45 +1,48 @@
-const URL_REGEX = /https?:\/\/[^\s]+/g
-const LINK_REGEX = /]*href\s*=\s*[^>]*)>/gi
+// Combined regex that matches either existing anchor tags OR standalone URLs
+const COMBINED_REGEX =
+ /(]*href\s*=\s*[^>]*>.*?<\/a>)|(https?:\/\/[^\s]+)/gi
export function formatDescription(text: string): string {
- // we coerce all existing anchor tags to have target="_blank" rel="noopener noreferrer" and typography-link class
- const result = text.replace(LINK_REGEX, (_, attributes) => {
- let attrs = attributes
-
- if (!attrs.includes("target=")) {
- attrs += ' target="_blank"'
- }
-
- if (!attrs.includes("rel=")) {
- attrs += ' rel="noopener noreferrer"'
- }
-
- if (!attrs.includes("class=")) {
- attrs += ' class="typography-link"'
- } else if (!attrs.includes("typography-link")) {
- attrs = attrs.replace(
- /class\s*=\s*["']([^"']*)/gi,
- 'class="$1 typography-link',
+ return text.replace(COMBINED_REGEX, (match, anchorTag, standaloneUrl) => {
+ if (anchorTag) {
+ const linkMatch = anchorTag.match(
+ /]*href\s*=\s*[^>]*)>(.*?)<\/a>/i,
+ )
+ if (!linkMatch) return anchorTag
+
+ const [, attributes, content] = linkMatch
+ let attrs = attributes
+
+ if (!attrs.includes("rel=")) {
+ attrs += ' rel="noopener noreferrer"'
+ }
+
+ if (!attrs.includes("target=")) {
+ attrs += ' target="_blank"'
+ }
+
+ if (!attrs.includes("class=")) {
+ attrs += ' class=" typography-link"'
+ } else if (!attrs.includes("typography-link")) {
+ attrs = attrs.replace(
+ /class\s*=\s*["']([^"']*)/gi,
+ 'class="$1 typography-link',
+ )
+ }
+
+ const urlContent = content.replace(
+ /https?:\/\/[^\s]+/g,
+ (url: string) => {
+ return url.replace(/^https?:\/\//, "")
+ },
)
- }
-
- return ``
- })
-
- // then we format plain URLs that are not already inside an anchor tag
- return result.replace(URL_REGEX, (url, offset) => {
- const beforeUrl = result.slice(0, offset)
- const afterUrl = result.slice(offset + url.length)
-
- const lastOpenTag = beforeUrl.lastIndexOf("<")
- const lastCloseTag = beforeUrl.lastIndexOf(">")
- const nextCloseTag = afterUrl.indexOf(">")
- if (lastOpenTag > lastCloseTag && nextCloseTag !== -1) {
- return url
+ return `${urlContent}`
+ } else if (standaloneUrl) {
+ const displayUrl = standaloneUrl.replace(/^https?:\/\//, "")
+ return `${displayUrl}`
}
- const displayUrl = url.replace(/^https?:\/\//, "")
- return `${displayUrl}`
+ return match
})
}
diff --git a/src/app/conf/2025/speakers/[id]/page.tsx b/src/app/conf/2025/speakers/[id]/page.tsx
index d2b66dd124..c7df3d322e 100644
--- a/src/app/conf/2025/speakers/[id]/page.tsx
+++ b/src/app/conf/2025/speakers/[id]/page.tsx
@@ -77,9 +77,12 @@ export default function SpeakerPage({ params }: SpeakerProps) {
{speaker.about && (
-
- {formatDescription(speaker.about)}
-
+
)}
{currentYearSessions.length > 0 && (
diff --git a/src/app/conf/_api/sched-client.tsx b/src/app/conf/_api/sched-client.tsx
index 67e4ab7740..d2f1c16757 100644
--- a/src/app/conf/_api/sched-client.tsx
+++ b/src/app/conf/_api/sched-client.tsx
@@ -135,9 +135,7 @@ export async function getSchedule(
...session,
event_type,
event_subtype,
- description: preprocessDescription(description, {
- allowSomeHtml: true,
- }),
+ description: preprocessDescription(description),
}
})
@@ -185,10 +183,7 @@ export async function getSpeakerDetails(
return shapeSpeaker(data as SchedSpeaker)
}
-function preprocessDescription(
- description: string | undefined | null,
- options: { allowSomeHtml?: boolean } = {},
-): string {
+function preprocessDescription(description: string | undefined | null): string {
let res = description || ""
// we respect manual line breaks
@@ -197,9 +192,18 @@ function preprocessDescription(
// respecting and tags doesn't make sense, because speakers don't use them consistently
// we'll improve how the descriptions look later down the tree in the session details page
return stripHtml(res, {
- ignoreTags: options.allowSomeHtml
- ? ["a", "b", "i", "em", "strong", "code", "pre", "ul", "ol", "li"]
- : [],
+ ignoreTags: [
+ "a",
+ "b",
+ "i",
+ "em",
+ "strong",
+ "code",
+ "pre",
+ "ul",
+ "ol",
+ "li",
+ ],
}).result
}