Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/sync-sched/schedule-2026.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions scripts/sync-sched/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ async function sync(
2023: "https://graphqlconf23.sched.com/api",
2024: "https://graphqlconf2024.sched.com/api",
2025: "https://graphqlconf2025.sched.com/api",
2026: "https://graphqlconf2026.sched.com/api",
}[year]

assert(apiUrl, `API URL for year ${year} not found`)
Expand Down
59 changes: 59 additions & 0 deletions src/app/conf/2026/_data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import "server-only"

import { SchedSpeaker, ScheduleSession } from "@/app/conf/2023/types"
import { readSpeakers } from "../_api/sched-data"

const speakersData = require("../../../../scripts/sync-sched/speakers.json")
const equalitySets: string[][] = speakersData.equal || []

export const schedule: ScheduleSession[] = require("../../../../scripts/sync-sched/schedule-2026.json")

type SpeakerUsername = SchedSpeaker["username"]

export const speakerSessions = new Map<SpeakerUsername, ScheduleSession[]>()

for (const session of schedule) {
for (const speaker of session.speakers || []) {
if (!speakerSessions.has(speaker.username)) {
speakerSessions.set(speaker.username, [])
}

speakerSessions.get(speaker.username)!.push(session)
}
}

export const speakers: SchedSpeaker[] = readSpeakers(2026).filter(speaker =>
speakerSessions.has(speaker.username),
)

export const previousEditionSessions = new Map<
SpeakerUsername,
ScheduleSession[]
>()

{
const schedule2023 = require("../../../../scripts/sync-sched/schedule-2023.json")
const schedule2024 = require("../../../../scripts/sync-sched/schedule-2024.json")
const schedule2025 = require("../../../../scripts/sync-sched/schedule-2025.json")

collectSessionsFromPreviousYears(schedule2023)
collectSessionsFromPreviousYears(schedule2024)
collectSessionsFromPreviousYears(schedule2025)
}

function collectSessionsFromPreviousYears(schedule: ScheduleSession[]) {
for (const session of schedule) {
for (const speaker of session.speakers || []) {
const duplicates = equalitySets.find(set =>
set.includes(speaker.username),
)

for (const username of duplicates || [speaker.username]) {
if (!previousEditionSessions.has(username)) {
previousEditionSessions.set(username, [])
}
previousEditionSessions.get(username)!.push(session)
}
}
}
}
35 changes: 35 additions & 0 deletions src/app/conf/2026/_videos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* This was populated with data captured via:
*
* https://developers.google.com/youtube/v3/docs/playlistItems/list
*
* with:
*
* - part: snippet
* - maxResults: 50
* - playlistId: <TODO>
*
* And then also adding `pageToken` for the second request to get the second
* page.
*
* Note that the playlistId is the ID of the "Uploads" playlist for the
* "GraphQLFoundationTalks" channel.
*
* Since the videos are unlisted it needed to be authenticated with the
* https://www.googleapis.com/auth/youtube.readonly scope. This is also
* why we couldn't use the generate-videos-mappings.py script.
*
* Then we simply mapped over the results:
*
* ```js
* for (const item of data.items) {
* const id = item.snippet.resourceId.videoId;
* const title = item.snippet.title
* videos.push({ id, title })
* }
* ```
*/
export const videos: {
id: string
title: string
}[] = []
113 changes: 113 additions & 0 deletions src/app/conf/2026/assets/graphql-foundation-wordmark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions src/app/conf/2026/code-of-conduct/code-of-conduct.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
The Linux Foundation and its project communities are dedicated to providing a harassment-free experience for participants at all of our events, whether they are held in person or virtually. Linux Foundation events are working conferences intended for professional networking and collaboration within the open source community. They exist to encourage the open exchange of ideas and expression and require an environment that recognizes the inherent worth of every person and group. While at Linux Foundation events or related ancillary or social events, any participants, including members, speakers, attendees, volunteers, sponsors, exhibitors, booth staff and anyone else, must not engage in harassment in any form.

This Code of Conduct may be revised at any time by The Linux Foundation and the terms are non-negotiable. Your registration for or attendance at any Linux Foundation event, whether it's held in person or virtually, indicates your agreement to abide by this policy and its terms.

<Callout>
## Expected Behavior

