diff --git a/pwa/app/(common)/events/components/EventsPage.tsx b/pwa/app/(common)/events/components/EventsPage.tsx index a6eb04d2f..d9df5b941 100644 --- a/pwa/app/(common)/events/components/EventsPage.tsx +++ b/pwa/app/(common)/events/components/EventsPage.tsx @@ -36,13 +36,13 @@ export default function EventsPage({ events }: EventsPageProps) { city: "Lille", }, startDate: { - date: "2025-09-18", + date: "2026-09-17", }, endDate: { - date: "2025-09-19", + date: "2026-09-18", }, picture: `/images/con/og-2021.png`, - title: "API Platform Conference 2025", + title: "API Platform Conference 2026", slug: "api-con", }; diff --git a/pwa/app/(con)/[locale]/con/2025/components/AfterMovie.tsx b/pwa/app/(con)/[locale]/con/2025/components/AfterMovie.tsx new file mode 100644 index 000000000..2191a39ce --- /dev/null +++ b/pwa/app/(con)/[locale]/con/2025/components/AfterMovie.tsx @@ -0,0 +1,29 @@ +"use client"; +import SectionTitle from "components/con/common/typography/SectionTitle"; +import Section from "components/con/home/Section"; +import { useContext } from "react"; +import { LanguageContext } from "contexts/con/LanguageContext"; +import SectionSubTitle from "components/con/common/typography/SectionSubtitle"; + +export default function AfterMovie() { + const { t, Translate } = useContext(LanguageContext); + return ( +
+
+ + + + {t("2024.aftermovie.subtitle")} + +
+
+ ); +} diff --git a/pwa/app/(con)/[locale]/con/2025/components/HomePage.tsx b/pwa/app/(con)/[locale]/con/2025/components/HomePage.tsx index 93d293cbb..56506eca8 100644 --- a/pwa/app/(con)/[locale]/con/2025/components/HomePage.tsx +++ b/pwa/app/(con)/[locale]/con/2025/components/HomePage.tsx @@ -40,6 +40,9 @@ const HomePage = ({ speakers, partners, images }: HomePageProps) => { {t("2025.baseline")}

+ {currentEdition === "2025" && ( {t("buy_tickets")} diff --git a/pwa/app/(con)/[locale]/con/2025/page.tsx b/pwa/app/(con)/[locale]/con/2025/page.tsx index e35758b05..8fdc6d49b 100644 --- a/pwa/app/(con)/[locale]/con/2025/page.tsx +++ b/pwa/app/(con)/[locale]/con/2025/page.tsx @@ -20,7 +20,7 @@ export async function generateMetadata({ params }: Props): Promise { alternates: { languages: { en: locale === "en" ? undefined : "/con/2025", - fr: locale === "fr" ? undefined : "/fr/con/2024", + fr: locale === "fr" ? undefined : "/fr/con/2025", }, }, }; diff --git a/pwa/app/(con)/[locale]/con/2025/review/components/Review/ReviewCover.tsx b/pwa/app/(con)/[locale]/con/2025/review/components/Review/ReviewCover.tsx new file mode 100644 index 000000000..b84f4cf15 --- /dev/null +++ b/pwa/app/(con)/[locale]/con/2025/review/components/Review/ReviewCover.tsx @@ -0,0 +1,43 @@ +"use client"; +import ReviewCoverBase from "components/con/review/ReviewCover"; +import { useContext } from "react"; +import { LanguageContext } from "contexts/con/LanguageContext"; + +export default function ReviewCover() { + const { t, Translate, locale } = useContext(LanguageContext); + return ( + +

{t("2025.review.subtitle_1")}

+ + {t("2025.review.link")} + + ), + link2: ( + + {t("2025.review.link2")} + + ), + }} + /> + + } + /> + ); +} diff --git a/pwa/app/(con)/[locale]/con/2025/review/components/Review/en.tsx b/pwa/app/(con)/[locale]/con/2025/review/components/Review/en.tsx new file mode 100644 index 000000000..d45da2e33 --- /dev/null +++ b/pwa/app/(con)/[locale]/con/2025/review/components/Review/en.tsx @@ -0,0 +1,445 @@ +/* eslint-disable react/no-unescaped-entities */ +"use client"; +import React from "react"; +import Button from "components/con/common/Button"; +import useDynamicRefs from "hooks/con/useDynamicRefs"; +import ReviewItem from "components/con/review/ReviewItem"; +import LinedTitle from "components/con/common/typography/LinedTitle"; + +export default function ReviewList() { + const [, setRef] = useDynamicRefs(); + const reviewRef = setRef("review-list"); + + return ( +
+
+ + 10 + years of innovation + + } + > + Major announcements made +

+ The opening keynote brought some major announcements: FrankenPHP and + API Platform are getting powerful new features including support for + gRPC (enabling faster, high-performance APIs), the ability to write + PHP extensions in Go. +

+

+ These innovations open up exciting new possibilities for the PHP + community, particularly in terms of performance, scalability, and + interoperability with other technologies. +

+
+ + 33 + High-Level Talks + + } + > + + Exclusive content for all skill levels + +

