diff --git a/src/content/config.ts b/src/content/config.ts
index 33e828647..1dcd08359 100644
--- a/src/content/config.ts
+++ b/src/content/config.ts
@@ -1,4 +1,31 @@
import { defineCollection, reference, z } from "astro:content";
+import fs from "fs/promises";
+import path from "path";
+
+const CACHE_DIR = ".cache/data";
+
+async function ensureCacheDir() {
+ await fs.mkdir(CACHE_DIR, { recursive: true });
+}
+
+async function fetchWithCache(url: string, filename: string): Promise {
+ const filePath = path.join(CACHE_DIR, filename);
+
+ try {
+ // Return cached if available
+ const data = await fs.readFile(filePath);
+ console.log(`Fetch from cache: ${filePath}`);
+ return data;
+ } catch {
+ const res = await fetch(url);
+ if (!res.ok) throw new Error(`Failed to fetch: ${url}`);
+
+ const arrayBuffer = await res.arrayBuffer();
+ const buffer: Buffer = Buffer.from(arrayBuffer);
+ await fs.writeFile(filePath, new Uint8Array(buffer));
+ return buffer;
+ }
+}
const tiers = [
"Keystone",
@@ -54,27 +81,95 @@ const keynoters = defineCollection({
}),
});
+// Shared data fetching function
+async function getCollectionsData() {
+ // Only fetch if not already cached
+ await ensureCacheDir();
+
+ const speakersBuffer = await fetchWithCache(
+ "https://gist.githubusercontent.com/nikoshell/d8efd41f90961cc6298519c0eec04843/raw/d13a7b1d35f61be1773404e7faf8395dd4862313/speakers.json",
+ "speakers.json"
+ );
+
+ const sessionsBuffer = await fetchWithCache(
+ "https://gist.githubusercontent.com/egeakman/eddfb15f32ae805e8cfb4c5856ae304b/raw/466f8c20c17a9f6c5875f973acaec60e4e4d0fae/sessions.json",
+ "sessions.json"
+ );
+
+ const cachedSpeakersData = JSON.parse(speakersBuffer.toString("utf-8"));
+ const cachedSessionsData = JSON.parse(sessionsBuffer.toString("utf-8"));
+
+ // Create indexed versions for efficient lookups
+ const speakersById = Object.entries(cachedSpeakersData).reduce(
+ (acc, [id, speaker]: [string, any]) => {
+ acc[id] = { id, ...speaker };
+ return acc;
+ },
+ {} as Record
+ );
+
+ const sessionsById = Object.entries(cachedSessionsData).reduce(
+ (acc, [id, session]: [string, any]) => {
+ acc[id] = { id, ...session };
+ return acc;
+ },
+ {} as Record
+ );
+
+ return {
+ speakersData: cachedSpeakersData,
+ sessionsData: cachedSessionsData,
+ speakersById,
+ sessionsById,
+ };
+}
+
const speakers = defineCollection({
- type: "content",
+ loader: async (): Promise => {
+ const { speakersData, sessionsById } = await getCollectionsData();
+
+ return Object.values(speakersData).map((speaker: any) => ({
+ id: speaker.slug,
+ ...speaker,
+ submissions: (speaker.submissions || [])
+ .filter((sessionId: string) => sessionId in sessionsById)
+ .map((sessionId: string) => sessionsById[sessionId].slug),
+ }));
+ },
schema: z.object({
code: z.string(),
name: z.string(),
+ slug: z.string(),
avatar: z.string(),
+ biography: z.string().nullable(),
submissions: z.array(reference("sessions")),
affiliation: z.string().nullable(),
homepage: z.string().nullable(),
gitx: z.string().nullable(),
linkedin_url: z.string().url().nullable(),
mastodon_url: z.string().url().nullable(),
+ bluesky_url: z.string().url().nullable(),
twitter_url: z.string().url().nullable(),
}),
});
const sessions = defineCollection({
- type: "content",
+ loader: async (): Promise => {
+ const { sessionsData, speakersById } = await getCollectionsData();
+
+ return Object.values(sessionsData).map((session: any) => ({
+ id: session.slug,
+ ...session,
+ speakers: (session.speakers || [])
+ .filter((speakerId: string) => speakerId in speakersById)
+ .map((speakerId: string) => speakersById[speakerId].slug),
+ }));
+ },
schema: z.object({
code: z.string(),
title: z.string(),
+ slug: z.string(),
+ abstract: z.string().nullable(),
speakers: z.array(reference("speakers")),
session_type: z.string(),
track: z.string().nullable(),
@@ -85,7 +180,7 @@ const sessions = defineCollection({
.nullable(),
duration: z.string(),
level: z.enum(["beginner", "intermediate", "advanced"]),
- delivery: z.enum(["in-person", "remote"]),
+ delivery: z.enum(["in-person", "remote", ""]),
room: z.string().nullable(),
start: z.string().nullable(),
end: z.string().nullable(),
diff --git a/src/content/pages/overview.mdx b/src/content/pages/overview.mdx
new file mode 100644
index 000000000..48ffe7748
--- /dev/null
+++ b/src/content/pages/overview.mdx
@@ -0,0 +1,98 @@
+---
+title: Programme & Events Overview
+subtitle: Explore everything happening at EuroPython 2025
+---
+### Programme & Events Overview
+
+The conference is organised into three phases:
+
+1. **Monday & Tuesday (14 & 15 July):** Tutorial Days
+2. **Wednesday – Friday (16 – 18 July):** Main Conference Days
+3. **Saturday & Sunday (19 & 20 July):** Sprint Days
+
+You can look forward to:
+
+* ~120 talks
+* ~20 tutorials
+* 5–6 keynotes
+* Open spaces
+* 3 summits
+* Community organisers’ sessions
+* PyLadies workshops
+* Sprint projects
+* Tutorials for less-represented groups in tech
+* Beginner-friendly unconference day
+* Social and networking events
+
+---
+
+## Sessions
+
+### Talks
+Talks are 30–45 minute presentations, held across six parallel tracks during the Main Conference Days.
+
+### Tutorials
+Tutorials are 180-minute hands-on sessions focused on learning by doing, held during the Tutorial Days.
+
+#### List of sessions
+Can be found on the [sessions page](/sessions).
+
+---
+
+## Summits
+Summits are full-day, topic-focused unconference-style gatherings for in-depth discussions, held during the Tutorial Days.
+
+#### List of summits
+- [Rust Summit](/programme/rust-summit)
+- [WASM Summit](/programme/wasm-summit)
+- [C API Summit](/programme/c-api-summit)
+
+---
+
+## Open Spaces
+Open spaces are informal sessions where anyone can gather and discuss any topic. There will be a table at the venue — if there's a free slot, simply write down your topic, and others can join the conversation.
+
+#### List of spaces
+Will be published soon.
+
+---
+
+## Sprints
+Our sprint days offer a chance to contribute to open-source projects and collaborate with others in the community. Sprints take place over the weekend.
+
+#### List of participating projects
+Will be published soon.
+
+---
+
+## PyLadies Sessions
+Workshops organised by and for PyLadies, focused on supporting less-represented groups in tech.
+
+#### List of sessions
+Will be added soon.
+
+---
+
+## Beginner’s Day Unconference Space
+Running in parallel with the sprints, this unconference space is designed for beginners. It includes Q&A sessions, AMAs, and career-focused discussions with experienced professionals.
+
+#### List of sessions
+Will be added soon.
+
+---
+
+## Tutorials for Less-Represented Groups in Tech
+Introductory tutorials designed to help beginners from less-represented groups start learning programming.
+
+#### List of tutorials
+- Django Girls – more info coming soon
+- Humble Data – more info coming soon
+
+---
+
+## Events
+Our events bring the community together for fun and connection throughout the conference.
+
+#### List of events
+- Main social event – details coming soon
+- Speakers’ dinner – details coming soon
diff --git a/src/content/pages/programme/sessions.mdx b/src/content/pages/programme/sessions.mdx
deleted file mode 100644
index a556b2b6c..000000000
--- a/src/content/pages/programme/sessions.mdx
+++ /dev/null
@@ -1,162 +0,0 @@
----
-title: Sessions Preview EuroPython 2025
-subtitle: This is a preliminary list of the confirmed sessions for EuroPython 2025. The list will get modified until the final schedule is published.
----
-
-# Sessions preview
-
-The following sessions are a preliminary list of the confirmed proposals that
-will be part of the conference. The list will keep growing in the following
-days and some sessions might be replaced in case of them being withdrawn by the
-authors.
-
-Go to session type:
-* [Keynotes](#keynote)
-* [Talks](#talk)
-* [Talks (long session)](#talk-long-session)
-* [Posters](#poster)
-
-## Keynote
-
-* "Why it took 4 years to get a lock files specification" by Brett Cannon
-* "You Don’t Have to be a Compiler Engineer to Work on Python" by Savannah Ostrowski
-
-## Talk
-
-* "PyScript as Infrastructure: Running EduBlocks at Scale Without the Cost" by Josh Lowe
-* "EU AI Act: Unveiling Lesser-Known Aspects and Implementation Entities" by Adrin Jalali
-* "GPU performance or ease of use: why not both?" by Kamil Tokarski, Szymon Karpiński
-* "What does = do?" by Reuven M. Lerner
-* "One Screenreader to rule them all: using NVDA for Windows automation" by Ramón Corominas
-* "Put your pants on and make a monorepo" by Max Kahan
-* "Your Cookiecutter is Wrong" by Miloslav Pojman
-* "Is your programming curriculum inclusive for neurodivergents?" by Mykalin Jones
-* "QuackOSM & OvertureMaestro: Open geospatial data at your fingertips" by Kamil Raczycki
-* "Fearless Automation that Runs Anywhere with Python" by Padraic Calpin
-* "From Code to Circuits: Programming with MicroPython and Raspberry Pico 2W" by Nilo Ney Coutinho Menezes
-* "Physics-Informed ML: Fusing Scientific Laws with AI" by Mehul Goyal
-* "Explaining the 5 types of database and how to choose between them" by Tibs
-* "A PEP Talk: Adventures As the Inaugural PyPI Support Specialist" by Maria Ashna
-* "dbt-score: continuous integration for dbt metadata" by Matthieu Caneill, Jochem van Dooren
-* "You Came to a Python Conference. Now, Go Do a PR Review!" by Samiul Huque
-* "A Pythonic semantic search" by Paolo Melchiorre
-* "How to Stop an Epidemic using the Atomica Python Tool" by Eloisa Pérez Bennetts
-* "Hacking LLMs: An Introduction to Mechanistic Interpretability" by Jenny Vega
-* "How to contribute to Python docs in your own language" by Marco Richetta
-* "End to End with Testcontainers and Playwright" by Vemund Mehl Santi
-* "Snapshot Testing: A New Era of Reliability" by Matthieu Rigal
-* "Memory Efficient Iteration with Python's itertools- A Deep Dive" by Kalyan Prasad
-* "Django and HTMX: Patterns to Success" by Lucas Pires
-* "Godot & Python: open source in game development" by Diego Díaz Morón
-* "From Trees To Transformers: Adopting Deep Learning for Ranking" by Theodore Meynard, Mihail
-* "Pydantic, Everywhere, All at Once" by Šimon Podhajský
-* "Python, Politics, and Public Health" by Gauden Galea
-* "Exploring the CPython JIT" by Diego Russo
-* "Broken `__slots__` are a silent performance killer—Let's fix them!" by Arie Bovenberg
-* "When in practice is Python performance an issue? Facts and myths." by Sebastian Buczyński
-* "ORMs: A Bridge to Efficient Database Interactions with Python" by Velda Kiara
-* "To the Moon and back: Archiving my dream open source project" by Juan Luis Cano Rodríguez
-* "Unlocking Hidden Power of Conda with Pixi" by Ruben Arts, Julian Hofer
-* "Meet Marimo, the next-gen Notebook" by Sven Arends
-* "Using Postgres schemas to separate data of your SaaS application in Django" by Mikuláš Poul
-* "Turbocharge your Python test suite today! 🚀" by Konstantinos Papadopoulos
-* "What to expect when you are expecting Free Threading" by Jimena Bermúdez
-* "Running every street in Paris with Python and PostGIS" by Vinayak Mehta
-* "Building my own (accurate!) Spotify Wrapped" by Iulia Feroli
-* "Type Hints in Real-World Projects: Maintenance & Improvement" by Koudai Aono
-* "How to deal with toxic people" by Gina Häußge
-* "Adaptive Inference: Why Taking a Ferrari for Groceries is a Terrible Idea" by Steven Kolawole
-* "Beyond the Code: Manipulating Bytecode and Building Community" by Kir Chou
-* "Design Patterns: Build better software from day one" by Marine Guyot
-* "Snake oil - or tools & tricks for making Python run smoother" by Sindre Nistad
-* "Behind the Scenes: PSF Infrastructure and How You Can Contribute" by Jacob Coffee
-* "MIDI, those cheesy sounds from the 90s? Wrong! Symbolic music vs Python" by Mateusz Modrzejewski
-* "Automating myself out of an unloved project with Python, n8n and Telegram" by Sebastian Witowski
-* "Anatomy of a Python OpenTelemetry instrumentation" by Riccardo Magliocchetti
-* "Continuous Documentation: basics and advanced techniques" by Anastasiia Tymoshchuk
-* "WASM and Python: The Future of Serverless Computing" by Kumar Anirudha, Farhaan Bukhsh
-* "Python Config That Will Give You Chills (In a Good Way, I Promise!)" by Grzegorz Kocjan
-* "Flying Free: data analysis with Python for aeronautical planning" by Joaquín Rayado
-* "Mentoring Both Ways: Helping Others While Leveling Up Yourself!" by Manivannan Selvaraj
-* "A tour of (some) Python JIT compilers" by Stepan Sindelar
-* "Data Governance 101: Stop Firefighting, Start Engineering" by Kateřina Ščavnická
-* "Efficient Caching in Python: From Local to External Solutions" by Akshita Gupta
-* "The Evolution of Advanced Python Monitoring" by May Walter
-* "Python on the Pitch: How Germany will win World Cup 2026" by Ruslan Korniichuk
-* "Building a new tail-calling interpreter for Python" by Ken Jin
-* "Microdot, the impossibly small web framework for Python and MicroPython." by Miguel Grinberg
-* "From Notes to Codes - Python-Driven AI for Efficient Medical Coding" by Reyha Verma
-* "Building a NoGIL Load Balancer in Python in 30 minutes" by Alvaro Duran
-* "Good Practices for Testing Web User Interfaces" by Ashish Gupta, Jan Jašek
-* "What comes after Rust in the Python ecosystem?" by Cristián Maureira-Fredes
-* "Offline Disaster Relief Coordination with OpenStreetMap and FastAPI" by Jannis Lübbe
-* "Typing at scale: statically type-checking a large codebase" by Alan Franzoni
-* "Testing the Tests - Assess and Improve Your Python Testing Code" by Stefan Bärisch
-* "Prenatal diagnosis of genetic diseases using Python" by Helena Gómez Pozo, Marina Moro López
-* "Death by a Thousand API Versions" by Stanislav Zmiev
-* "The Network Next Door: How Connections Shape the World Around Us" by Kshitijaa Jaglan
-* "Programming hardware displays the easy way - using MicroPython and LVGL" by Marc-André Lemburg
-* "Bridging the gap: Viewing your project through a downstream packager's lens" by Karolina Surma
-* "How Open-Source Software empowers Computer Science education in schools." by Robson Kanhalelo
-* "How Python's Evolving Type Hints Help You Work Smarter, Not Harder." by Abigail Afi Gbadago
-* "Terraform CDK in Python: Where Infrastructure Meets Code" by Yuliia Barabash
-* "Fixtures meets parameters: Writing efficient, elegant and reusable tests" by Anupama Tiruvaipati
-* "From Grilling to Growing: Python Interviews as Shared Learning for All" by Artur Patoka
-* "Uncovering the magic of implementing a new Python syntax feature" by Lysandros Nikolaou
-* "Hold on! You have a data team in PyCon Taiwan!" by Wei Lee
-* "Zero-Drama Upgrades: Real-World Tactics for Major Python Migrations" by Alejandro Cabello Jiménez
-* "Going beyond Parquet: Handling large-scale datasets with Iceberg and Dask" by Patrick Hoefler
-* "Breaking HTTP Boundaries: ASGI to build a fleet management system in Python" by Kirill Druzhinin
-* "Fairlearn:practical approach to assessing and mitigating harm in AI systems" by Tamara Atanasoska
-* "Navigating the mesh: Istio for Python applications" by Israel Blancas
-* "Performance improvements in 3.14 and maybe 3.15" by Mark Shannon
-* "Refactoring and Maintaing Software : Building code you won't hate tomorrow" by Bojan Miletic
-* "Is Prompt Engineering Dead? How Auto-Optimization is Changing the Game" by Iryna Kondrashchenko, Oleh Kostromin
-
-## Talk (long session)
-
-* "Computer Vision Data Version Control and Reproducibility at Scale" by Tal Sofer, Itai Gilo
-* "Teamwork makes the dream work" by Sheena
-* "Accelerating privacy-enhancing data processing" by Florian Stefan, Anna Schwarz
-* "Indico: the 20 year history and evolution of an open-source project at CERN" by Tomas Roun, Dominic Hollis
-* "Unveiling Data's Hidden Shape with TDA in Python (GUDHI)" by Jessica Randall
-* "Origami Speed Championships: Fast Polygon Triangulation in Python" by Grzegorz Bokota
-* "Parallel programming and Cython" by David Woods
-* "Let's talk: Communication & Consensusing Building in Open-Source" by Travis Hathaway
-* "From Notebook to Production: Deploying ML Models with Confidence." by Ariane Djeupang
-* "A new safe external debugger interface for CPython" by Pablo Galindo Salgado
-* "Async Python: Concurrency Without the Headaches" by Mateusz Zaremba, Krzysztof Wilczyński
-* "Intuition vs. Reality: Surprising Truths in Python Performance" by Arthur Pastel, Adrien Cacciaguerra
-* "Myths and fairy tales around Python performance" by Antonio Cuni
-* "How to use Python on a RPi to develop a custom headless guitar FX box" by Matthieu Amiguet
-* "Python, SQLAlchemy, and SQL: A Powerful Trilogy for Data Scientists" by Elvis Kwabena Asare Nkrumah
-* "Sharing is caring: Efficient Data Exchange with pyarrow" by Raúl Cumplido, Alenka Frim
-* "It's All About Time ⏰ - What developers need to know about time" by Petter Salminen
-
-## Tutorial
-
-* "Setting Up Reliable CI/CD Pipelines with Python, K8s & Testcontainers" by Koteswara Rao Vellanki
-* "GIL-free Python and the GPU: hands-on experience" by Michał Szołucha, Rostan Tabet
-* "The Mighty Dot - Customize Attribute Access with Descriptors" by Mike Müller
-* "Rambo Python" by Julien LENORMAND
-* "pytest - simple, rapid and fun testing with Python" by Florian Bruhin
-* "Accelerating Scientific Python: JAX, Numba, and Ray in Action" by Jakub Urban
-* "Writing Python modules in Rust - PyO3 101" by Cheuk Ting Ho
-* "Mastering decorators: the cherry on top of your functions" by Rodrigo Girão Serrão
-* "Building a cross-platform app with BeeWare" by Russell Keith-Magee
-* "Practical PyScript" by Nicholas H.Tollervey
-* "Python and Data Storytelling to create and deliver better presentations" by Sebastián Flores
-* "Speaking at EuroPython (or your favorite conference)? Yes, you can!" by Vinícius Gubiani Ferreira
-* "“Building Privacy-Focused Vector Search Applications: Hands-On Guide to Gen" by Shivay Lamba
-* "Cleaner Code, Better Queries: SQLAlchemy, ORMs and asyncio" by Aya Elsayed, Rhythm Patel
-* "Efficient Query Routing using Agentic RAG" by Tarun Jain
-* "Understand Git and Never Break a Repo Again" by Themistoklis Spanoudis
-
-## Poster
-
-* "Psychological Model for Mapping and Prediction of Stress Among Students" by Oladapo Kayode Abiodun, Oluwakemi Jacobs
-* "PySchool: Introducing High School Students to the World of Python" by Sebastián Flores
-* "Preserving Culture with Python: AI plays Ayo, a Traditional Nigerian Game" by Kayode Makinde
-* "Portable data-parallel Python extensions using oneAPI" by Nikita Grigorian
-* "ClimateML: Machine Learning for Climate Model Downscaling" by Neeraj Pandey
-* "Exploring LLM latency" by Pavel Král
diff --git a/src/content/speakers/.gitkeep b/src/content/speakers/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/data/links.json b/src/data/links.json
index fa02dcbd8..0a552df3c 100644
--- a/src/data/links.json
+++ b/src/data/links.json
@@ -4,8 +4,12 @@
"name": "Programme",
"items": [
{
- "name": "Sessions Previews",
- "path": "/programme/sessions"
+ "name": "Overview",
+ "path": "/overview"
+ },
+ {
+ "name": "List of Sessions",
+ "path": "/sessions"
},
{
"name": "Tracks",
@@ -19,6 +23,10 @@
"name": "Community Voting",
"path": "/programme/voting"
},
+ {
+ "name": "List of Speakers",
+ "path": "/speakers"
+ },
{
"name": "Speaker Mentorship",
"path": "/programme/mentorship"
diff --git a/src/pages/session/[slug].astro b/src/pages/session/[slug].astro
index a04265334..c467c9d15 100644
--- a/src/pages/session/[slug].astro
+++ b/src/pages/session/[slug].astro
@@ -5,11 +5,13 @@ import Prose from "../../components/prose/prose.astro";
import { Separator } from "../../components/separator/separator";
import { formatInTimeZone } from "date-fns-tz";
import { YouTube } from "@astro-community/astro-embed-youtube";
+import { Picture } from "astro:assets";
+import Markdown from "@ui/Markdown.astro";
export async function getStaticPaths() {
const sessions = await getCollection("sessions");
return sessions.map((entry) => ({
- params: { slug: entry.slug },
+ params: { slug: entry.id},
props: { entry },
}));
}
@@ -18,15 +20,9 @@ export async function getStaticPaths() {
const sessions = await getCollection("sessions");
const { entry } = Astro.props;
-const { Content } = await entry.render();
const speakers = await getEntries(entry.data.speakers);
-for (const speaker of speakers) {
- // @ts-ignore
- speaker.Content = (await speaker.render()).Content;
-}
-
// Resolve session codes to session data
const resolveSessions = (codes: string[]) =>
codes.map((code) => sessions.find((s) => s?.data?.code === code));
@@ -106,7 +102,7 @@ const nextSessionsOrdered = sameRoomNextSession