All event participants, whether they are attending an in-person event or a virtual event, are expected to behave in accordance with professional standards, with both this Code of Conduct as well as their respective employer's policies governing appropriate workplace behavior and applicable laws.
</Callout>

## Unacceptable Behavior

Harassment will not be tolerated in any form, whether in person or virtually, including, but not limited to, harassment based on gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, age, religion or any other status protected by laws in which the conference or program is being held. Harassment includes the use of abusive, offensive or degrading language, intimidation, stalking, harassing photography or recording, inappropriate physical contact, sexual imagery and unwelcome sexual advances or requests for sexual favors. Any report of harassment at one of our events, whether in person or virtual, will be addressed immediately. Participants asked to stop any harassing behavior are expected to comply immediately. Anyone who witnesses or is subjected to unacceptable behavior should notify a conference organizer at once.

Individuals who participate (or plan to participate) in Linux Foundation events, whether its an in-person event or a virtual event, should conduct themselves at all times in a manner that comports with both the letter and spirit of this policy prohibiting harassment and abusive behavior, whether before, during or after the event. This includes statements made in social media postings, on-line publications, text messages, and all other forms of electronic communication.

Speakers should not use sexual language, images, or any language or images that would constitute harassment as defined above in their talks. Exhibitor booths serve as a platform for presenting businesses and/or projects and should maintain a professional and inclusive presence; therefore, the use of sexualized images, activities, materials, or attire, including costumes and uniforms that contribute to a sexualized environment, is strictly prohibited. Additionally, booths must not be utilized for political campaigning or promoting political causes, including the display or engagement in activities or materials that support such endeavors.

<Callout>
## Consequences of Unacceptable Behavior

If a participant engages in harassing behavior, whether in person or virtually, the conference organizers may take any action they deem appropriate depending on the circumstances, ranging from issuance of a warning to the offending individual to expulsion from the conference with no refund. The Linux Foundation reserves the right to exclude any participant found to be engaging in harassing behavior from participating in any further Linux Foundation events, trainings or other activities.

If a participant (or individual wishing to participate in a Linux Foundation event, in-person and/or virtual), through postings on social media or other online publications or another form of electronic communication, engages in conduct that violates this policy, whether before, during or after a Linux Foundation event, The Linux Foundation may take appropriate corrective action, which could include imposing a temporary or permanent ban on an individual's participation in future Linux Foundation events.
</Callout>

## What To Do If You Witness or Are Subject To Unacceptable Behavior

If you are being harassed, notice that someone else is being harassed, or have any other concerns relating to harassment, please contact a member of the conference staff immediately. You are also encouraged to contact Angela Brown, Senior VP & General Manager of Events, at [angela@linuxfoundation.org](mailto:angela@linuxfoundation.org).

<Callout>
## Incident Response

Our staff has taken incident response training and responds to harassment reports quickly and thoroughly. As referenced above, if a participant engages in harassing behavior, whether in-person or virtually, the conference organizers may take any action they deem appropriate, ranging from issuance of a warning to the offending individual to expulsion from the conference with no refund, depending on the circumstances. The Linux Foundation reserves the right to exclude any participant found to be engaging in harassing behavior from participating in any further Linux Foundation events, trainings or other activities.

Conference staff will also provide support to victims, including, but not limited to:
- Providing an Escort
- Contacting Hotel/Venue Security or Local Law Enforcement
- Briefing Key Event Staff For Response/Victim Assistance
- And otherwise assisting those experiencing harassment to ensure that they feel safe for the duration of the conference.
</Callout>

## Health and Safety Requirements

It is necessary for all attendees to cooperate and protect one another. For this reason, The Linux Foundation's events may have health and safety requirements (the "Health and Safety Requirements"). The specific requirements may vary from event to event, and will be communicated in writing prior to and during the event.

If an attendee fails to comply with any of the Health and Safety Requirements, The Linux Foundation may (but is not obligated to) take appropriate corrective action, which could include immediate removal from the event and venue without a refund, and/or imposing a temporary or permanent ban on an individual's participation in future Linux Foundation events.

<Callout>
## Pre-Event Concerns