+ On September 18 and 19, Lille became the meeting point for key + figures in the PHP ecosystem. The program featured the latest + innovations and trends in modern web development, highlighted + throughout the event by strong representation from communities and + personalities such as Symfony, Laravel, or Go. +

+ +
+ + 33 + partners + + } + > + + Partners from across the ecosystem + +

+ Thank you to our Gold sponsors:{" "} + + Sensiolabs + + ,{" "} + + Sylius + {" "} + and{" "} + + Ibexa + + . +

+

+ Thanks also to our Silver sponsors:{" "} + + Packagist + + ,{" "} + + Vonage + + ,{" "} + + NRB Group + + ,{" "} + + Akawaka + + ,{" "} + + Clever Cloud + + ,{" "} + + Perfect Corp + + ,{" "} + + Fairness + + ,{" "} + + SMTP Labs + + ,{" "} + + Emagma + + ,{" "} + + Sweeek + {" "} + and{" "} + + Upsun + + . +

+

+ Thank you to our Bronze sponsors:{" "} + + Darkwood + + ,{" "} + + baksla.sh + {" "} + ,{" "} + + Sylvain Combraque + + ,{" "} + + CBA Informatique + {" "} + and{" "} + + Lior Chamla + + . +

+

+ Many thanks to our Copper sponsors:{" "} + + Fork it! + {" "} + and{" "} + + Thomas Dutrion + + . +

+

+ Finally, thanks to our community and media partners:{" "} + + Laravel France + + ,{" "} + + Motiv'Her + + ,{" "} + + Symfony + + ,{" "} + + ChtiteDev + + ,{" "} + + PHP Brussels + + ,{" "} + + WeLoveDevs + + ,{" "} + + Larabelles + + ,{" "} + + Archimag + + ,{" "} + + JL Recrutement + + ,{" "} + + MongoDB + + ,{" "} + + Euratechnologies + {" "} + and{" "} + + Hôtels de Lille + + . +

+ +
+ + 300 + elephants unleashed + + } + > + It’s alive! +

+ FrankenPHP ElePHPants came to life and met their first humans during + the conference. The merch sold out in no time! +

+

+ Our little monsters will return at future events. Stay tuned for + their next release by following us on social media! +

+
+ + 1 + birthday party + + } + > + + Happy birthday to API Platform! + +

+ We marked API Platform’s 10th anniversary in style with music, a + magic show, and a beautiful birthday cake. +

+

+ As always, community drinks were sponsored by{" "} + JL Recrutement, thank + you to them! +

+
+
+
+ ); +} diff --git a/pwa/app/(con)/[locale]/con/2025/review/components/Review/fr.tsx b/pwa/app/(con)/[locale]/con/2025/review/components/Review/fr.tsx new file mode 100644 index 000000000..d4d970c79 --- /dev/null +++ b/pwa/app/(con)/[locale]/con/2025/review/components/Review/fr.tsx @@ -0,0 +1,453 @@ +/* eslint-disable react/no-unescaped-entities */ +"use client"; +import React from "react"; +import Button from "components/con/common/Button"; +import useDynamicRefs from "hooks/con/useDynamicRefs"; +import ReviewItem from "components/con/review/ReviewItem"; +import LinedTitle from "components/con/common/typography/LinedTitle"; + +export default function ReviewList() { + const [, setRef] = useDynamicRefs(); + const reviewRef = setRef("review-list"); + + return ( +
+
+ + 10 + ans d'innovation + + } + > + + Et toujours de grandes ambitions pour l’écosystème PHP + +

+ La keynote d’ouverture a dévoilé plusieurs annonces majeures : + FrankenPHP et API Platform vont bénéficier de nouvelles + fonctionnalités puissantes, notamment le support de gRPC (permettant + des API plus rapides et performantes) et la possibilité d’écrire des + extensions PHP en Go. +

+

+ De nouvelles perspectives passionnantes pour la communauté PHP, + notamment en termes de performance, déploiement, scalabilité et + d’interopérabilité avec d’autres technologies. +

+
+ + 33 + Conférences + + } + > + + Du contenu exclusif pour tous les niveaux + +

+ Les 18 et 19 septembre, Lille est devenu le point de rendez-vous des + grandes figures de l’écosystème PHP. Au programme : les dernières + innovations et tendances du web moderne, mises à l’honneur tout au + long de l’événement, avec des communautés et personnalités + brillamment représentées : Symfony, Laravel, Go... +

+ +
+ + 33 + partenaires + + } + > + + Des soutiens venus de tous les horizons + +

