diff --git a/elections/blocks.py b/elections/blocks.py
index 46fb15f7013dc627849fb07fdf807a2e2478c3fe..dca84ab9403cd28b37d5cbac1b78eddcf6f2d19a 100644
--- a/elections/blocks.py
+++ b/elections/blocks.py
@@ -3,7 +3,10 @@ from wagtail.images.blocks import ImageChooserBlock
 from wagtail.blocks import (
     RichTextBlock,
     TextBlock,
+    CharBlock,
+    IntegerBlock,
     PageChooserBlock,
+    URLBlock,
     ListBlock
 )
 
@@ -53,3 +56,47 @@ class CandidateListBlock(StructBlock):
         template = "styleguide2/includes/organisms/candidates/elections/candidate_primary_list.html"
         icon = "form"
         label = "Seznam kandidátů"
+
+
+class ProgramCategoryItemBlock(StructBlock):
+    number = IntegerBlock(label="Číslo")
+
+    content = TextBlock(label="Obsah")
+
+    class Meta:
+        icon = "form"
+        label = "Bod"
+
+
+class ProgramCategoryBlock(StructBlock):
+    number = IntegerBlock(
+        label="Číslo"
+    )
+
+    name = CharBlock(
+        label="Název"
+    )
+
+    points = ListBlock(
+        ProgramCategoryItemBlock(),
+        label="Body"
+    )
+
+    class Meta:
+        icon = "form"
+        label = "Kategorie"
+
+
+class ProgramBlock(StructBlock):
+    categories = ListBlock(
+        ProgramCategoryBlock(),
+        label="Kategorie"
+    )
+
+    long_version_url = URLBlock(label="Odkaz na celou verzi programu")
+    long_version_text = CharBlock(label="Nadpis odkazu na celou verzi programu")
+
+    class Meta:
+        icon = "form"
+        label = "Vyskakovací program"
+        template = "styleguide2/includes/molecules/program/card_program.html"
diff --git a/elections/migrations/0012_alter_electionshomepage_content.py b/elections/migrations/0012_alter_electionshomepage_content.py
new file mode 100644
index 0000000000000000000000000000000000000000..f87db9df5a56ee52b0a73dd5c7e73487018f55c7
--- /dev/null
+++ b/elections/migrations/0012_alter_electionshomepage_content.py
@@ -0,0 +1,21 @@
+# Generated by Django 4.1.10 on 2024-01-05 19:47
+
+from django.db import migrations
+import wagtail.blocks
+import wagtail.fields
+import wagtail.images.blocks
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('elections', '0011_alter_electionshomepage_content'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='electionshomepage',
+            name='content',
+            field=wagtail.fields.StreamField([('carousel', wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Obrázek na pozadí'))])), ('candidate', wagtail.blocks.StructBlock([('candidates', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('page', wagtail.blocks.PageChooserBlock(label='Stránka', page_type=['elections.ElectionsCandidatePage'])), ('image', wagtail.images.blocks.ImageChooserBlock(help_text='Pokud není vybrán, použije se obrázek ze stránky kandidáta', label='Obrázek', required=False)), ('description', wagtail.blocks.TextBlock(help_text='Pokud zůstane prázdné, použije se popis ze stránky kandidáta', label='Popis', required=False))]), label='Kandidáti'))])), ('program', wagtail.blocks.StructBlock([('categories', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('number', wagtail.blocks.IntegerBlock(label='Číslo')), ('name', wagtail.blocks.CharBlock(label='Název')), ('points', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('number', wagtail.blocks.IntegerBlock(label='Číslo')), ('content', wagtail.blocks.RichTextBlock(label='Obsah'))]), label='Body'))]), label='Kategorie')), ('long_version_url', wagtail.blocks.URLBlock(label='Odkaz na celou verzi programu')), ('long_version_text', wagtail.blocks.CharBlock(label='Nadpis odkazu na celou verzi programu'))]))], blank=True, use_json_field=True, verbose_name='Hlavní obsah'),
+        ),
+    ]
diff --git a/elections/models.py b/elections/models.py
index 405a7424f246fb294ca27fdb20801f5ee0fbad3c..6e3b52c4b1d67c77c9c607e4d930a82b74263764 100644
--- a/elections/models.py
+++ b/elections/models.py
@@ -55,7 +55,9 @@ class ElectionsHomePage(MainHomePageMixin):
     content = StreamField(
         [
             ("carousel", blocks.ElectionsCarouselBlock()),
-            ("candidate", blocks.CandidateListBlock())
+            ("candidate", blocks.CandidateListBlock()),
+            ("program", blocks.ProgramBlock()),
+            ("news", shared_blocks.NewsBlock(template="styleguide2/includes/organisms/articles/elections/articles_section.html")),
         ],
         verbose_name="Hlavní obsah",
         blank=True,
diff --git a/elections/templatetags/rawtext.py b/elections/templatetags/rawtext.py
new file mode 100644
index 0000000000000000000000000000000000000000..252fe7220e2f1b61b590c525cca746380ed7d44f
--- /dev/null
+++ b/elections/templatetags/rawtext.py
@@ -0,0 +1,8 @@
+from django import template
+
+register = template.Library()
+
+
+@register.filter
+def rawtext(source_text_block) -> str:
+    return str(source_text_block)
diff --git a/main/blocks.py b/main/blocks.py
index e3778a2607aa31b6b4bcb18eef7f43358a498769..975b3cdc066356ebc37938b548926c06a9c324a8 100644
--- a/main/blocks.py
+++ b/main/blocks.py
@@ -103,19 +103,6 @@ class HomePageCarouseSlideBlock(StructBlock):
         label = "Carousel"
 
 
-class NewsBlock(StructBlock):
-    title = CharBlock(
-        label="Titulek",
-        help_text="Nejnovější články se načtou automaticky",
-    )
-    description = TextBlock(label="Popis")
-
-    class Meta:
-        template = "styleguide2/includes/organisms/articles/articles_section.html"
-        icon = "doc-full-inverse"
-        label = "Novinky"
-
-
 class EuroparlNewsBlock(StructBlock):
     class Meta:
         template = (
diff --git a/main/models.py b/main/models.py
index 726eb1d82a9766fdf3b46ef1e560ae24dc007bdc..9b2f29f5bf01fea6f6917c0006ce57f69b0aba12 100644
--- a/main/models.py
+++ b/main/models.py
@@ -55,7 +55,7 @@ class MainHomePage(MainHomePageMixin):
     content = StreamField(
         [
             ("carousel", blocks.HomePageCarouseSlideBlock()),
-            ("news", blocks.NewsBlock()),
+            ("news", shared_blocks.NewsBlock(template="styleguide2/includes/organisms/articles/articles_section.html")),
             ("europarl_news", blocks.EuroparlNewsBlock()),
             ("people", blocks.PeopleOverviewBlock()),
             ("regions", blocks.RegionsBlock()),
diff --git a/shared/blocks/main.py b/shared/blocks/main.py
index 60483e8e5fef38c3f7513a5b1469584808251bb7..3a5cbbe84270bffea80d9b5996fa1bf60b90a424 100644
--- a/shared/blocks/main.py
+++ b/shared/blocks/main.py
@@ -5,6 +5,7 @@ from wagtail.blocks import (
     PageChooserBlock,
     RichTextBlock,
     StructBlock,
+    TextBlock,
     URLBlock,
 )
 from wagtail.documents.blocks import DocumentChooserBlock
@@ -68,6 +69,18 @@ class SocialLinkBlock(LinkBlock):
 # Articles
 
 
+class NewsBlock(StructBlock):
+    title = CharBlock(
+        label="Titulek",
+        help_text="Nejnovější články se načtou automaticky",
+    )
+    description = TextBlock(label="Popis")
+
+    class Meta:
+        icon = "doc-full-inverse"
+        label = "Novinky"
+
+
 class ArticleQuoteBlock(StructBlock):
     quote = CharBlock(label="Citace")
     autor_name = CharBlock(label="Jméno autora")
diff --git a/shared/templates/styleguide2/includes/molecules/program/card_program.html b/shared/templates/styleguide2/includes/molecules/program/card_program.html
new file mode 100644
index 0000000000000000000000000000000000000000..fae1fd8478d76d0e68a99c6da86d049b566065fb
--- /dev/null
+++ b/shared/templates/styleguide2/includes/molecules/program/card_program.html
@@ -0,0 +1,39 @@
+{% load rawtext %}
+
+<div class="bg-pirati-yellow">
+  <div
+    class="__js-root container--wide"
+    id="program"
+  >
+    <ui-card-program
+      :points="
+        [
+          {% for category in self.categories %}
+            {
+              slug: '{{ category.number }}',
+              number: {{ category.number }},
+              title: '{{ category.name }}',
+              points: [
+                {% for point in category.points %}
+                  {
+                    number: '{{ point.number }}',
+                    content: '{{ point.content|rawtext }}'
+                  }{% if not forloop.last %},{% endif %}
+                {% endfor %}
+              ]
+            }{% if not forloop.last %},{% endif %}
+          {% endfor %}
+        ]
+      "
+    ></ui-card-program>
+
+    <!-- Make this accessible without JS, at least -->
+    <a
+      class="text-xl font-bold pl-4"
+      href="{{ self.long_version_url }}"
+    >
+      <i class="ico--chevron-right"></i>
+      {{ self.long_version_text }}
+    </a>
+  </div>
+</div>
diff --git a/shared/templates/styleguide2/includes/organisms/articles/articles_section.html b/shared/templates/styleguide2/includes/organisms/articles/articles_section.html
index 56b9b04e4d9fc358eb4e068d8b69363e5ddc4f2a..50649d85551a2bb13528a5288b0f0ae2f4777b7d 100644
--- a/shared/templates/styleguide2/includes/organisms/articles/articles_section.html
+++ b/shared/templates/styleguide2/includes/organisms/articles/articles_section.html
@@ -1,6 +1,12 @@
 {% load wagtailcore_tags wagtailimages_tags shared_perex %}
 
-<div class="bg-black text-white">
+<div
+  class="
+    {% block wrapper_classes %}
+      bg-black text-white
+    {% endblock %}
+  "
+>
   <div class="container--medium __js-root">
     <div
       class="
@@ -33,9 +39,11 @@
 
     <div
       class="
-        flex justify-center pb-0 pt-12
+        {% block button_wrapper_classes %}
+          flex justify-center pt-12
 
-        xl:py-24
+          xl:py-24
+        {% endblock %}
       "
     >
       {% include "styleguide2/includes/atoms/buttons/round_button.html" with button_text="Více článků" classes="bg-white text-black" url=page.root_page.articles_page.url %}
diff --git a/shared/templates/styleguide2/includes/organisms/candidates/elections/candidate_primary_list.html b/shared/templates/styleguide2/includes/organisms/candidates/elections/candidate_primary_list.html
index d87a6a690d5be714bac69a4d36347502defb62d5..8c8c8ef3223ff1fb94ee1f30d3b8e7e55cd38328 100644
--- a/shared/templates/styleguide2/includes/organisms/candidates/elections/candidate_primary_list.html
+++ b/shared/templates/styleguide2/includes/organisms/candidates/elections/candidate_primary_list.html
@@ -1,11 +1,11 @@
-{% load wagtailimages_tags %}
+{% load wagtailimages_tags wagtailcore_tags %}
 
 <ul
   class="candidate-primary-list __js-root"
-  id="{{ id }}"
+  id="kandidati"
 >
   {% for candidate in self.candidates %}
-    {% firstof candidate.description candidate.page.description as description %}
+    {% firstof candidate.description candidate.page.perex as description %}
 
     {% if candidate.image %}
       {% image candidate.image original as resized_candidate_image %}