If you are planning to attend an upcoming event, whether in-person or virtually and have concerns regarding another individual who may be present, please contact Angela Brown ([angela@linuxfoundation.org](mailto:angela@linuxfoundation.org)). Precautions will be taken to ensure your comfort and safety, including, but not limited to providing an escort, prepping onsite event staff, keeping victim and harasser from attending the same talks/social events and providing onsite contact cell phone numbers for immediate contact.
</Callout>
10 changes: 10 additions & 0 deletions src/app/conf/2026/code-of-conduct/opengraph-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SimpleOpengraphImage } from "../components/og-images/simple-opengraph-image"
export {
generateStaticParams,
contentType,
size,
} from "../components/og-images/simple-opengraph-image"

export default SimpleOpengraphImage.bind(null, {
pageTitle: "Code of Conduct",
})
99 changes: 99 additions & 0 deletions src/app/conf/2026/code-of-conduct/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import type { Metadata } from "next"
import clsx from "clsx"

import { Anchor } from "@/app/conf/_design-system/anchor"
import { ServerComponentMarkdown } from "@/app/conf/_components/server-component-markdown"
import { Button } from "@/app/conf/_design-system/button"

import { NavbarPlaceholder } from "../components/navbar"
import { Hero, HeroStripes } from "../components/hero"
import "../resources/prose.css"

import markdown from "./code-of-conduct.mdx?raw"

export const metadata: Metadata = {
title: "Code of Conduct | GraphQLConf 2026",
}

const components = {
a: (props: React.AnchorHTMLAttributes<HTMLAnchorElement>) => {
return (
<Anchor
{...props}
href={props.href ?? ""}
className={clsx(props.className, "typography-link")}
/>
)
},
ul: (props: React.HTMLAttributes<HTMLUListElement>) => {
return <ul {...props} className={clsx(props.className, "-mt-6")} />
},
Callout: (props: React.HTMLAttributes<HTMLDivElement>) => {
return (
<div
{...props}
className={clsx(
props.className,
"gql-prose-inner -mx-4 w-fit border border-neu-300 bg-neu-50 p-4 dark:border-neu-100 dark:bg-neu-50/50 max-md:border-x-0 xl:my-4",
)}
/>
)
},
}