+ Un immense merci à nos sponsors Gold :{" "} + + Sensiolabs + + ,{" "} + + Sylius + {" "} + et{" "} + + Ibexa + + . +

+

+ Merci également à nos sponsors Silver :{" "} + + Packagist + + ,{" "} + + Vonage + + ,{" "} + + NRB Group + + ,{" "} + + Akawaka + + ,{" "} + + Clever Cloud + + ,{" "} + + Perfect Corp + + ,{" "} + + Fairness + + ,{" "} + + SMTP Labs + + ,{" "} + + Emagma + + ,{" "} + + Sweeek + {" "} + et{" "} + + Upsun + + . +

+

+ Nous sommes reconnaissants du soutien de nos sponsors Bronze{" "} + + Darkwood + + ,{" "} + + baksla.sh + {" "} + ,{" "} + + Sylvain Combraque + + ,{" "} + + CBA Informatique + {" "} + et{" "} + + Lior Chamla + + . +

+

+ Un grand merci à nos sponsors Copper :{" "} + + Fork it! + {" "} + et{" "} + + Thomas Dutrion + + . +

+

+ Enfin, nous tenons à remercier nos partenaires communautaires et + médias :{" "} + + Laravel France + + ,{" "} + + Motiv'Her + + ,{" "} + + Symfony + + ,{" "} + + ChtiteDev + + ,{" "} + + PHP Brussels + + ,{" "} + + WeLoveDevs + + ,{" "} + + Larabelles + + ,{" "} + + Archimag + + ,{" "} + + JL Recrutement + + ,{" "} + + MongoDB + + ,{" "} + + Euratechnologies + {" "} + et{" "} + + Hôtels de Lille + + . +

+ +
+ + 300 + elePHPants lâchés dans la nature + + } + > + It’s alive! +

+ Les elePHPants FrankenPHP ont vu le jour et rencontré leurs premiers + humains lors de la conférence. Ils ont été adoptés en un rien de + temps ! +

+

+ Nos petits monstres feront leur retour lors de prochains événements. + Restez à l’affût de leur prochaine apparition en nous suivant sur + les réseaux sociaux. +

+
+ + 1 + fête d’anniversaire mémorable + + } + > + + Joyeux anniversaire API Platform ! + +

+ Nous avons célébré les 10 ans d’API Platform en musique, avec un + spectacle de magie, et soufflé les bougies sur un gâteau + d’anniversaire flamboyant ! +

+

+ Et comme chaque année, les boissons (et le fameux punch !) étaient + offerts par le cabinet{" "} + JL Recrutement. Un + immense merci à eux ! +

