diff --git a/source/_layouts/page.html.twig b/source/_layouts/page.html.twig
index a41ae1fe..0192cb19 100644
--- a/source/_layouts/page.html.twig
+++ b/source/_layouts/page.html.twig
@@ -1 +1,7 @@
{% extends "default" %}
+
+{% block body %}
+
{{ page.title }}
+
+ {{ parent() }}
+{% endblock %}
diff --git a/source/_layouts/talk.html.twig b/source/_layouts/talk.html.twig
index a41ae1fe..99acc790 100644
--- a/source/_layouts/talk.html.twig
+++ b/source/_layouts/talk.html.twig
@@ -1 +1,18 @@
-{% extends "default" %}
+{% extends "page.html.twig" %}
+
+{% block body %}
+ {{ parent() }}
+
+ {% include 'talk/slides' with {
+ speakerdeck: page.speakerdeck,
+ } only %}
+
+ {% include 'talk/video' with {
+ video: page.video,
+ } only %}
+
+ {% include 'talk/events' with {
+ events: page.events|reverse,
+ } only %}
+
+{% endblock %}
diff --git a/source/_pages/talks.html.twig b/source/_pages/talks.html.twig
new file mode 100644
index 00000000..a690be56
--- /dev/null
+++ b/source/_pages/talks.html.twig
@@ -0,0 +1,17 @@
+---
+title: Talks and Workshops
+use:
+ - talks
+---
+
+{% for talk in data.talks|sort((a,b) => a.sortable_date < b.sortable_date) %}
+
+
+
+ {{ talk.description }}
+
+{% endfor %}
diff --git a/source/_partials/talk/events.html.twig b/source/_partials/talk/events.html.twig
new file mode 100644
index 00000000..41c8e97a
--- /dev/null
+++ b/source/_partials/talk/events.html.twig
@@ -0,0 +1,15 @@
+{% if events is not empty %}
+ Events
+
+
+ {% for event in events %}
+ {% include 'talk/events/event.html.twig' with {
+ date: event.date,
+ is_online: event.is_online ?? false,
+ location: event.location,
+ name: event.name,
+ url: event.url,
+ } only %}
+ {% endfor %}
+
+{% endif %}
diff --git a/source/_partials/talk/events/event.html.twig b/source/_partials/talk/events/event.html.twig
new file mode 100644
index 00000000..99b54322
--- /dev/null
+++ b/source/_partials/talk/events/event.html.twig
@@ -0,0 +1,10 @@
+
+ {% if url %}
+ {{ name }}
+ {% else %}
+ {{ name }}
+ {% endif %}
+ {% if location %}in {{ location }}{% endif %}
+ {{ is_online ? '(Online)' }}
+ - {{ date|date('jS F Y') }}
+
diff --git a/source/_partials/talk/slides.html.twig b/source/_partials/talk/slides.html.twig
new file mode 100644
index 00000000..e3f101b9
--- /dev/null
+++ b/source/_partials/talk/slides.html.twig
@@ -0,0 +1,9 @@
+{% if speakerdeck.id and speakerdeck.ratio %}
+
+
Slides
+
+ {% include 'talk/speakerdeck' with {
+ data: speakerdeck,
+ } only %}
+
+{% endif %}
diff --git a/source/_partials/talk/speakerdeck.html.twig b/source/_partials/talk/speakerdeck.html.twig
new file mode 100644
index 00000000..863e50df
--- /dev/null
+++ b/source/_partials/talk/speakerdeck.html.twig
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/source/_partials/talk/video.html.twig b/source/_partials/talk/video.html.twig
new file mode 100644
index 00000000..bdad9b71
--- /dev/null
+++ b/source/_partials/talk/video.html.twig
@@ -0,0 +1,28 @@
+{% macro videoSrc(video) %}
+ {% set srcUrls = {
+ youtube: '//www.youtube.com/embed',
+ videopress: 'https://videopress.com/embed',
+ vimeo: 'https://player.vimeo.com/video',
+ } %}
+
+ {{ srcUrls[video.type] ~ '/' ~ video.id }}
+{% endmacro %}
+
+{% from _self import videoSrc %}
+
+{% if video.id %}
+
+{% endif %}