Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lyonjs100): add program page #476

Merged
merged 3 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/evenement/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default async function EventPage({ params: { slug } }: { params: { slug:
<EventMarkup event={event} />
</main>
);
} catch (e) {
} catch {
notFound();
}
}
Expand All @@ -50,7 +50,7 @@ export async function generateMetadata({ params: { slug } }: { params: { slug: s
description,
},
};
} catch (e) {
} catch {
return {};
}
}
11 changes: 11 additions & 0 deletions app/lyonjs-100/programme/Programme.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.container {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
padding: 20px 0;
}

.introduction {
color: var(--white-0);
margin-top: 24px;
}
40 changes: 40 additions & 0 deletions app/lyonjs-100/programme/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Metadata } from 'next';
import { H1 } from '../../../modules/atoms/remark/Titles';
import { speakers } from '../../../data/lyonjs100-speakers';
import { Talk } from '../../../modules/program/Talk';
import styles from './Programme.module.css';

const title = 'LyonJS | LyonJS πŸ’― | Programme';
const description = 'Le programme de la journΓ©e du LyonJS 100';

export const revalidate = 3600;

export const metadata: Metadata = {
title,
description,
twitter: {
title,
description,
},
openGraph: {
title,
description,
},
};

export default function LyonJS100() {
return (
<main>
<H1>Programme</H1>
<p className={styles.introduction}>
Voici un aperΓ§u de quelques talks au programme de cette journΓ©e, Et d’autres talks vous attendent tout au long
de la journΓ©e ! Le programme dΓ©taillΓ© est encore en validation.
</p>
<div className={styles.container}>
{speakers.map((speaker) => (
<Talk speaker={speaker} key={speaker.name} />
))}
</div>
</main>
);
}
63 changes: 47 additions & 16 deletions data/lyonjs100-speakers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
type Speaker = {
export type Speaker = {
name: string;
talk?: {
title: string;
description: string;
description?: string;
};
avatarUrl: string;
social: {
Expand All @@ -11,26 +11,57 @@ type Speaker = {
};
};
export const speakers: Array<Speaker> = [
{ name: 'Matthieu Lux', avatarUrl: '/speakers/matthieu-lux.webp', social: { twitter: 'swiip', linkedin: 'swiip' } },
// { name: 'JΓ©rΓ©mie Patonnier', avatarUrl: '/speakers/jeremie-patonnier.jpg', social: { twitter: 'jeremiepat' } },
{
name: 'Jonny Burger',
avatarUrl: '/speakers/jonny-burger.png',
social: { twitter: 'JNYBGR', linkedin: 'jonny-burger-4115109b' },
name: 'Matthieu Lux',
avatarUrl: '/speakers/matthieu-lux.webp',
social: { twitter: 'swiip', linkedin: 'swiip' },
talk: {
title: 'Astro, le framework Web JS multi page',
description: `Et si finalement, on faisait des sites avec plusieurs pages ?

Astro est d'abord un framework Web JS basΓ© sur Vite qui permet d'utiliser pratiquement n'importe quel framework frontend: React, Vue, mais aussi Svelte, Solid, Preact... Et mΓͺme plusieurs d'entre eux Γ  la fois si nΓ©cessaire. Au milieu des tout puissants Next et Nuxt, ce trublion propose une voie Γ©tonnement simple : revenir au site multi page ! Cela lui permet d'afficher des performances incroyables.

(Pratiquement ?) Tous les serveurs Web JS modernes proposent ni plus ni moins qu'une application JS qui ne fait que faire semblant de se comporter comme un site Web. Cela ne fonctionne pas si mal bien sΓ»r, mais cela a tout de mΓͺme un coΓ»t, Γ  la fois en performance et en complexitΓ©. Astro propose une autre voie, on revient aux vraies pages Web et Γ  la navigation entre deux pages. On se rend vite compte que cela ne marche pas si mal, bizarrement, les navigateurs le gΓ¨re plutΓ΄t bien ! Mais attention, avec tout le confort et la puissance des outils JS moderne !

Chez Proton, nous nous sommes engagés sur Astro pour les sites Web. Une partie est maintenant en production, une autre est encore en cours. Outre les fonctionnalités du framework, je vous propose un retour d'experience sur notre migration, nos difficultés et nos succès.`,
},
},
{
name: `Bientôt lui 🀫`,
avatarUrl: '/speakers/secret.png',
social: {},
name: 'JΓ©rΓ©mie Patonnier',
avatarUrl: '/speakers/jeremie-patonnier.jpg',
social: { twitter: 'jeremiepat' },
talk: {
title: "Deno, l'avenir du dev JS/TS ?",
description:
"Deno est la nouvelle alternative Γ  Node... si on en crois Ryan Dahl, le crΓ©ateur de ces deux environnements ! Si Node est devenus un standard industriel pour le dΓ©veloppement de serveur d'API et d'application Web Front, quel est l'intΓ©rΓͺt de Deno ? Juste un runtime JS de plus ? Que nenni, Deno, c'est Node avec 10 d'expΓ©rience en plus, avec des paradigme plus moderne, des choix d'architecture plus robuste et tout un Γ©cosystΓ¨me pour supporter l'usage de JavaScript et TypeScript Γ  grande Γ©chelle. Il y a beaucoup Γ  dire... alors si on se prenais un petit moment pour faire le tour de ce nouvel environnement d'exΓ©cution JS qui va trΓ¨s vraisemblablement changer nos pratiques de dev dans les 5 ans Γ  venir ?",
},
},
{
name: `Elle aussi !! 🀩`,
avatarUrl: '/speakers/secret.png',
social: {},
name: 'Jonny Burger',
avatarUrl: '/speakers/jonny-burger.png',
social: { twitter: 'JNYBGR', linkedin: 'jonny-burger-4115109b' },
talk: {
title: 'How to build a video editor in React',
description: `In this very concrete talk, I'll give an outline in 30 minutes on how to build a video editor from scratch.
We'll talk about:

- Building a canvas with user interactions
- Creating a timeline
- Adding captioning with AI functionality
- Rendering out the video!

None of these will be in-depth but by the end of the talk, you shall have no fear if you want to build your own video editor!`,
},
},
{
name: `Non pas lui !! ?? 😱`,
avatarUrl: '/speakers/secret.png',
social: {},
name: `Ayoub Alouane`,
avatarUrl: '/speakers/ayoub-alouane.png',
social: { twitter: 'alouane_med', linkedin: 'med-ayb-alouane' },
talk: {
title: "La Performance Web : Le cas de l'Afrique",
description: `Nous partons souvent du principe que tout le monde dispose d'une bonne connexion Internet et d'un matΓ©riel informatique de haute spΓ©cification. Bien que cela puisse Γͺtre vrai dans certaines rΓ©gions, ce n'est pas le cas dans le monde entier. Je souhaite attirer l'attention sur l'Afrique, oΓΉ de nombreux pays luttent contre de faibles connexions 3G coΓ»teuses, en fonction de la quantitΓ© de donnΓ©es consommΓ©es. Ceci est dΓ» Γ  l'infrastructure limitΓ©e du continent, conduisant Γ  une dΓ©pendance aux connexions mobiles.

Compte tenu de ces circonstances, une utilisation efficace des donnΓ©es avec une bonne performance web devient une prioritΓ©. Ainsi, notre session se concentrera sur les dΓ©fis rencontrΓ©s par les utilisateurs et les dΓ©veloppeurs africains, et comment le tΓ©lΓ©chargement et l'exΓ©cution de grandes quantitΓ©s de JavaScript exacerbe les problΓ¨mes de consommation de donnΓ©es et de performance. Nous explorerons comment les frameworks js existants ont tentΓ© de rΓ©soudre le problΓ¨me et comment Qwik, avec son approche innovante de la Resumability, prΓ©sente une solution transformatrice Γ  ces dΓ©fis. Contrairement aux SPAs traditionnels, la Resumability de Qwik rΓ©duit considΓ©rablement la charge initiale de JavaScript, permettant aux applications de devenir interactives plus rapidement, mΓͺme sur des connexions lentes.`,
},
},
];
44 changes: 4 additions & 40 deletions modules/person/ListOfPeople.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,18 @@
import styles from './person-card.module.css';
import Image from 'next/image';
import { IconLink } from '../navigation/links/IconLink';
import { Twitter } from '../icons/Twitter';
import { Linkedin } from '../icons/Linkedin';
import React from 'react';
import { Person } from './types';
import { PersonDisplay } from './PersonDisplay';

type Props = {
people: Array<{
name: string;
description?: string;
avatarUrl: string;
social: {
twitter?: string;
linkedin?: string;
};
}>;
people: Array<Person>;
};

export const ListOfPeople = ({ people }: Props) => {
return (
<ul className={styles.container}>
{people.map((person) => (
<li key={person.name}>
<figure className={styles.person}>
<Image src={person.avatarUrl} alt={person.name} width="120" height="120" title={person.name} />
<p>{person.name}</p>
{person.description && <p className={styles.description}>{person.description}</p>}
<div className={styles.socials}>
{person.social.twitter && (
<IconLink
href={`https://twitter.com/${person.social.twitter}`}
target="_blank"
rel="noreferrer noopener"
title={`Compte Twitter de ${person.name}`}
>
<Twitter color="currentColor" size={20} />
</IconLink>
)}
{person.social.linkedin && (
<IconLink
href={`https://www.linkedin.com/in/${person.social.linkedin}`}
target="_blank"
rel="noreferrer noopener"
title={`Compte Linkedin de ${person.name}`}
>
<Linkedin color="currentColor" size={20} />
</IconLink>
)}
</div>
</figure>
<PersonDisplay person={person} />
</li>
))}
</ul>
Expand Down
42 changes: 42 additions & 0 deletions modules/person/PersonDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import styles from './person-card.module.css';
import Image from 'next/image';
import { IconLink } from '../navigation/links/IconLink';
import { Twitter } from '../icons/Twitter';
import { Linkedin } from '../icons/Linkedin';
import React from 'react';
import type { Person } from './types';

type Props = {
person: Person;
};
export const PersonDisplay = ({ person }: Props) => {
return (
<figure className={styles.person}>
<Image src={person.avatarUrl} alt={person.name} width="120" height="120" title={person.name} />
<p>{person.name}</p>
{person.description && <p className={styles.description}>{person.description}</p>}
<div className={styles.socials}>
{person.social.twitter && (
<IconLink
href={`https://twitter.com/${person.social.twitter}`}
target="_blank"
rel="noreferrer noopener"
title={`Compte Twitter de ${person.name}`}
>
<Twitter color="currentColor" size={20} />
</IconLink>
)}
{person.social.linkedin && (
<IconLink
href={`https://www.linkedin.com/in/${person.social.linkedin}`}
target="_blank"
rel="noreferrer noopener"
title={`Compte Linkedin de ${person.name}`}
>
<Linkedin color="currentColor" size={20} />
</IconLink>
)}
</div>
</figure>
);
};
9 changes: 9 additions & 0 deletions modules/person/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type Person = {
name: string;
description?: string;
avatarUrl: string;
social: {
twitter?: string;
linkedin?: string;
};
};
36 changes: 36 additions & 0 deletions modules/program/Talk.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.container {
background-color: var(--background-card);
padding: 2.5rem;
border-radius: 0.5rem;
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 40px;
}

.title {
margin-top: 0;
}

.speaker {
flex-shrink: 0;
}

.description {
font-family: 'Inter', sans-serif;
font-size: 16px;
line-height: 28px;
overflow-wrap: break-word;
}

.description ul {
list-style: inside;
margin-bottom: 20px;
}

@media screen and (min-width: 768px) {
.container {
gap: 60px;
flex-direction: row;
}
}
29 changes: 29 additions & 0 deletions modules/program/Talk.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Speaker } from '../../data/lyonjs100-speakers';
import React from 'react';
import styles from './Talk.module.css';
import { Heading } from '../atoms/heading/Heading';
import { PersonDisplay } from '../person/PersonDisplay';
import { Collapsible } from '../atoms/collapsible/Collapsible';
import dynamic from 'next/dynamic';

const ReactMarkdown = dynamic(() => import('react-markdown').then((module) => module.default));

export const Talk = ({ speaker }: { speaker: Speaker }) => {
return (
<article className={styles.container}>
<div>
<Heading Component={'h2'} className={styles.title}>
{speaker.talk?.title}
</Heading>
{speaker.talk?.description && (
<Collapsible className={styles.description}>
<ReactMarkdown>{speaker.talk.description}</ReactMarkdown>
</Collapsible>
)}
</div>
<div className={styles.speaker}>
<PersonDisplay person={speaker} />
</div>
</article>
);
};
Binary file added public/speakers/ayoub-alouane.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/speakers/lea-coston.jpeg
Binary file not shown.
Loading