diff --git a/src/components/pages/home/speakers/speakers.jsx b/src/components/pages/home/speakers/speakers.jsx
index eb2130e..00da8d1 100644
--- a/src/components/pages/home/speakers/speakers.jsx
+++ b/src/components/pages/home/speakers/speakers.jsx
@@ -313,6 +313,7 @@ const ITEMS = [
{
// 20
+ id: '50',
name: 'Engin Diri',
position: 'Customer Experience Architect Pulumi',
content:
@@ -323,10 +324,12 @@ const ITEMS = [
time: '10:25',
title: 'How To Add Infrastructure Provisioning to Your Backstage Templates',
duration: '90 min',
+ isWorkshop: true,
},
{
// 21
+ id: '51',
name: 'Mikkel Mørk Hegnhøj',
position: 'Head of Product and DevRel Fermyon',
content:
@@ -337,10 +340,12 @@ const ITEMS = [
time: '10:25',
title: 'Hands on with WebAssembly and Kubernetes',
duration: '90 min',
+ isWorkshop: true,
},
{
// 22
+ id: '52',
name: 'Nic Vermande',
position: 'Head of Developer Relations Spectro Cloud',
content:
@@ -352,10 +357,12 @@ const ITEMS = [
title:
'Mastering Cluster API and GitOps: Deep Dive into Extensible Components for Building Production-Ready Kubernetes Clusters',
duration: '90 min',
+ isWorkshop: true,
},
{
// 23
+ id: '53',
name: 'Thomas Labarussias',
position: 'OSS and Ecosystem Advocate Sysdig',
content:
@@ -366,10 +373,12 @@ const ITEMS = [
time: '13:40',
title: 'Detecting unexpected behavior and intrusions with Falco',
duration: '90 min',
+ isWorkshop: true,
},
{
// 24
+ id: '53',
name: 'Vicente J. Jiménez Miras',
position: 'Security Content Engineer Sysdig',
content:
@@ -378,6 +387,7 @@ const ITEMS = [
time: '13:40',
title: 'Detecting unexpected behavior and intrusions with Falco',
duration: '90 min',
+ isWorkshop: true,
},
{
diff --git a/src/components/pages/workshops/hero/hero.jsx b/src/components/pages/workshops/hero/hero.jsx
new file mode 100644
index 0000000..71833bd
--- /dev/null
+++ b/src/components/pages/workshops/hero/hero.jsx
@@ -0,0 +1,31 @@
+import React from 'react';
+
+import Button from 'components/shared/button';
+
+const TITLE = 'Workshops schedule for ';
+const DESCRIPTION =
+ "Workshops are included in the schedule for the Kubernetes Community Days Denmark. Attendance is included with the conference ticket and available on a first-come first-served basis.";
+
+const Hero = () => (
+
+
+
+
+ {DESCRIPTION}
+
+
+
+
+);
+
+export default Hero;
diff --git a/src/components/pages/workshops/hero/index.js b/src/components/pages/workshops/hero/index.js
new file mode 100644
index 0000000..cffaeab
--- /dev/null
+++ b/src/components/pages/workshops/hero/index.js
@@ -0,0 +1,3 @@
+import Hero from './hero';
+
+export default Hero;
diff --git a/src/components/pages/workshops/schedule/images/engin-diri.jpg b/src/components/pages/workshops/schedule/images/engin-diri.jpg
new file mode 100644
index 0000000..8995611
Binary files /dev/null and b/src/components/pages/workshops/schedule/images/engin-diri.jpg differ
diff --git a/src/components/pages/workshops/schedule/images/mikkel-hegnhoj.jpg b/src/components/pages/workshops/schedule/images/mikkel-hegnhoj.jpg
new file mode 100644
index 0000000..4e91a43
Binary files /dev/null and b/src/components/pages/workshops/schedule/images/mikkel-hegnhoj.jpg differ
diff --git a/src/components/pages/workshops/schedule/images/nicolas-vermande.jpg b/src/components/pages/workshops/schedule/images/nicolas-vermande.jpg
new file mode 100644
index 0000000..14fcc5a
Binary files /dev/null and b/src/components/pages/workshops/schedule/images/nicolas-vermande.jpg differ
diff --git a/src/components/pages/workshops/schedule/images/thomas-labarussias.jpg b/src/components/pages/workshops/schedule/images/thomas-labarussias.jpg
new file mode 100644
index 0000000..c83c360
Binary files /dev/null and b/src/components/pages/workshops/schedule/images/thomas-labarussias.jpg differ
diff --git a/src/components/pages/workshops/schedule/images/vicente-miras.jpg b/src/components/pages/workshops/schedule/images/vicente-miras.jpg
new file mode 100644
index 0000000..931bc0f
Binary files /dev/null and b/src/components/pages/workshops/schedule/images/vicente-miras.jpg differ
diff --git a/src/components/pages/workshops/schedule/index.js b/src/components/pages/workshops/schedule/index.js
new file mode 100644
index 0000000..eb56775
--- /dev/null
+++ b/src/components/pages/workshops/schedule/index.js
@@ -0,0 +1,3 @@
+import Workshops from './workshops';
+
+export default Workshops;
diff --git a/src/components/pages/workshops/schedule/workshops.jsx b/src/components/pages/workshops/schedule/workshops.jsx
new file mode 100644
index 0000000..3d448ca
--- /dev/null
+++ b/src/components/pages/workshops/schedule/workshops.jsx
@@ -0,0 +1,280 @@
+/* eslint-disable react/prop-types */
+import clsx from 'clsx';
+import React, { useEffect, useState } from 'react';
+
+import Button from 'components/shared/button';
+import Modal from 'components/shared/modal';
+
+import EnginDiri from './images/engin-diri.jpg';
+import MikkelHegnhoj from './images/mikkel-hegnhoj.jpg';
+import NicVermande from './images/nicolas-vermande.jpg';
+import ThomasLabarussias from './images/thomas-labarussias.jpg';
+import VicenteMiras from './images/vicente-miras.jpg';
+
+// TODO: merge with ITEMS array from components/pages/home/speakers
+const ITEMS = [
+ {
+ id: '50',
+ time: '10:25',
+ title: 'How To Add Infrastructure Provisioning to Your Backstage Templates',
+ duration: '90 min',
+ speakers: [
+ {
+ id: '20',
+ name: 'Engin Diri',
+ photo: EnginDiri,
+ },
+ ],
+ presentation:
+ 'Software templates in Backstage are vital for bootstrapping new projects, effectively reducing startup time and masking complexities. When provisioning infrastructure, questions arise on modeling both day-1 and day-2 operations and ensuring compliance with security and company policies.
In this interactive workshop, I will lead participants through these essential concepts. We\'ll explore how to integrate infrastructure provisioning into software templates and provide a detailed walkthrough of a reference implementation, including day-2 operations.
By the end, attendees will:' +
+ ' - Understand the benefits of provisioning with Backstage' +
+ ' - Identify challenges in provisioning infrastructure in templates' +
+ ' - Apply best practices through Backstage' +
+ ' - Automate continuous delivery and verification of changes using GitOps with Pulumi' +
+ ' - Build self-service enabled software templates in Backstage',
+ coincidedEvent: {
+ id: '51',
+ time: '10:25',
+ title: 'Hands on with WebAssembly and Kubernetes',
+ duration: '90 min',
+ speakers: [
+ {
+ id: '21',
+ name: 'Mikkel Mørk Hegnhøj',
+ photo: MikkelHegnhoj,
+ },
+ ],
+ presentation:
+ 'Learning a new technology can be daunting, and getting started with WebAssembly on the server requires getting up to speed with both new concepts and new tooling. With Spin (https://github.com/fermyon/spin), we want to bring a delightful developer experience to building, distributing, and running serverless functions and microservices with WebAssembly. As with any exciting early ecosystem, there are a lot of tools, libraries, and CLIs out there, and figuring out how and if they work together can be difficult. With Spin, our goal is to empower developers to go from nothing to building and iterating on their application in just a few commands: `spin new` , `spin build`, and `spin up` is all you need to remember. In this tutorial, you will get hands-on with Spin and see how Spin applications can run in a Kubernetes environment.',
+ },
+ },
+ {
+ id: '52',
+ time: '13:40',
+ title: 'Mastering Cluster API and GitOps: Deep Dive into Extensible Components for Building Production-Ready Kubernetes Clusters',
+ duration: '90 min',
+ speakers: [
+ {
+ id: '22',
+ name: 'Nic Vermande',
+ photo: NicVermande
+ }
+ ],
+ presentation:
+ 'There are many different ways you can bootstrap Kubernetes clusters, with various degrees of complexity. Modern Kubernetes installers automate manual tasks but generally, the more they abstract away complexity, the more opinionated they are — and that restricts your choice. Cluster API is different. It is one of the most flexible and efficient tools for managing the Kubernetes lifecycle, whether used for deployments, upgrades or scaling operations. While Cluster API is a powerful tool for provisioning Kubernetes clusters, it doesn\'t cover everything. Essential add-on components and software, such as node auto-scalers, CNI, ingress controllers, and other key infrastructure elements, are not included. In this workshop, you will delve into how to supercharge Cluster API by integrating it with various solutions to build production-ready clusters, with GitOps as the automation master.',
+ coincidedEvent: {
+ id: '53',
+ time: '13:40',
+ title: 'Detecting unexpected behavior and intrusions with Falco',
+ duration: '90 min',
+ speakers: [
+ {
+ id: '23',
+ name: 'Thomas Labarussias',
+ photo: ThomasLabarussias,
+ },
+ {
+ id: '24',
+ name: 'Vicente J. Jiménez Miras',
+ photo: VicenteMiras,
+ },
+ ],
+ presentation:
+ "The adoption of containers and orchestration systems, such as Kubernetes, has skyrocketed over the last few years. The popularity of these platforms makes them common targets for cyber criminals. Kubernetes combats this risk with built in controls but what if you want to observe the behavior of your pods at runtime to detect intrusions? In this entry-level tutorial, the instructors will dive into cloud threat detection and explain how to detect unexpected behavior and intrusion. This tutorial offers a hands-on introduction to Falco, an open source CNCF incubation project. Every participant will use a web browser to access their own lab environment, in which they will use Falco to identify and notify of suspicious behaviors and intrusions. This session targets security practitioners that are new to cloud native and want to expand their knowledge of runtime security and Falco.",
+ },
+ },
+];
+
+const Workshops = ({ location }) => {
+ const [isModalVisible, setIsModalVisible] = useState(false);
+ const [isCoincidedEvent, setIsCoincidedEvent] = useState(false);
+ const [modalDataId, setModalDataId] = useState(0);
+
+ const handleModalShow = (id) => {
+ document.body.classList.add('overflow-hidden');
+ setIsModalVisible(true);
+ setModalDataId(id);
+ };
+
+ const handleModalHide = () => {
+ document.body.classList.remove('overflow-hidden');
+ setIsModalVisible(false);
+ setIsCoincidedEvent(false);
+ setModalDataId(0);
+ };
+
+ useEffect(() => {
+ if (typeof window !== `undefined`) {
+ const { state = {} } = location;
+
+ if (state?.modalId) {
+ handleModalShow(Number(state.modalId));
+ }
+
+ if (state?.isCoincidedEvent) {
+ setIsCoincidedEvent(true);
+ }
+ }
+ }, [location]);
+
+ return (
+
+