export default function ResourcesPage() {
return (
<>
<NavbarPlaceholder className="top-0 bg-neu-100 before:bg-white/30 dark:bg-[#181A12] dark:before:bg-blk/40" />
<Hero
pageName="Code of conduct"
subtitle="The Linux Foundation"
colorScheme="neutral"
stripes={
<HeroStripes
className="-scale-x-100 dark:data-[loaded=true]:opacity-80"
evenClassName="bg-[linear-gradient(180deg,hsl(var(--color-sec-light))_0%,hsl(319deg_100%_90%_/_0.2)_100%)] dark:bg-[linear-gradient(180deg,hsl(var(--color-sec-dark))_0%,hsl(var(--color-neu-100))_100%)]"
oddClassName="bg-[linear-gradient(180deg,hsl(319deg_100%_90%_/_0.2)_0%,hsl(var(--color-sec-base))_100%)] dark:bg-[linear-gradient(180deg,hsl(var(--color-sec-dark))_0%,hsl(var(--color-neu-0))_100%)]"
/>
}
>
<Button
href="https://events.linuxfoundation.org/about/code-of-conduct/"
className="mt-[18px] w-fit"
>
See on The Linux Foundation
</Button>
</Hero>
<main className="gql-all-anchors-focusable gql-conf-navbar-strip text-neu-900 before:bg-white/40 before:dark:bg-blk/30">
<div className="gql-container gql-section xl:mb-16 xl:mt-8">
<ServerComponentMarkdown
markdown={markdown}
extractToc
render={({ mdx, data }) => {
return (
<div className="gql-prose md:max-lg:[&>:not(:first-child)]:mx-4">
<aside className="gql-sticky-aside row-span-8 -mt-1 w-fit sm:max-xl:grid sm:max-xl:grid-cols-2 sm:max-xl:bg-neu-100 sm:max-xl:p-4 dark:sm:max-xl:bg-neu-50/50 xl:max-w-[284px]">
{data.toc.map(({ value, id, depth }) => (
<a
key={id}
data-depth={depth}
className="raw typography-menu block p-4 py-2 text-neu-800 hover:bg-neu-100 hover:text-neu-900 dark:hover:bg-neu-50 max-xl:-ml-4"
style={{
paddingLeft: (depth - 2) * 16 + 16,
}}
href={`#${id}`}
>
{value}
</a>
))}
</aside>
{mdx({ components })}
</div>
)
}}
/>
</div>
</main>
</>
)
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions src/app/conf/2026/components/become-a-sponsor/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import clsx from "clsx"

import { Button } from "../../../_design-system/button"

import blurBlob from "./blur-blob.webp"
import { StripesDecoration } from "@/app/conf/_design-system/stripes-decoration"

export function BecomeASponsor() {
return (
<section className="relative overflow-hidden">
<Stripes />
<div className="gql-container gql-section xl:py-16">
<header className="flex flex-col gap-x-48 gap-y-4 md:flex-row md:items-end md:justify-between">
<div>
<h2 className="typography-h2">Become a Sponsor</h2>
<p className="typography-body-lg mt-6 text-pretty">
Connect with the global GraphQL community and showcase your brand
to industry leaders and decision-makers.
</p>
</div>
{/* TODO
<Button
variant="primary"
href="https://events.linuxfoundation.org/sponsor-GraphQLConf-25?utm_source=graphql_conf_2025&utm_medium=website&utm_campaign=sponsor_section"
target="_blank"
rel="noreferrer"
className="md:w-fit"
>
Sponsor
</Button>
*/}
</header>
<dl className="relative z-10 mt-10 border border-neu-300 md:backdrop-blur-[6.4px] xl:mt-16">
<DefinitionListItem
term="Brand Visibility"
definition="Showcase your brand to thousands of GraphQL enthusiasts and decision-makers."
/>
<DefinitionListItem
term="Lead Generation"
definition="Connect with potential customers and partners in the GraphQL ecosystem."
/>
<DefinitionListItem
term="Thought Leadership"
definition="Position your company as a leader in the GraphQL space."
/>
<DefinitionListItem
term="Talent Acquisition"
definition="Meet and recruit top GraphQL developers and engineers."
/>
<DefinitionListItem
term="Product Feedback"
definition="Gather valuable feedback from the GraphQL community."
/>
<DefinitionListItem
term="Community Impact"
definition="Support and shape the future of GraphQL technology."
/>
</dl>
</div>
</section>
)
}

function DefinitionListItem({
className,
term,
definition,
}: {
className?: string
term: string
definition: string
}) {
return (
<div
className={clsx(
className,
"flex border-b border-neu-300 last:border-b-0 max-sm:flex-col",
)}
>
<dt className="typography-body-lg flex min-w-[320px] shrink-0 items-center whitespace-pre border-b border-neu-300 p-4 max-sm:w-full sm:border-b-0 sm:border-r">
{term}
</dt>
<dd className="typography-body-md flex items-center p-4">{definition}</dd>
</div>
)
}

function Stripes() {
return (
<div
role="presentation"
// prettier-ignore
// false positive
// eslint-disable-next-line tailwindcss/no-contradicting-classname
className="pointer-events-none absolute inset-0
[--start-1:hsl(var(--color-sec-lighter))]
[--end-1:hsl(hsl(320deg_100%_96%/.8)]
dark:[--start-1:hsl(var(--color-sec-lighter))]
dark:[--end-1:hsl(var(--color-pri-lighter)/.2)]

[--start-2:#FFEAF8]
[--end-2:hsl(var(--color-neu-0))]
dark:[--start-2:rgba(255,204,239,.1)]
dark:[--end-2:hsl(var(--color-pri-lighter)/.4)]

translate-y-12

[mask-size:120%]
3xl:[mask-size:2000px] 2xl:opacity-50
max-md:[mask-size:600%] max-md:opacity-50
"
style={{
maskImage: `url(${blurBlob.src})`,
WebkitMaskImage: `url(${blurBlob.src})`,
maskPosition: "center",
WebkitMaskPosition: "center",
maskRepeat: "no-repeat",
WebkitMaskRepeat: "no-repeat",
}}
>
<StripesDecoration
evenClassName="bg-[linear-gradient(180deg,var(--start-1)_-200%,var(--end-1)_100%)]"
oddClassName="bg-[linear-gradient(180deg,var(--start-2)_0%,var(--end-2)_100%)]"
/>
</div>
)
}
Loading
Loading