diff --git a/astro.config.mjs b/astro.config.mjs index fe463afba..b180cd7e0 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -177,4 +177,7 @@ export default defineConfig({ prefetch: { prefetchAll: false, }, + devToolbar: { + enabled: false, + }, }); diff --git a/public/media/speakers/social-abhik-sarkar.png b/public/media/speakers/social-abhik-sarkar.png new file mode 100644 index 000000000..c43ebeb11 Binary files /dev/null and b/public/media/speakers/social-abhik-sarkar.png differ diff --git a/public/media/speakers/social-abhimanyu-singh-shekhawat.png b/public/media/speakers/social-abhimanyu-singh-shekhawat.png new file mode 100644 index 000000000..99a191f4f Binary files /dev/null and b/public/media/speakers/social-abhimanyu-singh-shekhawat.png differ diff --git a/public/media/speakers/social-abigail-afi-gbadago.png b/public/media/speakers/social-abigail-afi-gbadago.png new file mode 100644 index 000000000..d37e09c69 Binary files /dev/null and b/public/media/speakers/social-abigail-afi-gbadago.png differ diff --git a/public/media/speakers/social-adam-gorgon.png b/public/media/speakers/social-adam-gorgon.png new file mode 100644 index 000000000..9fd0a1cc3 Binary files /dev/null and b/public/media/speakers/social-adam-gorgon.png differ diff --git a/public/media/speakers/social-alejandro-cabello-jimenez.png b/public/media/speakers/social-alejandro-cabello-jimenez.png new file mode 100644 index 000000000..bd6165139 Binary files /dev/null and b/public/media/speakers/social-alejandro-cabello-jimenez.png differ diff --git a/public/media/speakers/social-aleksander.png b/public/media/speakers/social-aleksander.png new file mode 100644 index 000000000..2adf9e25d Binary files /dev/null and b/public/media/speakers/social-aleksander.png differ diff --git a/public/media/speakers/social-alenka-frim.png b/public/media/speakers/social-alenka-frim.png new file mode 100644 index 000000000..7779e9fce Binary files /dev/null and b/public/media/speakers/social-alenka-frim.png differ diff --git a/public/media/speakers/social-anwesha-das.png b/public/media/speakers/social-anwesha-das.png new file mode 100644 index 000000000..69d07e443 Binary files /dev/null and b/public/media/speakers/social-anwesha-das.png differ diff --git a/public/media/speakers/social-ariel-ortiz.png b/public/media/speakers/social-ariel-ortiz.png new file mode 100644 index 000000000..f89a772a3 Binary files /dev/null and b/public/media/speakers/social-ariel-ortiz.png differ diff --git a/public/media/speakers/social-bryce-adelstein-lelbach.png b/public/media/speakers/social-bryce-adelstein-lelbach.png new file mode 100644 index 000000000..2246faf5f Binary files /dev/null and b/public/media/speakers/social-bryce-adelstein-lelbach.png differ diff --git a/public/media/speakers/social-carlos-a-aranibar.png b/public/media/speakers/social-carlos-a-aranibar.png new file mode 100644 index 000000000..5c6d1774b Binary files /dev/null and b/public/media/speakers/social-carlos-a-aranibar.png differ diff --git a/public/media/speakers/social-cheuk-ting-ho.png b/public/media/speakers/social-cheuk-ting-ho.png new file mode 100644 index 000000000..1f4750882 Binary files /dev/null and b/public/media/speakers/social-cheuk-ting-ho.png differ diff --git a/public/media/speakers/social-christian-leitold.png b/public/media/speakers/social-christian-leitold.png new file mode 100644 index 000000000..49ce1f38d Binary files /dev/null and b/public/media/speakers/social-christian-leitold.png differ diff --git a/public/media/speakers/social-claudiu-belu.png b/public/media/speakers/social-claudiu-belu.png new file mode 100644 index 000000000..a9e9401f9 Binary files /dev/null and b/public/media/speakers/social-claudiu-belu.png differ diff --git a/public/media/speakers/social-cody-fincher.png b/public/media/speakers/social-cody-fincher.png new file mode 100644 index 000000000..4ca3a7c32 Binary files /dev/null and b/public/media/speakers/social-cody-fincher.png differ diff --git a/public/media/speakers/social-cristian-maureira-fredes.png b/public/media/speakers/social-cristian-maureira-fredes.png new file mode 100644 index 000000000..17f602d00 Binary files /dev/null and b/public/media/speakers/social-cristian-maureira-fredes.png differ diff --git a/public/media/speakers/social-damian-wysocki.png b/public/media/speakers/social-damian-wysocki.png new file mode 100644 index 000000000..72b4b75fe Binary files /dev/null and b/public/media/speakers/social-damian-wysocki.png differ diff --git a/public/media/speakers/social-daniel-vahla.png b/public/media/speakers/social-daniel-vahla.png new file mode 100644 index 000000000..27078c5bd Binary files /dev/null and b/public/media/speakers/social-daniel-vahla.png differ diff --git a/public/media/speakers/social-daria-korsakova.png b/public/media/speakers/social-daria-korsakova.png new file mode 100644 index 000000000..96be618e9 Binary files /dev/null and b/public/media/speakers/social-daria-korsakova.png differ diff --git a/public/media/speakers/social-david-rousset.png b/public/media/speakers/social-david-rousset.png new file mode 100644 index 000000000..5a1e9f9ae Binary files /dev/null and b/public/media/speakers/social-david-rousset.png differ diff --git a/public/media/speakers/social-david-vaz.png b/public/media/speakers/social-david-vaz.png new file mode 100644 index 000000000..9d2e83655 Binary files /dev/null and b/public/media/speakers/social-david-vaz.png differ diff --git a/public/media/speakers/social-dawn-wages.png b/public/media/speakers/social-dawn-wages.png new file mode 100644 index 000000000..b312201a9 Binary files /dev/null and b/public/media/speakers/social-dawn-wages.png differ diff --git a/public/media/speakers/social-deb-nicholson.png b/public/media/speakers/social-deb-nicholson.png new file mode 100644 index 000000000..73e9ec0e5 Binary files /dev/null and b/public/media/speakers/social-deb-nicholson.png differ diff --git a/public/media/speakers/social-deborah-e-danjuma.png b/public/media/speakers/social-deborah-e-danjuma.png new file mode 100644 index 000000000..fee46e395 Binary files /dev/null and b/public/media/speakers/social-deborah-e-danjuma.png differ diff --git a/public/media/speakers/social-diego-russo.png b/public/media/speakers/social-diego-russo.png new file mode 100644 index 000000000..05d48e650 Binary files /dev/null and b/public/media/speakers/social-diego-russo.png differ diff --git a/public/media/speakers/social-domagoj-maric.png b/public/media/speakers/social-domagoj-maric.png new file mode 100644 index 000000000..284edf9eb Binary files /dev/null and b/public/media/speakers/social-domagoj-maric.png differ diff --git a/public/media/speakers/social-eleni-tokmaktsi.png b/public/media/speakers/social-eleni-tokmaktsi.png new file mode 100644 index 000000000..2e70f7483 Binary files /dev/null and b/public/media/speakers/social-eleni-tokmaktsi.png differ diff --git a/public/media/speakers/social-emmanuel-ugwu.png b/public/media/speakers/social-emmanuel-ugwu.png new file mode 100644 index 000000000..3be4a4edf Binary files /dev/null and b/public/media/speakers/social-emmanuel-ugwu.png differ diff --git a/public/media/speakers/social-evan-kohilas.png b/public/media/speakers/social-evan-kohilas.png new file mode 100644 index 000000000..f8187bb4f Binary files /dev/null and b/public/media/speakers/social-evan-kohilas.png differ diff --git a/public/media/speakers/social-farhaan-bukhsh.png b/public/media/speakers/social-farhaan-bukhsh.png new file mode 100644 index 000000000..b7b5253b1 Binary files /dev/null and b/public/media/speakers/social-farhaan-bukhsh.png differ diff --git a/public/media/speakers/social-felipe-arruda-pontes.png b/public/media/speakers/social-felipe-arruda-pontes.png new file mode 100644 index 000000000..e7796cbc4 Binary files /dev/null and b/public/media/speakers/social-felipe-arruda-pontes.png differ diff --git a/public/media/speakers/social-filip-makraduli.png b/public/media/speakers/social-filip-makraduli.png new file mode 100644 index 000000000..b863acc46 Binary files /dev/null and b/public/media/speakers/social-filip-makraduli.png differ diff --git a/public/media/speakers/social-florian-freitag.png b/public/media/speakers/social-florian-freitag.png new file mode 100644 index 000000000..2bdfcf755 Binary files /dev/null and b/public/media/speakers/social-florian-freitag.png differ diff --git a/public/media/speakers/social-francesco-lucantoni.png b/public/media/speakers/social-francesco-lucantoni.png new file mode 100644 index 000000000..629ee563f Binary files /dev/null and b/public/media/speakers/social-francesco-lucantoni.png differ diff --git a/public/media/speakers/social-freya-bruhin.png b/public/media/speakers/social-freya-bruhin.png new file mode 100644 index 000000000..8fcbe5cf0 Binary files /dev/null and b/public/media/speakers/social-freya-bruhin.png differ diff --git a/public/media/speakers/social-fridtjof-stoldt.png b/public/media/speakers/social-fridtjof-stoldt.png new file mode 100644 index 000000000..4de0fc002 Binary files /dev/null and b/public/media/speakers/social-fridtjof-stoldt.png differ diff --git a/public/media/speakers/social-gaffiot-jonathan.png b/public/media/speakers/social-gaffiot-jonathan.png new file mode 100644 index 000000000..379d6f144 Binary files /dev/null and b/public/media/speakers/social-gaffiot-jonathan.png differ diff --git a/public/media/speakers/social-giovanni-barillari.png b/public/media/speakers/social-giovanni-barillari.png new file mode 100644 index 000000000..f1cf14b59 Binary files /dev/null and b/public/media/speakers/social-giovanni-barillari.png differ diff --git a/public/media/speakers/social-gleb-khmyznikov.png b/public/media/speakers/social-gleb-khmyznikov.png new file mode 100644 index 000000000..5cfea85d5 Binary files /dev/null and b/public/media/speakers/social-gleb-khmyznikov.png differ diff --git a/public/media/speakers/social-goutam-tiwari.png b/public/media/speakers/social-goutam-tiwari.png new file mode 100644 index 000000000..e0e313b2e Binary files /dev/null and b/public/media/speakers/social-goutam-tiwari.png differ diff --git a/public/media/speakers/social-gracjan-adamus.png b/public/media/speakers/social-gracjan-adamus.png new file mode 100644 index 000000000..24cd78e17 Binary files /dev/null and b/public/media/speakers/social-gracjan-adamus.png differ diff --git a/public/media/speakers/social-grzegorz-bokota.png b/public/media/speakers/social-grzegorz-bokota.png new file mode 100644 index 000000000..bb1b7a334 Binary files /dev/null and b/public/media/speakers/social-grzegorz-bokota.png differ diff --git a/public/media/speakers/social-grzegorz-kocjan.png b/public/media/speakers/social-grzegorz-kocjan.png new file mode 100644 index 000000000..1587ac3de Binary files /dev/null and b/public/media/speakers/social-grzegorz-kocjan.png differ diff --git a/public/media/speakers/social-ivan-markeev.png b/public/media/speakers/social-ivan-markeev.png new file mode 100644 index 000000000..dcdbd4b9d Binary files /dev/null and b/public/media/speakers/social-ivan-markeev.png differ diff --git a/public/media/speakers/social-ivana-kellyer.png b/public/media/speakers/social-ivana-kellyer.png new file mode 100644 index 000000000..619a1483e Binary files /dev/null and b/public/media/speakers/social-ivana-kellyer.png differ diff --git a/public/media/speakers/social-jan-bjorge.png b/public/media/speakers/social-jan-bjorge.png new file mode 100644 index 000000000..db8fda9df Binary files /dev/null and b/public/media/speakers/social-jan-bjorge.png differ diff --git a/public/media/speakers/social-jan-koprowski.png b/public/media/speakers/social-jan-koprowski.png new file mode 100644 index 000000000..49cc54ba1 Binary files /dev/null and b/public/media/speakers/social-jan-koprowski.png differ diff --git a/public/media/speakers/social-jan-musilek.png b/public/media/speakers/social-jan-musilek.png new file mode 100644 index 000000000..bd7809113 Binary files /dev/null and b/public/media/speakers/social-jan-musilek.png differ diff --git a/public/media/speakers/social-jan-smitka.png b/public/media/speakers/social-jan-smitka.png new file mode 100644 index 000000000..616e03694 Binary files /dev/null and b/public/media/speakers/social-jan-smitka.png differ diff --git a/public/media/speakers/social-jaroslaw-smietanka.png b/public/media/speakers/social-jaroslaw-smietanka.png new file mode 100644 index 000000000..480758340 Binary files /dev/null and b/public/media/speakers/social-jaroslaw-smietanka.png differ diff --git a/public/media/speakers/social-jenny-vega.png b/public/media/speakers/social-jenny-vega.png new file mode 100644 index 000000000..c50b3f183 Binary files /dev/null and b/public/media/speakers/social-jenny-vega.png differ diff --git a/public/media/speakers/social-johannes-kolbe.png b/public/media/speakers/social-johannes-kolbe.png new file mode 100644 index 000000000..af9226a0c Binary files /dev/null and b/public/media/speakers/social-johannes-kolbe.png differ diff --git a/public/media/speakers/social-jon-nordby.png b/public/media/speakers/social-jon-nordby.png new file mode 100644 index 000000000..82767bf0b Binary files /dev/null and b/public/media/speakers/social-jon-nordby.png differ diff --git a/public/media/speakers/social-jukka-lehtosalo.png b/public/media/speakers/social-jukka-lehtosalo.png new file mode 100644 index 000000000..396295e73 Binary files /dev/null and b/public/media/speakers/social-jukka-lehtosalo.png differ diff --git a/public/media/speakers/social-julien-courtes.png b/public/media/speakers/social-julien-courtes.png new file mode 100644 index 000000000..b1b2497de Binary files /dev/null and b/public/media/speakers/social-julien-courtes.png differ diff --git a/public/media/speakers/social-julien-lenormand.png b/public/media/speakers/social-julien-lenormand.png new file mode 100644 index 000000000..ff91dacd4 Binary files /dev/null and b/public/media/speakers/social-julien-lenormand.png differ diff --git a/public/media/speakers/social-kamil-kulig.png b/public/media/speakers/social-kamil-kulig.png new file mode 100644 index 000000000..27241072a Binary files /dev/null and b/public/media/speakers/social-kamil-kulig.png differ diff --git a/public/media/speakers/social-karen-jex.png b/public/media/speakers/social-karen-jex.png new file mode 100644 index 000000000..b1eaa5f4e Binary files /dev/null and b/public/media/speakers/social-karen-jex.png differ diff --git a/public/media/speakers/social-katie-bickford.png b/public/media/speakers/social-katie-bickford.png new file mode 100644 index 000000000..beeda9f22 Binary files /dev/null and b/public/media/speakers/social-katie-bickford.png differ diff --git a/public/media/speakers/social-ken-jin.png b/public/media/speakers/social-ken-jin.png new file mode 100644 index 000000000..4af0a82ef Binary files /dev/null and b/public/media/speakers/social-ken-jin.png differ diff --git a/public/media/speakers/social-koudai-aono.png b/public/media/speakers/social-koudai-aono.png new file mode 100644 index 000000000..132dcacc0 Binary files /dev/null and b/public/media/speakers/social-koudai-aono.png differ diff --git a/public/media/speakers/social-kuldeep-pisda.png b/public/media/speakers/social-kuldeep-pisda.png new file mode 100644 index 000000000..b41a0b3cd Binary files /dev/null and b/public/media/speakers/social-kuldeep-pisda.png differ diff --git a/public/media/speakers/social-larry-hastings.png b/public/media/speakers/social-larry-hastings.png new file mode 100644 index 000000000..23ef77de4 Binary files /dev/null and b/public/media/speakers/social-larry-hastings.png differ diff --git a/public/media/speakers/social-laura-summers.png b/public/media/speakers/social-laura-summers.png new file mode 100644 index 000000000..5d7931bac Binary files /dev/null and b/public/media/speakers/social-laura-summers.png differ diff --git a/public/media/speakers/social-lokko-joyce-dzifa.png b/public/media/speakers/social-lokko-joyce-dzifa.png new file mode 100644 index 000000000..85f2b5cdd Binary files /dev/null and b/public/media/speakers/social-lokko-joyce-dzifa.png differ diff --git a/public/media/speakers/social-lysandros-nikolaou.png b/public/media/speakers/social-lysandros-nikolaou.png new file mode 100644 index 000000000..ba9d0fcfd Binary files /dev/null and b/public/media/speakers/social-lysandros-nikolaou.png differ diff --git a/public/media/speakers/social-maciej-sobczak.png b/public/media/speakers/social-maciej-sobczak.png new file mode 100644 index 000000000..aa286912b Binary files /dev/null and b/public/media/speakers/social-maciej-sobczak.png differ diff --git a/public/media/speakers/social-mai-gimenez.png b/public/media/speakers/social-mai-gimenez.png new file mode 100644 index 000000000..d4e8a393b Binary files /dev/null and b/public/media/speakers/social-mai-gimenez.png differ diff --git a/public/media/speakers/social-malcolm-smith.png b/public/media/speakers/social-malcolm-smith.png new file mode 100644 index 000000000..6c4d21c31 Binary files /dev/null and b/public/media/speakers/social-malcolm-smith.png differ diff --git a/public/media/speakers/social-manivannan-selvaraj.png b/public/media/speakers/social-manivannan-selvaraj.png new file mode 100644 index 000000000..afa7b025d Binary files /dev/null and b/public/media/speakers/social-manivannan-selvaraj.png differ diff --git a/public/media/speakers/social-marc-andre-lemburg.png b/public/media/speakers/social-marc-andre-lemburg.png new file mode 100644 index 000000000..b0f7df812 Binary files /dev/null and b/public/media/speakers/social-marc-andre-lemburg.png differ diff --git a/public/media/speakers/social-marcelo-trylesinski.png b/public/media/speakers/social-marcelo-trylesinski.png new file mode 100644 index 000000000..c384d432f Binary files /dev/null and b/public/media/speakers/social-marcelo-trylesinski.png differ diff --git a/public/media/speakers/social-marco-grossi.png b/public/media/speakers/social-marco-grossi.png new file mode 100644 index 000000000..2e32bff7e Binary files /dev/null and b/public/media/speakers/social-marco-grossi.png differ diff --git a/public/media/speakers/social-maria-ashna.png b/public/media/speakers/social-maria-ashna.png new file mode 100644 index 000000000..3974a7c59 Binary files /dev/null and b/public/media/speakers/social-maria-ashna.png differ diff --git a/public/media/speakers/social-maria-lowas-rzechonek.png b/public/media/speakers/social-maria-lowas-rzechonek.png new file mode 100644 index 000000000..d5dcc6592 Binary files /dev/null and b/public/media/speakers/social-maria-lowas-rzechonek.png differ diff --git a/public/media/speakers/social-mario-garcia.png b/public/media/speakers/social-mario-garcia.png new file mode 100644 index 000000000..0277b6a6a Binary files /dev/null and b/public/media/speakers/social-mario-garcia.png differ diff --git a/public/media/speakers/social-mateusz-modrzejewski.png b/public/media/speakers/social-mateusz-modrzejewski.png new file mode 100644 index 000000000..d842120eb Binary files /dev/null and b/public/media/speakers/social-mateusz-modrzejewski.png differ diff --git a/public/media/speakers/social-mateusz-sokol.png b/public/media/speakers/social-mateusz-sokol.png new file mode 100644 index 000000000..f35630c87 Binary files /dev/null and b/public/media/speakers/social-mateusz-sokol.png differ diff --git a/public/media/speakers/social-michael-seifert.png b/public/media/speakers/social-michael-seifert.png new file mode 100644 index 000000000..846b49cb2 Binary files /dev/null and b/public/media/speakers/social-michael-seifert.png differ diff --git a/public/media/speakers/social-michal-karzynski.png b/public/media/speakers/social-michal-karzynski.png new file mode 100644 index 000000000..2b94066c9 Binary files /dev/null and b/public/media/speakers/social-michal-karzynski.png differ diff --git a/public/media/speakers/social-mike-fiedler.png b/public/media/speakers/social-mike-fiedler.png new file mode 100644 index 000000000..992c006ab Binary files /dev/null and b/public/media/speakers/social-mike-fiedler.png differ diff --git a/public/media/speakers/social-mike-muller.png b/public/media/speakers/social-mike-muller.png new file mode 100644 index 000000000..f22a9bb41 Binary files /dev/null and b/public/media/speakers/social-mike-muller.png differ diff --git a/public/media/speakers/social-mohamed-elmaghraby.png b/public/media/speakers/social-mohamed-elmaghraby.png new file mode 100644 index 000000000..3918a5b81 Binary files /dev/null and b/public/media/speakers/social-mohamed-elmaghraby.png differ diff --git a/public/media/speakers/social-mohit-kumar-vyas.png b/public/media/speakers/social-mohit-kumar-vyas.png new file mode 100644 index 000000000..66f69811f Binary files /dev/null and b/public/media/speakers/social-mohit-kumar-vyas.png differ diff --git a/public/media/speakers/social-nathan-goldbaum.png b/public/media/speakers/social-nathan-goldbaum.png new file mode 100644 index 000000000..d4ccd9495 Binary files /dev/null and b/public/media/speakers/social-nathan-goldbaum.png differ diff --git a/public/media/speakers/social-nicholas-h-tollervey.png b/public/media/speakers/social-nicholas-h-tollervey.png new file mode 100644 index 000000000..0d8b30429 Binary files /dev/null and b/public/media/speakers/social-nicholas-h-tollervey.png differ diff --git a/public/media/speakers/social-nikita-karamov.png b/public/media/speakers/social-nikita-karamov.png new file mode 100644 index 000000000..09d3cdcbe Binary files /dev/null and b/public/media/speakers/social-nikita-karamov.png differ diff --git a/public/media/speakers/social-nikita-smirnov.png b/public/media/speakers/social-nikita-smirnov.png new file mode 100644 index 000000000..b7136e6cb Binary files /dev/null and b/public/media/speakers/social-nikita-smirnov.png differ diff --git a/public/media/speakers/social-nitish.png b/public/media/speakers/social-nitish.png new file mode 100644 index 000000000..831946f51 Binary files /dev/null and b/public/media/speakers/social-nitish.png differ diff --git a/public/media/speakers/social-oladapo-jesusemilore-jael.png b/public/media/speakers/social-oladapo-jesusemilore-jael.png new file mode 100644 index 000000000..a3d144698 Binary files /dev/null and b/public/media/speakers/social-oladapo-jesusemilore-jael.png differ diff --git a/public/media/speakers/social-oladapo-kayode-abiodun.png b/public/media/speakers/social-oladapo-kayode-abiodun.png new file mode 100644 index 000000000..5facbe799 Binary files /dev/null and b/public/media/speakers/social-oladapo-kayode-abiodun.png differ diff --git a/public/media/speakers/social-olha-poliuliakh.png b/public/media/speakers/social-olha-poliuliakh.png new file mode 100644 index 000000000..04a56128a Binary files /dev/null and b/public/media/speakers/social-olha-poliuliakh.png differ diff --git a/public/media/speakers/social-pablo-galindo-salgado.png b/public/media/speakers/social-pablo-galindo-salgado.png new file mode 100644 index 000000000..053a37c27 Binary files /dev/null and b/public/media/speakers/social-pablo-galindo-salgado.png differ diff --git a/public/media/speakers/social-petr-viktorin.png b/public/media/speakers/social-petr-viktorin.png new file mode 100644 index 000000000..1db365e81 Binary files /dev/null and b/public/media/speakers/social-petr-viktorin.png differ diff --git a/public/media/speakers/social-piotr-gredowski.png b/public/media/speakers/social-piotr-gredowski.png new file mode 100644 index 000000000..3b00a652c Binary files /dev/null and b/public/media/speakers/social-piotr-gredowski.png differ diff --git a/public/media/speakers/social-piotr-rybak.png b/public/media/speakers/social-piotr-rybak.png new file mode 100644 index 000000000..50270d7fb Binary files /dev/null and b/public/media/speakers/social-piotr-rybak.png differ diff --git a/public/media/speakers/social-raul-cumplido-dominguez.png b/public/media/speakers/social-raul-cumplido-dominguez.png new file mode 100644 index 000000000..6a959f080 Binary files /dev/null and b/public/media/speakers/social-raul-cumplido-dominguez.png differ diff --git a/public/media/speakers/social-reuven-m-lerner.png b/public/media/speakers/social-reuven-m-lerner.png new file mode 100644 index 000000000..b618580e1 Binary files /dev/null and b/public/media/speakers/social-reuven-m-lerner.png differ diff --git a/public/media/speakers/social-rodrigo-girao-serrao.png b/public/media/speakers/social-rodrigo-girao-serrao.png new file mode 100644 index 000000000..768d28134 Binary files /dev/null and b/public/media/speakers/social-rodrigo-girao-serrao.png differ diff --git a/public/media/speakers/social-sangarshanan.png b/public/media/speakers/social-sangarshanan.png new file mode 100644 index 000000000..2b355eded Binary files /dev/null and b/public/media/speakers/social-sangarshanan.png differ diff --git a/public/media/speakers/social-savannah-ostrowski.png b/public/media/speakers/social-savannah-ostrowski.png new file mode 100644 index 000000000..849a8ed81 Binary files /dev/null and b/public/media/speakers/social-savannah-ostrowski.png differ diff --git a/public/media/speakers/social-sebastian-buczynski.png b/public/media/speakers/social-sebastian-buczynski.png new file mode 100644 index 000000000..61638b02c Binary files /dev/null and b/public/media/speakers/social-sebastian-buczynski.png differ diff --git a/public/media/speakers/social-sebastian-burzynski.png b/public/media/speakers/social-sebastian-burzynski.png new file mode 100644 index 000000000..1757f4415 Binary files /dev/null and b/public/media/speakers/social-sebastian-burzynski.png differ diff --git a/public/media/speakers/social-sergi-porta.png b/public/media/speakers/social-sergi-porta.png new file mode 100644 index 000000000..076fb5ec5 Binary files /dev/null and b/public/media/speakers/social-sergi-porta.png differ diff --git a/public/media/speakers/social-seth-michael-larson.png b/public/media/speakers/social-seth-michael-larson.png new file mode 100644 index 000000000..87d6c235e Binary files /dev/null and b/public/media/speakers/social-seth-michael-larson.png differ diff --git a/public/media/speakers/social-stefanie-molin.png b/public/media/speakers/social-stefanie-molin.png new file mode 100644 index 000000000..c693bfcfa Binary files /dev/null and b/public/media/speakers/social-stefanie-molin.png differ diff --git a/public/media/speakers/social-sviatoslav-sydorenko-sviatoslav-sidorenko.png b/public/media/speakers/social-sviatoslav-sydorenko-sviatoslav-sidorenko.png new file mode 100644 index 000000000..0182fdb15 Binary files /dev/null and b/public/media/speakers/social-sviatoslav-sydorenko-sviatoslav-sidorenko.png differ diff --git a/public/media/speakers/social-sylwia-budzynska.png b/public/media/speakers/social-sylwia-budzynska.png new file mode 100644 index 000000000..9a2f38b92 Binary files /dev/null and b/public/media/speakers/social-sylwia-budzynska.png differ diff --git a/public/media/speakers/social-thomas-wouters.png b/public/media/speakers/social-thomas-wouters.png new file mode 100644 index 000000000..5d721344b Binary files /dev/null and b/public/media/speakers/social-thomas-wouters.png differ diff --git a/public/media/speakers/social-tobias-wrigstad.png b/public/media/speakers/social-tobias-wrigstad.png new file mode 100644 index 000000000..f760b114c Binary files /dev/null and b/public/media/speakers/social-tobias-wrigstad.png differ diff --git a/public/media/speakers/social-tomas-roun.png b/public/media/speakers/social-tomas-roun.png new file mode 100644 index 000000000..4953b5f44 Binary files /dev/null and b/public/media/speakers/social-tomas-roun.png differ diff --git a/public/media/speakers/social-vincenzo-ventriglia.png b/public/media/speakers/social-vincenzo-ventriglia.png new file mode 100644 index 000000000..cd0201261 Binary files /dev/null and b/public/media/speakers/social-vincenzo-ventriglia.png differ diff --git a/public/media/speakers/social-vinicius-gubiani-ferreira.png b/public/media/speakers/social-vinicius-gubiani-ferreira.png new file mode 100644 index 000000000..87c1c0652 Binary files /dev/null and b/public/media/speakers/social-vinicius-gubiani-ferreira.png differ diff --git a/public/media/speakers/social-vlad-stefan-harbuz.png b/public/media/speakers/social-vlad-stefan-harbuz.png new file mode 100644 index 000000000..4543957a5 Binary files /dev/null and b/public/media/speakers/social-vlad-stefan-harbuz.png differ diff --git a/public/media/speakers/social-vladimir-slavov.png b/public/media/speakers/social-vladimir-slavov.png new file mode 100644 index 000000000..68db312fe Binary files /dev/null and b/public/media/speakers/social-vladimir-slavov.png differ diff --git a/public/media/speakers/social-vyron-vasileiadis.png b/public/media/speakers/social-vyron-vasileiadis.png new file mode 100644 index 000000000..de0e6fa24 Binary files /dev/null and b/public/media/speakers/social-vyron-vasileiadis.png differ diff --git a/public/media/speakers/social-will-vincent.png b/public/media/speakers/social-will-vincent.png new file mode 100644 index 000000000..87ce1ba7e Binary files /dev/null and b/public/media/speakers/social-will-vincent.png differ diff --git a/public/media/speakers/social-wojtek-erbetowski.png b/public/media/speakers/social-wojtek-erbetowski.png new file mode 100644 index 000000000..e903f23d8 Binary files /dev/null and b/public/media/speakers/social-wojtek-erbetowski.png differ diff --git a/public/media/sponsors/social-1password.png b/public/media/sponsors/social-1password.png deleted file mode 100644 index ff8d9ed88..000000000 Binary files a/public/media/sponsors/social-1password.png and /dev/null differ diff --git a/public/media/sponsors/social-anaconda.png b/public/media/sponsors/social-anaconda.png deleted file mode 100644 index 4daad47cc..000000000 Binary files a/public/media/sponsors/social-anaconda.png and /dev/null differ diff --git a/public/media/sponsors/social-apify.png b/public/media/sponsors/social-apify.png deleted file mode 100644 index b93567fff..000000000 Binary files a/public/media/sponsors/social-apify.png and /dev/null differ diff --git a/public/media/sponsors/social-arm.png b/public/media/sponsors/social-arm.png index b30b6ddb1..77da9159c 100644 Binary files a/public/media/sponsors/social-arm.png and b/public/media/sponsors/social-arm.png differ diff --git a/public/media/sponsors/social-ataccama.png b/public/media/sponsors/social-ataccama.png deleted file mode 100644 index 44cf8265c..000000000 Binary files a/public/media/sponsors/social-ataccama.png and /dev/null differ diff --git a/public/media/sponsors/social-backmarket.png b/public/media/sponsors/social-backmarket.png new file mode 100644 index 000000000..d86a9b3c0 Binary files /dev/null and b/public/media/sponsors/social-backmarket.png differ diff --git a/public/media/sponsors/social-bloomberg.png b/public/media/sponsors/social-bloomberg.png index 01af4f90f..48c2ebcf4 100644 Binary files a/public/media/sponsors/social-bloomberg.png and b/public/media/sponsors/social-bloomberg.png differ diff --git a/public/media/sponsors/social-clug.png b/public/media/sponsors/social-clug.png new file mode 100644 index 000000000..809ac7432 Binary files /dev/null and b/public/media/sponsors/social-clug.png differ diff --git a/public/media/sponsors/social-cultrepo.png b/public/media/sponsors/social-cultrepo.png deleted file mode 100644 index 5da9da22f..000000000 Binary files a/public/media/sponsors/social-cultrepo.png and /dev/null differ diff --git a/public/media/sponsors/social-djangocon.png b/public/media/sponsors/social-djangocon.png deleted file mode 100644 index 25580dfb0..000000000 Binary files a/public/media/sponsors/social-djangocon.png and /dev/null differ diff --git a/public/media/sponsors/social-dsf.png b/public/media/sponsors/social-dsf.png deleted file mode 100644 index 636a2d7ae..000000000 Binary files a/public/media/sponsors/social-dsf.png and /dev/null differ diff --git a/public/media/sponsors/social-eps.png b/public/media/sponsors/social-eps.png index dc4f412d6..691c9415b 100644 Binary files a/public/media/sponsors/social-eps.png and b/public/media/sponsors/social-eps.png differ diff --git a/public/media/sponsors/social-euroscipy.png b/public/media/sponsors/social-euroscipy.png new file mode 100644 index 000000000..878fe1e01 Binary files /dev/null and b/public/media/sponsors/social-euroscipy.png differ diff --git a/public/media/sponsors/social-evolabel.png b/public/media/sponsors/social-evolabel.png deleted file mode 100644 index 10fe02c38..000000000 Binary files a/public/media/sponsors/social-evolabel.png and /dev/null differ diff --git a/public/media/sponsors/social-fsfe.png b/public/media/sponsors/social-fsfe.png new file mode 100644 index 000000000..b518623c6 Binary files /dev/null and b/public/media/sponsors/social-fsfe.png differ diff --git a/public/media/sponsors/social-gel.png b/public/media/sponsors/social-gel.png deleted file mode 100644 index 73c8b90cc..000000000 Binary files a/public/media/sponsors/social-gel.png and /dev/null differ diff --git a/public/media/sponsors/social-google-cloud.png b/public/media/sponsors/social-google-cloud.png index 49515c9d0..84ebf71e7 100644 Binary files a/public/media/sponsors/social-google-cloud.png and b/public/media/sponsors/social-google-cloud.png differ diff --git a/public/media/sponsors/social-hablemospython.png b/public/media/sponsors/social-hablemospython.png index 3e5538561..bc64f42af 100644 Binary files a/public/media/sponsors/social-hablemospython.png and b/public/media/sponsors/social-hablemospython.png differ diff --git a/public/media/sponsors/social-hrt.png b/public/media/sponsors/social-hrt.png new file mode 100644 index 000000000..4f251c5f1 Binary files /dev/null and b/public/media/sponsors/social-hrt.png differ diff --git a/public/media/sponsors/social-jetbrains.png b/public/media/sponsors/social-jetbrains.png index 21e74e1ad..70dbf8c77 100644 Binary files a/public/media/sponsors/social-jetbrains.png and b/public/media/sponsors/social-jetbrains.png differ diff --git a/public/media/sponsors/social-junior-guru.png b/public/media/sponsors/social-junior-guru.png deleted file mode 100644 index 3d6d44535..000000000 Binary files a/public/media/sponsors/social-junior-guru.png and /dev/null differ diff --git a/public/media/sponsors/social-lwn-net.png b/public/media/sponsors/social-lwn-net.png deleted file mode 100644 index 451d964d4..000000000 Binary files a/public/media/sponsors/social-lwn-net.png and /dev/null differ diff --git a/public/media/sponsors/social-manychat.png b/public/media/sponsors/social-manychat.png new file mode 100644 index 000000000..821bb900f Binary files /dev/null and b/public/media/sponsors/social-manychat.png differ diff --git a/public/media/sponsors/social-microsoft.png b/public/media/sponsors/social-microsoft.png index 1911b083c..9ce26b8e6 100644 Binary files a/public/media/sponsors/social-microsoft.png and b/public/media/sponsors/social-microsoft.png differ diff --git a/public/media/sponsors/social-numberly.png b/public/media/sponsors/social-numberly.png index 4ec210413..9e2dbf953 100644 Binary files a/public/media/sponsors/social-numberly.png and b/public/media/sponsors/social-numberly.png differ diff --git a/public/media/sponsors/social-optiver.png b/public/media/sponsors/social-optiver.png new file mode 100644 index 000000000..62503bda5 Binary files /dev/null and b/public/media/sponsors/social-optiver.png differ diff --git a/public/media/sponsors/social-picnic.png b/public/media/sponsors/social-picnic.png deleted file mode 100644 index 372b84cc6..000000000 Binary files a/public/media/sponsors/social-picnic.png and /dev/null differ diff --git a/public/media/sponsors/social-pretalx.png b/public/media/sponsors/social-pretalx.png deleted file mode 100644 index 2db8473b1..000000000 Binary files a/public/media/sponsors/social-pretalx.png and /dev/null differ diff --git a/public/media/sponsors/social-pretix.png b/public/media/sponsors/social-pretix.png deleted file mode 100644 index 8ec478f19..000000000 Binary files a/public/media/sponsors/social-pretix.png and /dev/null differ diff --git a/public/media/sponsors/social-prusa.png b/public/media/sponsors/social-prusa.png deleted file mode 100644 index bff9865c0..000000000 Binary files a/public/media/sponsors/social-prusa.png and /dev/null differ diff --git a/public/media/sponsors/social-psf.png b/public/media/sponsors/social-psf.png index 8140ee3cc..bc42c9802 100644 Binary files a/public/media/sponsors/social-psf.png and b/public/media/sponsors/social-psf.png differ diff --git a/public/media/sponsors/social-pycon-at.png b/public/media/sponsors/social-pycon-at.png deleted file mode 100644 index 91ddd6ed4..000000000 Binary files a/public/media/sponsors/social-pycon-at.png and /dev/null differ diff --git a/public/media/sponsors/social-pycon-fi.png b/public/media/sponsors/social-pycon-fi.png deleted file mode 100644 index 5bb665de6..000000000 Binary files a/public/media/sponsors/social-pycon-fi.png and /dev/null differ diff --git a/public/media/sponsors/social-pycon-fr.png b/public/media/sponsors/social-pycon-fr.png deleted file mode 100644 index 39bcc3374..000000000 Binary files a/public/media/sponsors/social-pycon-fr.png and /dev/null differ diff --git a/public/media/sponsors/social-pycon-gr.png b/public/media/sponsors/social-pycon-gr.png deleted file mode 100644 index fd4ec46c3..000000000 Binary files a/public/media/sponsors/social-pycon-gr.png and /dev/null differ diff --git a/public/media/sponsors/social-pycon-greece.png b/public/media/sponsors/social-pycon-greece.png new file mode 100644 index 000000000..7b1679b9e Binary files /dev/null and b/public/media/sponsors/social-pycon-greece.png differ diff --git a/public/media/sponsors/social-pycon-it.png b/public/media/sponsors/social-pycon-it.png deleted file mode 100644 index 96eacf50b..000000000 Binary files a/public/media/sponsors/social-pycon-it.png and /dev/null differ diff --git a/public/media/sponsors/social-pycon-pt.png b/public/media/sponsors/social-pycon-pt.png deleted file mode 100644 index 4037c8235..000000000 Binary files a/public/media/sponsors/social-pycon-pt.png and /dev/null differ diff --git a/public/media/sponsors/social-pyconwro.png b/public/media/sponsors/social-pyconwro.png new file mode 100644 index 000000000..6d22f52bc Binary files /dev/null and b/public/media/sponsors/social-pyconwro.png differ diff --git a/public/media/sponsors/social-pydantic.png b/public/media/sponsors/social-pydantic.png deleted file mode 100644 index 30f11d1cc..000000000 Binary files a/public/media/sponsors/social-pydantic.png and /dev/null differ diff --git a/public/media/sponsors/social-pydatabydgoszcz.png b/public/media/sponsors/social-pydatabydgoszcz.png new file mode 100644 index 000000000..0bdca515c Binary files /dev/null and b/public/media/sponsors/social-pydatabydgoszcz.png differ diff --git a/public/media/sponsors/social-pydatakrk.png b/public/media/sponsors/social-pydatakrk.png new file mode 100644 index 000000000..59f6c495c Binary files /dev/null and b/public/media/sponsors/social-pydatakrk.png differ diff --git a/public/media/sponsors/social-pydatatrojmiasto.png b/public/media/sponsors/social-pydatatrojmiasto.png new file mode 100644 index 000000000..640361ab4 Binary files /dev/null and b/public/media/sponsors/social-pydatatrojmiasto.png differ diff --git a/public/media/sponsors/social-pygda.png b/public/media/sponsors/social-pygda.png new file mode 100644 index 000000000..2a5995ffb Binary files /dev/null and b/public/media/sponsors/social-pygda.png differ diff --git a/public/media/sponsors/social-pykonik.png b/public/media/sponsors/social-pykonik.png new file mode 100644 index 000000000..9f5397b92 Binary files /dev/null and b/public/media/sponsors/social-pykonik.png differ diff --git a/public/media/sponsors/social-pyladies.png b/public/media/sponsors/social-pyladies.png deleted file mode 100644 index db8b3d301..000000000 Binary files a/public/media/sponsors/social-pyladies.png and /dev/null differ diff --git a/public/media/sponsors/social-pyladiescon.png b/public/media/sponsors/social-pyladiescon.png index a8f8d56fe..084e625f8 100644 Binary files a/public/media/sponsors/social-pyladiescon.png and b/public/media/sponsors/social-pyladiescon.png differ diff --git a/public/media/sponsors/social-pystok.png b/public/media/sponsors/social-pystok.png new file mode 100644 index 000000000..d1584fb80 Binary files /dev/null and b/public/media/sponsors/social-pystok.png differ diff --git a/public/media/sponsors/social-python-ankara.png b/public/media/sponsors/social-python-ankara.png new file mode 100644 index 000000000..5bdc03063 Binary files /dev/null and b/public/media/sponsors/social-python-ankara.png differ diff --git a/public/media/sponsors/social-python-institute.png b/public/media/sponsors/social-python-institute.png deleted file mode 100644 index de1092a69..000000000 Binary files a/public/media/sponsors/social-python-institute.png and /dev/null differ diff --git a/public/media/sponsors/social-pythonlodz.png b/public/media/sponsors/social-pythonlodz.png new file mode 100644 index 000000000..ca855e45a Binary files /dev/null and b/public/media/sponsors/social-pythonlodz.png differ diff --git a/public/media/sponsors/social-pythonpizza.png b/public/media/sponsors/social-pythonpizza.png new file mode 100644 index 000000000..788b802a9 Binary files /dev/null and b/public/media/sponsors/social-pythonpizza.png differ diff --git a/public/media/sponsors/social-pyvec.png b/public/media/sponsors/social-pyvec.png deleted file mode 100644 index 9f5b7663a..000000000 Binary files a/public/media/sponsors/social-pyvec.png and /dev/null differ diff --git a/public/media/sponsors/social-pyvo.png b/public/media/sponsors/social-pyvo.png deleted file mode 100644 index 375b1edfe..000000000 Binary files a/public/media/sponsors/social-pyvo.png and /dev/null differ diff --git a/public/media/sponsors/social-pywaw.png b/public/media/sponsors/social-pywaw.png new file mode 100644 index 000000000..fc664c2ce Binary files /dev/null and b/public/media/sponsors/social-pywaw.png differ diff --git a/public/media/sponsors/social-qt.png b/public/media/sponsors/social-qt.png deleted file mode 100644 index c191ef518..000000000 Binary files a/public/media/sponsors/social-qt.png and /dev/null differ diff --git a/public/media/sponsors/social-radio-beat.png b/public/media/sponsors/social-radio-beat.png deleted file mode 100644 index c87c76e4b..000000000 Binary files a/public/media/sponsors/social-radio-beat.png and /dev/null differ diff --git a/public/media/sponsors/social-rossum.png b/public/media/sponsors/social-rossum.png deleted file mode 100644 index 79dc3eb57..000000000 Binary files a/public/media/sponsors/social-rossum.png and /dev/null differ diff --git a/public/media/sponsors/social-sema.png b/public/media/sponsors/social-sema.png deleted file mode 100644 index e31d3526f..000000000 Binary files a/public/media/sponsors/social-sema.png and /dev/null differ diff --git a/public/media/sponsors/social-sentry.png b/public/media/sponsors/social-sentry.png deleted file mode 100644 index 008805bcb..000000000 Binary files a/public/media/sponsors/social-sentry.png and /dev/null differ diff --git a/public/media/sponsors/social-snowflake.png b/public/media/sponsors/social-snowflake.png deleted file mode 100644 index a6d5c59cd..000000000 Binary files a/public/media/sponsors/social-snowflake.png and /dev/null differ diff --git a/public/media/sponsors/social-startup.png b/public/media/sponsors/social-startup.png deleted file mode 100644 index 4d9feed28..000000000 Binary files a/public/media/sponsors/social-startup.png and /dev/null differ diff --git a/public/media/sponsors/social-travelperk.png b/public/media/sponsors/social-travelperk.png deleted file mode 100644 index 73e577740..000000000 Binary files a/public/media/sponsors/social-travelperk.png and /dev/null differ diff --git a/public/social/partner_card.png b/public/social/partner_card.png new file mode 100644 index 000000000..1f3d3d11f Binary files /dev/null and b/public/social/partner_card.png differ diff --git a/public/social/speaker_card.png b/public/social/speaker_card.png new file mode 100644 index 000000000..6ecfb128c Binary files /dev/null and b/public/social/speaker_card.png differ diff --git a/public/social/sponsor_card.png b/public/social/sponsor_card.png new file mode 100644 index 000000000..4a73719f8 Binary files /dev/null and b/public/social/sponsor_card.png differ diff --git a/scripts/download_social_speakers.cjs b/scripts/download_social_speakers.cjs new file mode 100644 index 000000000..5d94f9577 --- /dev/null +++ b/scripts/download_social_speakers.cjs @@ -0,0 +1,80 @@ +const puppeteer = require("puppeteer"); + +(async () => { + const browser = await puppeteer.launch({ + executablePath: process.env.CHROME_BIN, + args: ["--no-sandbox", "--disable-setuid-sandbox"], + }); + const page = await browser.newPage(); + await page.goto("http://localhost:4321/media/speakers", { + waitUntil: "domcontentloaded", + timeout: 60000, + }); + + // Wait for all images to finish loading (both and SVG elements) + await page.evaluate(() => + Promise.all([ + // HTML img elements + ...Array.from(document.images) + .filter((img) => !img.complete) + .map( + (img) => + new Promise((resolve) => { + img.onload = resolve; + img.onerror = resolve; + }) + ), + // SVG elements loaded via href + ...Array.from(document.querySelectorAll("svg image[href]")).map( + (svgImg) => + new Promise((resolve) => { + const url = svgImg.getAttribute("href"); + if (!url) return resolve(); + const img = new Image(); + img.onload = resolve; + img.onerror = resolve; + img.src = url; + }) + ), + ]) + ); + + // Hide the Astro dev toolbar and any other overlays before screenshotting + await page.addStyleTag({ + content: ` + astro-dev-toolbar, + astro-dev-toolbar-window, + [data-astro-dev-toolbar], + #astro-dev-toolbar { display: none !important; } + `, + }); + + // Unwrap .social divs from their parent to prevent the browser's + // link toolbar overlay from appearing in screenshots + await page.evaluate(() => { + document.querySelectorAll("a > .social").forEach((el) => { + el.parentElement.replaceWith(el); + }); + }); + + // Move mouse away from any element to avoid hover states + await page.mouse.move(0, 0); + + const elements = await page.$$(".social"); + + for (let i = 0; i < elements.length; i++) { + const el = elements[i]; + + // Get the slug from the element + const slug = await page.evaluate((el) => el.getAttribute("data-slug"), el); + + // Fallback if slug is missing + const filename = slug ? `social-${slug}.png` : `social-${i}.png`; + + await el.screenshot({ path: filename }); + console.log(`Saved ${filename}`); + } + + console.log(`Done. ${elements.length} cards generated.`); + await browser.close(); +})(); diff --git a/scripts/download_social.cjs b/scripts/download_social_sponsors.cjs similarity index 100% rename from scripts/download_social.cjs rename to scripts/download_social_sponsors.cjs diff --git a/src/components/SocialMediaCard.astro b/src/components/SocialMediaCard.astro index ba8ab9b84..070df5b48 100644 --- a/src/components/SocialMediaCard.astro +++ b/src/components/SocialMediaCard.astro @@ -6,26 +6,22 @@ const { entry } = Astro.props; const sessions: CollectionEntry<"sessions">[]= await getEntries(entry.data.submissions); --- - + { entry.data.avatar ? ( - + @@ -33,10 +29,10 @@ const sessions: CollectionEntry<"sessions">[]= await getEntries(entry.data.submi -{sessions.map((session) => <>{session.data.title} >)} +{sessions.map((session) => <>{session.data.title}>)} - + {entry.data.name} @@ -45,7 +41,7 @@ const sessions: CollectionEntry<"sessions">[]= await getEntries(entry.data.submi -{sessions.map((session) => <>{session.data.title} >)} +{sessions.map((session) => <>{session.data.title}>)} @@ -58,56 +54,59 @@ const sessions: CollectionEntry<"sessions">[]= await getEntries(entry.data.submi diff --git a/src/components/SocialMediaSponsorCard.astro b/src/components/SocialMediaSponsorCard.astro index bcf0e7afc..bdb8d5d9f 100644 --- a/src/components/SocialMediaSponsorCard.astro +++ b/src/components/SocialMediaSponsorCard.astro @@ -21,7 +21,7 @@ const tiers = [ "Patron", ] as const; -const bg_url = tiers.includes(tier)? '/social/bg4.png' : '/social/bg5.png'; +const bg_url = tiers.includes(tier)? '/social/sponsor_card.png' : '/social/partner_card.png'; // Function to parse CSS padding values @@ -76,7 +76,7 @@ if (height > availableHeight) { // Calculate position with padding offset const x = 450 - (width + padding.left + padding.right) / 2 + padding.left; -const y = 650 - (height + padding.top + padding.bottom) / 2 + padding.top; +const y = 670 - (height + padding.top + padding.bottom) / 2 + padding.top; --- diff --git a/src/pages/api/media/queue.ts b/src/pages/api/media/queue.ts new file mode 100644 index 000000000..edff84158 --- /dev/null +++ b/src/pages/api/media/queue.ts @@ -0,0 +1,297 @@ +import { getCollection, getEntry } from "astro:content"; +import type { APIRoute } from "astro"; + +// ── helpers ──────────────────────────────────────────────────────────────── + +function getTwitterUsername(url: string): string | undefined { + if (!url) return undefined; + const username = url.split("/").pop(); + return (username ?? url).startsWith("@") ? username : `@${username}`; +} + +function getBlueskyUsername(url: string): string | undefined { + if (!url) return undefined; + const username = url.split("/").pop()?.replace(/^@/, ""); + return username ? `@${username}` : undefined; +} + +function getMastodonUsername(url: string): string | undefined { + if (!url) return undefined; + const match = url.match(/https?:\/\/([^\/]+)\/@([^\/]+)(\/|\?|$)/); + return match ? `@${match[2]}@${match[1]}` : undefined; +} + +function getLinkedInUsernameHandler(url: string): string | undefined { + if (!url) return undefined; + const match = url.match(/https?:\/\/([^\/]+)\/in\/([^\/]+)(\/|\?|$)/); + if (match) { + try { + return `https://www.linkedin.com/in/${decodeURIComponent(match[2])}`; + } catch { + return `https://www.linkedin.com/in/${match[2]}`; + } + } + return undefined; +} + +const trimToLimit = (text: string, limit: number) => + text.length <= limit ? text : text.slice(0, limit - 1) + "…"; + +// ── tiers ────────────────────────────────────────────────────────────────── + +const commercialTiers = [ + "Keystone", + "Diamond", + "Platinum", + "Platinum X", + "Gold", + "Silver", + "Bronze", + "Patron", +] as const; + +const isCommercialTier = (tier: any) => commercialTiers.includes(tier); + +// ── message templates ────────────────────────────────────────────────────── + +const charLimits: Record = { + instagram: 2200, + x: 280, + linkedin: 3000, + bsky: 300, + fosstodon: 500, +}; + +// Speaker messages +const speakerMessageTemplate = { + instagram: ({ name, talkTitle }) => + `Join ${name} at EuroPython for "${talkTitle}".`, + x: ({ name, handle, talkTitle, talkUrl }) => + handle + ? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". Talk: ${talkUrl}` + : `Join ${name} at EuroPython for "${talkTitle}". Talk: ${talkUrl}`, + linkedin: ({ name, talkTitle }) => + `Join ${name} at EuroPython for "${talkTitle}".`, + bsky: ({ name, handle, talkTitle, talkUrl }) => + handle + ? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". Talk: ${talkUrl}` + : `Join ${name} at EuroPython for "${talkTitle}". Talk: ${talkUrl}`, + fosstodon: ({ name, handle, talkTitle, talkUrl }) => + handle + ? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". talk: ${talkUrl}` + : `Join ${name} at EuroPython for "${talkTitle}". Talk: ${talkUrl}`, +}; + +// Sponsor messages +const commercialMessages = [ + "🎉✨ We are pleased to welcome SPONSOR_NAME as a sponsor for EuroPython 2026! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ We are delighted to welcome SPONSOR_NAME as a sponsor for EuroPython 2026! Your support helps make this event extraordinary. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ A big thank you to SPONSOR_NAME for joining us as a sponsor for EuroPython 2026! Your support is making a huge impact. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ Big shoutout and heartfelt thanks to SPONSOR_NAME for sponsoring EuroPython 2026! Your support is crucial in bringing the European Python 🐍 community closer together. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ Thank you to SPONSOR_NAME for sponsoring EuroPython 2026! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ A huge thank you to SPONSOR_NAME for sponsoring EuroPython 2026! Your support helps make this event extraordinary. 🙌 SPONSOR_HANDLE SPONSOR_URL", +]; + +const communityMessages = [ + "🎉✨ A warm thank you to SPONSOR_NAME for supporting EuroPython 2026! We're proud to be a space where communities come together, and we value the opportunity to collaborate with other communities and open-source projects. 🙌 SUPPORTER_HANDLE SUPPORTER_URL", +]; + +const getRandomMessage = (messages: string[]) => + messages[Math.floor(Math.random() * messages.length)]; + +function buildSponsorMessage( + template: string, + name: string, + handle: string, + url: string +): string { + return template + .replace(/SPONSOR_NAME/g, name) + .replace(/SPONSOR_HANDLE/g, handle) + .replace(/SPONSOR_URL/g, url) + .replace(/SUPPORTER_HANDLE/g, handle) + .replace(/SUPPORTER_URL/g, url); +} + +// ── main route ───────────────────────────────────────────────────────────── + +export const GET: APIRoute = async () => { + const allSpeakers = await getCollection("speakers"); + const allSessions = await getCollection("sessions"); + const allSponsors = await getCollection("sponsors"); + + const excludeSponsors = ["startup"]; + + // Derive keynote speaker IDs so we can skip them + const keynoteSpeakerIds = new Set( + allSessions + .filter((s) => s.data.session_type?.toLowerCase() === "keynote") + .flatMap((s) => s.data.speakers.map((ref) => ref.id)) + ); + + // ── build speaker records ──────────────────────────────────────────────── + const speakerRecords: any[] = []; + + for (const speaker of allSpeakers) { + if (keynoteSpeakerIds.has(speaker.id)) continue; + + const { + name, + twitter_url, + linkedin_url, + bluesky_url, + mastodon_url, + submissions, + } = speaker.data; + + const sessions = await Promise.all( + submissions.map((s) => getEntry("sessions", s.id)) + ); + const validSessions = sessions.filter((s) => s && s.data.title); + if (validSessions.length === 0) continue; + + const talkTitle = validSessions[0]?.data.title || "an exciting topic"; + const talkCode = validSessions[0]?.data.code; + const talkUrl = `https://ep2026.europython.eu/${talkCode}`; + const fallbackUrl = `https://ep2026.europython.eu/speaker/${speaker.id}`; + const image = `https://ep2026.europython.eu/media/speakers/social-${speaker.id}.png`; + + const handles = { + x: getTwitterUsername(twitter_url || ""), + linkedin: getLinkedInUsernameHandler(linkedin_url || ""), + bsky: getBlueskyUsername(bluesky_url || ""), + fosstodon: getMastodonUsername(mastodon_url || ""), + }; + + const generateSpeakerMessage = ( + platform: keyof typeof speakerMessageTemplate + ) => { + const fn = speakerMessageTemplate[platform]; + const handle = + platform === "instagram" + ? undefined + : handles[platform as keyof typeof handles]; + const full = fn({ + name, + handle, + talkTitle, + talkUrl: platform === "instagram" ? fallbackUrl : talkUrl, + }); + return trimToLimit(full, charLimits[platform]); + }; + + speakerRecords.push({ + type: "speaker", + name, + image, + handles, + channel: { + instagram: generateSpeakerMessage("instagram"), + x: generateSpeakerMessage("x"), + linkedin: generateSpeakerMessage("linkedin"), + bsky: generateSpeakerMessage("bsky"), + fosstodon: generateSpeakerMessage("fosstodon"), + }, + }); + } + + // ── build sponsor records (commercial) ────────────────────────────────── + const sponsorRecords: any[] = []; + + for (const sponsor of allSponsors) { + if (excludeSponsors.includes(sponsor.id)) continue; + if (!isCommercialTier(sponsor.data.tier)) continue; + + const { name, url, socials } = sponsor.data; + const image = `https://ep2026.europython.eu/media/sponsors/social-${sponsor.id}.png`; + + const handles = { + x: socials?.twitter || "", + linkedin: socials?.linkedin || "", + bsky: socials?.bluesky || "", + fosstodon: socials?.mastodon || "", + }; + + const makeMsg = (platform: "x" | "linkedin" | "bsky" | "fosstodon") => { + const messages = commercialMessages; + const template = + platform === "x" ? messages[0] : getRandomMessage(messages); + const full = buildSponsorMessage(template, name, handles[platform], url); + return trimToLimit(full, charLimits[platform]); + }; + + sponsorRecords.push({ + type: "sponsor", + name, + image, + handles, + channel: { + x: makeMsg("x"), + linkedin: makeMsg("linkedin"), + bsky: makeMsg("bsky"), + fosstodon: makeMsg("fosstodon"), + }, + }); + } + + // ── build partner records (community) ──────────────────────────────────── + const partnerRecords: any[] = []; + + for (const sponsor of allSponsors) { + if (excludeSponsors.includes(sponsor.id)) continue; + if (isCommercialTier(sponsor.data.tier)) continue; + + const { name, url, socials } = sponsor.data; + const image = `https://ep2026.europython.eu/media/sponsors/social-${sponsor.id}.png`; + + const handles = { + x: socials?.twitter || "", + linkedin: socials?.linkedin || "", + bsky: socials?.bluesky || "", + fosstodon: socials?.mastodon || "", + }; + + const makeMsg = (platform: "x" | "linkedin" | "bsky" | "fosstodon") => { + const template = getRandomMessage(communityMessages); + const full = buildSponsorMessage(template, name, handles[platform], url); + return trimToLimit(full, charLimits[platform]); + }; + + partnerRecords.push({ + type: "partner", + name, + image, + handles, + channel: { + x: makeMsg("x"), + linkedin: makeMsg("linkedin"), + bsky: makeMsg("bsky"), + fosstodon: makeMsg("fosstodon"), + }, + }); + } + + // ── interleave: speaker, speaker, sponsor, speaker, partner ────────────── + // The pattern is a sequence of bucket references that repeats until all + // buckets are exhausted; remaining items are appended at the end. + const queue: any[] = []; + const buckets = [speakerRecords, sponsorRecords, partnerRecords]; + const pattern = [0, 0, 1, 0, 2]; // indices into buckets[] + const cursors = [0, 0, 0]; + + while (true) { + let added = 0; + for (const b of pattern) { + if (cursors[b] < buckets[b].length) { + queue.push(buckets[b][cursors[b]++]); + added++; + } + } + if (added === 0) break; // all buckets exhausted + } + + return new Response(JSON.stringify(queue, null, 2), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); +}; diff --git a/src/pages/api/media/speakers/posts.ts b/src/pages/api/media/speakers/posts.ts index 20fcd5805..0a109dc65 100644 --- a/src/pages/api/media/speakers/posts.ts +++ b/src/pages/api/media/speakers/posts.ts @@ -39,13 +39,16 @@ function getLinkedInUsernameHandler(url: string): string | undefined { export const GET: APIRoute = async () => { const limit = Infinity; const speakers = await getCollection("speakers"); - const exclude = [ - "sebastian-ramirez", - "savannah-ostrowski", - "nerea-luis", - "petr-baudis", - "brett-cannon", - ]; + const sessions = await getCollection("sessions"); + + // Dynamically derive keynote speaker slugs from the sessions collection + // so this list stays accurate as the programme is updated + const keynoteSpeakerIds = new Set( + sessions + .filter((s) => s.data.session_type?.toLowerCase() === "keynote") + .flatMap((s) => s.data.speakers.map((ref) => ref.id)) + ); + const records: any[] = []; const charLimits: Record = { @@ -85,7 +88,7 @@ export const GET: APIRoute = async () => { for (const speaker of speakers) { if (records.length >= limit) break; - if (exclude.includes(speaker.id)) continue; + if (keynoteSpeakerIds.has(speaker.id)) continue; const { name, diff --git a/src/pages/api/media/sponsors/posts.ts b/src/pages/api/media/sponsors/posts.ts index f4f0048d2..90fd64a91 100644 --- a/src/pages/api/media/sponsors/posts.ts +++ b/src/pages/api/media/sponsors/posts.ts @@ -27,16 +27,16 @@ export const GET: APIRoute = async () => { ] as const; const commercialMessages = [ - "🎉✨ We are pleased to welcome SPONSOR_NAME as a sponsor for EuroPython 2025! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", - "🚀✨ We are delighted to welcome SPONSOR_NAME as a sponsor for EuroPython 2025! Your support helps make this event extraordinary. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", - "🎉✨ A big thank you to SPONSOR_NAME for joining us as a sponsor for EuroPython 2025! Your support is making a huge impact. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", - "🚀✨ Big shoutout and heartfelt thanks to SPONSOR_NAME for sponsoring EuroPython 2025! Your support is crucial in bringing the European Python 🐍 community closer together. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌SPONSOR_HANDLE SPONSOR_URL", - "🎉✨ Thank you to SPONSOR_NAME for sponsoring EuroPython 2025! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", - "🚀✨ A huge thank you to SPONSOR_NAME for sponsoring EuroPython 2025! Your support helps make this event extraordinary. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ We are pleased to welcome SPONSOR_NAME as a sponsor for EuroPython 2026! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ We are delighted to welcome SPONSOR_NAME as a sponsor for EuroPython 2026! Your support helps make this event extraordinary. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ A big thank you to SPONSOR_NAME for joining us as a sponsor for EuroPython 2026! Your support is making a huge impact. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ Big shoutout and heartfelt thanks to SPONSOR_NAME for sponsoring EuroPython 2026! Your support is crucial in bringing the European Python 🐍 community closer together. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ Thank you to SPONSOR_NAME for sponsoring EuroPython 2026! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ A huge thank you to SPONSOR_NAME for sponsoring EuroPython 2026! Your support helps make this event extraordinary. 🙌 SPONSOR_HANDLE SPONSOR_URL", ]; const communityMessages = [ - "🎉✨ A warm thank you to SPONSOR_NAME for supporting EuroPython 2025! We're proud to be a space where communities come together, and we value the opportunity to collaborate with other communities and open-source projects. 🙌 SUPPORTER_HANDLE SUPPORTER_URL", + "🎉✨ A warm thank you to SPONSOR_NAME for supporting EuroPython 2026! We're proud to be a space where communities come together, and we value the opportunity to collaborate with other communities and open-source projects. 🙌 SUPPORTER_HANDLE SUPPORTER_URL", ]; const getRandomMessage = (messages: any) => { diff --git a/src/pages/media/speaker/[slug].astro b/src/pages/media/speaker/[slug].astro index 431d61208..0cccf5073 100644 --- a/src/pages/media/speaker/[slug].astro +++ b/src/pages/media/speaker/[slug].astro @@ -62,7 +62,8 @@ const { entry } = Astro.props;
-{sessions.map((session) => <>{session.data.title} >)} +{sessions.map((session) => <>{session.data.title}>)}
+
{entry.data.name}
@@ -58,56 +54,59 @@ const sessions: CollectionEntry<"sessions">[]= await getEntries(entry.data.submi diff --git a/src/components/SocialMediaSponsorCard.astro b/src/components/SocialMediaSponsorCard.astro index bcf0e7afc..bdb8d5d9f 100644 --- a/src/components/SocialMediaSponsorCard.astro +++ b/src/components/SocialMediaSponsorCard.astro @@ -21,7 +21,7 @@ const tiers = [ "Patron", ] as const; -const bg_url = tiers.includes(tier)? '/social/bg4.png' : '/social/bg5.png'; +const bg_url = tiers.includes(tier)? '/social/sponsor_card.png' : '/social/partner_card.png'; // Function to parse CSS padding values @@ -76,7 +76,7 @@ if (height > availableHeight) { // Calculate position with padding offset const x = 450 - (width + padding.left + padding.right) / 2 + padding.left; -const y = 650 - (height + padding.top + padding.bottom) / 2 + padding.top; +const y = 670 - (height + padding.top + padding.bottom) / 2 + padding.top; --- diff --git a/src/pages/api/media/queue.ts b/src/pages/api/media/queue.ts new file mode 100644 index 000000000..edff84158 --- /dev/null +++ b/src/pages/api/media/queue.ts @@ -0,0 +1,297 @@ +import { getCollection, getEntry } from "astro:content"; +import type { APIRoute } from "astro"; + +// ── helpers ──────────────────────────────────────────────────────────────── + +function getTwitterUsername(url: string): string | undefined { + if (!url) return undefined; + const username = url.split("/").pop(); + return (username ?? url).startsWith("@") ? username : `@${username}`; +} + +function getBlueskyUsername(url: string): string | undefined { + if (!url) return undefined; + const username = url.split("/").pop()?.replace(/^@/, ""); + return username ? `@${username}` : undefined; +} + +function getMastodonUsername(url: string): string | undefined { + if (!url) return undefined; + const match = url.match(/https?:\/\/([^\/]+)\/@([^\/]+)(\/|\?|$)/); + return match ? `@${match[2]}@${match[1]}` : undefined; +} + +function getLinkedInUsernameHandler(url: string): string | undefined { + if (!url) return undefined; + const match = url.match(/https?:\/\/([^\/]+)\/in\/([^\/]+)(\/|\?|$)/); + if (match) { + try { + return `https://www.linkedin.com/in/${decodeURIComponent(match[2])}`; + } catch { + return `https://www.linkedin.com/in/${match[2]}`; + } + } + return undefined; +} + +const trimToLimit = (text: string, limit: number) => + text.length <= limit ? text : text.slice(0, limit - 1) + "…"; + +// ── tiers ────────────────────────────────────────────────────────────────── + +const commercialTiers = [ + "Keystone", + "Diamond", + "Platinum", + "Platinum X", + "Gold", + "Silver", + "Bronze", + "Patron", +] as const; + +const isCommercialTier = (tier: any) => commercialTiers.includes(tier); + +// ── message templates ────────────────────────────────────────────────────── + +const charLimits: Record = { + instagram: 2200, + x: 280, + linkedin: 3000, + bsky: 300, + fosstodon: 500, +}; + +// Speaker messages +const speakerMessageTemplate = { + instagram: ({ name, talkTitle }) => + `Join ${name} at EuroPython for "${talkTitle}".`, + x: ({ name, handle, talkTitle, talkUrl }) => + handle + ? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". Talk: ${talkUrl}` + : `Join ${name} at EuroPython for "${talkTitle}". Talk: ${talkUrl}`, + linkedin: ({ name, talkTitle }) => + `Join ${name} at EuroPython for "${talkTitle}".`, + bsky: ({ name, handle, talkTitle, talkUrl }) => + handle + ? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". Talk: ${talkUrl}` + : `Join ${name} at EuroPython for "${talkTitle}". Talk: ${talkUrl}`, + fosstodon: ({ name, handle, talkTitle, talkUrl }) => + handle + ? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". talk: ${talkUrl}` + : `Join ${name} at EuroPython for "${talkTitle}". Talk: ${talkUrl}`, +}; + +// Sponsor messages +const commercialMessages = [ + "🎉✨ We are pleased to welcome SPONSOR_NAME as a sponsor for EuroPython 2026! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ We are delighted to welcome SPONSOR_NAME as a sponsor for EuroPython 2026! Your support helps make this event extraordinary. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ A big thank you to SPONSOR_NAME for joining us as a sponsor for EuroPython 2026! Your support is making a huge impact. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ Big shoutout and heartfelt thanks to SPONSOR_NAME for sponsoring EuroPython 2026! Your support is crucial in bringing the European Python 🐍 community closer together. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ Thank you to SPONSOR_NAME for sponsoring EuroPython 2026! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ A huge thank you to SPONSOR_NAME for sponsoring EuroPython 2026! Your support helps make this event extraordinary. 🙌 SPONSOR_HANDLE SPONSOR_URL", +]; + +const communityMessages = [ + "🎉✨ A warm thank you to SPONSOR_NAME for supporting EuroPython 2026! We're proud to be a space where communities come together, and we value the opportunity to collaborate with other communities and open-source projects. 🙌 SUPPORTER_HANDLE SUPPORTER_URL", +]; + +const getRandomMessage = (messages: string[]) => + messages[Math.floor(Math.random() * messages.length)]; + +function buildSponsorMessage( + template: string, + name: string, + handle: string, + url: string +): string { + return template + .replace(/SPONSOR_NAME/g, name) + .replace(/SPONSOR_HANDLE/g, handle) + .replace(/SPONSOR_URL/g, url) + .replace(/SUPPORTER_HANDLE/g, handle) + .replace(/SUPPORTER_URL/g, url); +} + +// ── main route ───────────────────────────────────────────────────────────── + +export const GET: APIRoute = async () => { + const allSpeakers = await getCollection("speakers"); + const allSessions = await getCollection("sessions"); + const allSponsors = await getCollection("sponsors"); + + const excludeSponsors = ["startup"]; + + // Derive keynote speaker IDs so we can skip them + const keynoteSpeakerIds = new Set( + allSessions + .filter((s) => s.data.session_type?.toLowerCase() === "keynote") + .flatMap((s) => s.data.speakers.map((ref) => ref.id)) + ); + + // ── build speaker records ──────────────────────────────────────────────── + const speakerRecords: any[] = []; + + for (const speaker of allSpeakers) { + if (keynoteSpeakerIds.has(speaker.id)) continue; + + const { + name, + twitter_url, + linkedin_url, + bluesky_url, + mastodon_url, + submissions, + } = speaker.data; + + const sessions = await Promise.all( + submissions.map((s) => getEntry("sessions", s.id)) + ); + const validSessions = sessions.filter((s) => s && s.data.title); + if (validSessions.length === 0) continue; + + const talkTitle = validSessions[0]?.data.title || "an exciting topic"; + const talkCode = validSessions[0]?.data.code; + const talkUrl = `https://ep2026.europython.eu/${talkCode}`; + const fallbackUrl = `https://ep2026.europython.eu/speaker/${speaker.id}`; + const image = `https://ep2026.europython.eu/media/speakers/social-${speaker.id}.png`; + + const handles = { + x: getTwitterUsername(twitter_url || ""), + linkedin: getLinkedInUsernameHandler(linkedin_url || ""), + bsky: getBlueskyUsername(bluesky_url || ""), + fosstodon: getMastodonUsername(mastodon_url || ""), + }; + + const generateSpeakerMessage = ( + platform: keyof typeof speakerMessageTemplate + ) => { + const fn = speakerMessageTemplate[platform]; + const handle = + platform === "instagram" + ? undefined + : handles[platform as keyof typeof handles]; + const full = fn({ + name, + handle, + talkTitle, + talkUrl: platform === "instagram" ? fallbackUrl : talkUrl, + }); + return trimToLimit(full, charLimits[platform]); + }; + + speakerRecords.push({ + type: "speaker", + name, + image, + handles, + channel: { + instagram: generateSpeakerMessage("instagram"), + x: generateSpeakerMessage("x"), + linkedin: generateSpeakerMessage("linkedin"), + bsky: generateSpeakerMessage("bsky"), + fosstodon: generateSpeakerMessage("fosstodon"), + }, + }); + } + + // ── build sponsor records (commercial) ────────────────────────────────── + const sponsorRecords: any[] = []; + + for (const sponsor of allSponsors) { + if (excludeSponsors.includes(sponsor.id)) continue; + if (!isCommercialTier(sponsor.data.tier)) continue; + + const { name, url, socials } = sponsor.data; + const image = `https://ep2026.europython.eu/media/sponsors/social-${sponsor.id}.png`; + + const handles = { + x: socials?.twitter || "", + linkedin: socials?.linkedin || "", + bsky: socials?.bluesky || "", + fosstodon: socials?.mastodon || "", + }; + + const makeMsg = (platform: "x" | "linkedin" | "bsky" | "fosstodon") => { + const messages = commercialMessages; + const template = + platform === "x" ? messages[0] : getRandomMessage(messages); + const full = buildSponsorMessage(template, name, handles[platform], url); + return trimToLimit(full, charLimits[platform]); + }; + + sponsorRecords.push({ + type: "sponsor", + name, + image, + handles, + channel: { + x: makeMsg("x"), + linkedin: makeMsg("linkedin"), + bsky: makeMsg("bsky"), + fosstodon: makeMsg("fosstodon"), + }, + }); + } + + // ── build partner records (community) ──────────────────────────────────── + const partnerRecords: any[] = []; + + for (const sponsor of allSponsors) { + if (excludeSponsors.includes(sponsor.id)) continue; + if (isCommercialTier(sponsor.data.tier)) continue; + + const { name, url, socials } = sponsor.data; + const image = `https://ep2026.europython.eu/media/sponsors/social-${sponsor.id}.png`; + + const handles = { + x: socials?.twitter || "", + linkedin: socials?.linkedin || "", + bsky: socials?.bluesky || "", + fosstodon: socials?.mastodon || "", + }; + + const makeMsg = (platform: "x" | "linkedin" | "bsky" | "fosstodon") => { + const template = getRandomMessage(communityMessages); + const full = buildSponsorMessage(template, name, handles[platform], url); + return trimToLimit(full, charLimits[platform]); + }; + + partnerRecords.push({ + type: "partner", + name, + image, + handles, + channel: { + x: makeMsg("x"), + linkedin: makeMsg("linkedin"), + bsky: makeMsg("bsky"), + fosstodon: makeMsg("fosstodon"), + }, + }); + } + + // ── interleave: speaker, speaker, sponsor, speaker, partner ────────────── + // The pattern is a sequence of bucket references that repeats until all + // buckets are exhausted; remaining items are appended at the end. + const queue: any[] = []; + const buckets = [speakerRecords, sponsorRecords, partnerRecords]; + const pattern = [0, 0, 1, 0, 2]; // indices into buckets[] + const cursors = [0, 0, 0]; + + while (true) { + let added = 0; + for (const b of pattern) { + if (cursors[b] < buckets[b].length) { + queue.push(buckets[b][cursors[b]++]); + added++; + } + } + if (added === 0) break; // all buckets exhausted + } + + return new Response(JSON.stringify(queue, null, 2), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); +}; diff --git a/src/pages/api/media/speakers/posts.ts b/src/pages/api/media/speakers/posts.ts index 20fcd5805..0a109dc65 100644 --- a/src/pages/api/media/speakers/posts.ts +++ b/src/pages/api/media/speakers/posts.ts @@ -39,13 +39,16 @@ function getLinkedInUsernameHandler(url: string): string | undefined { export const GET: APIRoute = async () => { const limit = Infinity; const speakers = await getCollection("speakers"); - const exclude = [ - "sebastian-ramirez", - "savannah-ostrowski", - "nerea-luis", - "petr-baudis", - "brett-cannon", - ]; + const sessions = await getCollection("sessions"); + + // Dynamically derive keynote speaker slugs from the sessions collection + // so this list stays accurate as the programme is updated + const keynoteSpeakerIds = new Set( + sessions + .filter((s) => s.data.session_type?.toLowerCase() === "keynote") + .flatMap((s) => s.data.speakers.map((ref) => ref.id)) + ); + const records: any[] = []; const charLimits: Record = { @@ -85,7 +88,7 @@ export const GET: APIRoute = async () => { for (const speaker of speakers) { if (records.length >= limit) break; - if (exclude.includes(speaker.id)) continue; + if (keynoteSpeakerIds.has(speaker.id)) continue; const { name, diff --git a/src/pages/api/media/sponsors/posts.ts b/src/pages/api/media/sponsors/posts.ts index f4f0048d2..90fd64a91 100644 --- a/src/pages/api/media/sponsors/posts.ts +++ b/src/pages/api/media/sponsors/posts.ts @@ -27,16 +27,16 @@ export const GET: APIRoute = async () => { ] as const; const commercialMessages = [ - "🎉✨ We are pleased to welcome SPONSOR_NAME as a sponsor for EuroPython 2025! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", - "🚀✨ We are delighted to welcome SPONSOR_NAME as a sponsor for EuroPython 2025! Your support helps make this event extraordinary. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", - "🎉✨ A big thank you to SPONSOR_NAME for joining us as a sponsor for EuroPython 2025! Your support is making a huge impact. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", - "🚀✨ Big shoutout and heartfelt thanks to SPONSOR_NAME for sponsoring EuroPython 2025! Your support is crucial in bringing the European Python 🐍 community closer together. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌SPONSOR_HANDLE SPONSOR_URL", - "🎉✨ Thank you to SPONSOR_NAME for sponsoring EuroPython 2025! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", - "🚀✨ A huge thank you to SPONSOR_NAME for sponsoring EuroPython 2025! Your support helps make this event extraordinary. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ We are pleased to welcome SPONSOR_NAME as a sponsor for EuroPython 2026! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ We are delighted to welcome SPONSOR_NAME as a sponsor for EuroPython 2026! Your support helps make this event extraordinary. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ A big thank you to SPONSOR_NAME for joining us as a sponsor for EuroPython 2026! Your support is making a huge impact. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ Big shoutout and heartfelt thanks to SPONSOR_NAME for sponsoring EuroPython 2026! Your support is crucial in bringing the European Python 🐍 community closer together. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌SPONSOR_HANDLE SPONSOR_URL", + "🎉✨ Thank you to SPONSOR_NAME for sponsoring EuroPython 2026! Your support is making a huge difference. We are so grateful for your sponsorship and are thrilled to have you with us. 🙌 SPONSOR_HANDLE SPONSOR_URL", + "🚀✨ A huge thank you to SPONSOR_NAME for sponsoring EuroPython 2026! Your support helps make this event extraordinary. 🙌 SPONSOR_HANDLE SPONSOR_URL", ]; const communityMessages = [ - "🎉✨ A warm thank you to SPONSOR_NAME for supporting EuroPython 2025! We're proud to be a space where communities come together, and we value the opportunity to collaborate with other communities and open-source projects. 🙌 SUPPORTER_HANDLE SUPPORTER_URL", + "🎉✨ A warm thank you to SPONSOR_NAME for supporting EuroPython 2026! We're proud to be a space where communities come together, and we value the opportunity to collaborate with other communities and open-source projects. 🙌 SUPPORTER_HANDLE SUPPORTER_URL", ]; const getRandomMessage = (messages: any) => { diff --git a/src/pages/media/speaker/[slug].astro b/src/pages/media/speaker/[slug].astro index 431d61208..0cccf5073 100644 --- a/src/pages/media/speaker/[slug].astro +++ b/src/pages/media/speaker/[slug].astro @@ -62,7 +62,8 @@ const { entry } = Astro.props;