+
+
+
+ ); +} diff --git a/pwa/app/(con)/[locale]/con/2025/review/page.tsx b/pwa/app/(con)/[locale]/con/2025/review/page.tsx new file mode 100644 index 000000000..b6a5c790b --- /dev/null +++ b/pwa/app/(con)/[locale]/con/2025/review/page.tsx @@ -0,0 +1,73 @@ +import { getAllEditionPictures } from "api/con/editions"; +import Cover from "./components/Review/ReviewCover"; +import ReviewListFr from "./components/Review/fr"; +import ReviewListEn from "./components/Review/en"; +import Image from "next/image"; +import PictureGallery from "components/con/common/PictureGallery"; +import { Locale, i18n } from "i18n/i18n-config"; +import { Metadata } from "next"; +import AfterMovie from "../components/AfterMovie"; + +type Props = { + params: { locale: Locale }; +}; +export async function generateMetadata({ params }: Props): Promise { + const locale = params.locale || i18n.defaultLocale; + const dictionary = await import(`i18n/meta/${locale}.json`); + + return { + title: dictionary.review.title, + description: dictionary.review.description.replace("%edition%", "2025"), + openGraph: { + title: `${dictionary.review.title} - API Platform Conference 2025`, + description: dictionary.review.description.replace("%edition%", "2025"), + }, + twitter: { + title: `${dictionary.review.title} - API Platform Conference 2025`, + description: dictionary.review.description.replace("%edition%", "2025"), + }, + alternates: { + languages: { + en: locale === "en" ? undefined : "/con/2025/review", + fr: locale === "fr" ? undefined : "/fr/con/2025/review", + }, + }, + }; +} + +export default async function Page({ params }: { params: { locale: Locale } }) { + const images = await getAllEditionPictures("2025"); + return ( + <> + + { + params.locale === "fr" ? ( + + ) : null /*FIXME: find an other way to translate this page*/ + } + { + params.locale === "en" ? ( + + ) : null /*FIXME: find an other way to translate this page*/ + } +
+ +
+ + {images.map((image: string) => ( + + ))} + + + ); +} diff --git a/pwa/app/(con)/[locale]/con/2026/components/HomePage.tsx b/pwa/app/(con)/[locale]/con/2026/components/HomePage.tsx new file mode 100644 index 000000000..710835a05 --- /dev/null +++ b/pwa/app/(con)/[locale]/con/2026/components/HomePage.tsx @@ -0,0 +1,164 @@ +"use client"; +import Button from "components/con/common/Button"; +import SpeakerList from "components/con/speakers/SpeakerList"; +import SectionTitle from "components/con/common/typography/SectionTitle"; +import SectionSubTitle from "components/con/common/typography/SectionSubtitle"; +import Venue from "components/con/home/Venue"; +import Image from "next/image"; +import Partners from "components/con/home/Partners"; +import LookingSponsorCard from "components/con/home/LookingSponsorCard"; +import { Partner, Speaker } from "types/con"; +import { useContext } from "react"; +import { LanguageContext } from "contexts/con/LanguageContext"; +import Section from "components/con/home/Section"; +import Cover from "components/con/home/Cover"; +import PictureGallery from "components/con/common/PictureGallery"; +import AfterMovie from "../../2025/components/AfterMovie"; + +type HomePageProps = { + speakers: Speaker[]; + partners: Partner[]; + images: string[]; +}; + +const HomePage = ({ speakers, partners, images }: HomePageProps) => { + const { t, Translate, locale } = useContext(LanguageContext); + return ( + <> + + {t("review.button")} + + } + /> +
+
+ + + + + + {t("last_edition.subtitle_link")} + + ), + }} + /> + + + {images.map((image: string) => ( + + ))} + +
+
+
+ +
+
+
+ + + + + + + +
+
+
+
+ + + + + + {t("2026.our_speakers.subtitle_link")} + + ), + }} + /> + + + {speakers.length > 9 ? ( + + ) : null} +
+
+ +
+
+ + + + +
+
+
+
+ {t("sponsorship.they_trust_us", { year: "2025" })} +
+ +
+
+
+ + ); +}; + +export const revalidate = 43200; + +export default HomePage; diff --git a/pwa/app/(con)/[locale]/con/2026/components/Logo.tsx b/pwa/app/(con)/[locale]/con/2026/components/Logo.tsx new file mode 100644 index 000000000..32e16602b --- /dev/null +++ b/pwa/app/(con)/[locale]/con/2026/components/Logo.tsx @@ -0,0 +1,552 @@ +export default function Logo() { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/pwa/app/(con)/[locale]/con/2026/layout.tsx b/pwa/app/(con)/[locale]/con/2026/layout.tsx new file mode 100644 index 000000000..6d9616014 --- /dev/null +++ b/pwa/app/(con)/[locale]/con/2026/layout.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import LayoutBase from "components/con/layout/LayoutBase"; +import ContactCard from "components/con/layout/ContactCard"; +import nav from "data/con/2026/nav"; +import footer from "data/con/2026/footer"; +import { Metadata } from "next"; +import { getEditionEventData } from "utils/con"; +import { i18n } from "i18n/i18n-config"; +import { getRootUrl } from "utils"; + +type Props = { + params: { edition: string; locale: string }; +}; + +export async function generateMetadata({ params }: Props): Promise { + // read route params + const locale = params.locale || i18n.defaultLocale; + + const dictionary = await import(`i18n/meta/${locale}.json`); + + const URL = `${getRootUrl()}/con/2026`; + + return { + title: { + default: dictionary[2026].title, + template: `%s - API Platform Conference 2026`, + }, + description: dictionary[2026].description, + openGraph: { + url: URL, + title: dictionary[2026].title, + description: dictionary[2025].description, + }, + twitter: { + title: dictionary[2026].title, + description: dictionary[2026].description, + }, + }; +} + +function EditionLayout({ children }: { children: React.ReactNode }) { + const eventData = getEditionEventData("2026"); + return ( + +