diff --git a/district/migrations/0218_auto_20240601_1530.py b/district/migrations/0218_auto_20240601_1530.py
index 85ea20a1ed9c34f7f270952b8225a40de601e8a8..eccb91228b8722f0cfdff2b105fd28812486e3c5 100644
--- a/district/migrations/0218_auto_20240601_1530.py
+++ b/district/migrations/0218_auto_20240601_1530.py
@@ -1,8 +1,9 @@
 # Generated by Django 5.0.4 on 2024-06-01 13:30
 
-from django.db import migrations
-from shared.blocks import SocialLinkBlock
+from django.db import migrations, transaction
+
 from district.blocks import ProgramGroupWithCandidatesBlock
+from shared.blocks import SocialLinkBlock
 
 
 def migrate_programs(apps, schema_editor):
@@ -21,15 +22,20 @@ def migrate_programs(apps, schema_editor):
         "district", "DistrictPostElectionStrategyPage"
     )
 
-    DistrictNewProgramPage = apps.get_model(
-        "district", "DistrictNewProgramPage"
-    )
+    DistrictNewProgramPage = apps.get_model("district", "DistrictNewProgramPage")
+
+    Locale = apps.get_model("wagtailcore", "Locale")
 
     DistrictPersonPage = apps.get_model("district", "DistrictPersonPage")
-    apps.get_model("wagtailcore", "Page")
+    DistrictPeoplePage = apps.get_model("district", "DistrictPeoplePage")
+
+    # Get the default locale
+    default_locale = Locale.objects.first()
+
+    Page = apps.get_model("wagtailcore", "Page")
 
-    # Get the content type for DistrictElectionCampaignPage and DistrictElectionRootPage
     ContentType = apps.get_model("contenttypes", "ContentType")
+
     root_page_content_type = ContentType.objects.get(
         app_label="district", model="districtelectionrootpage"
     )
@@ -37,12 +43,19 @@ def migrate_programs(apps, schema_editor):
         app_label="district", model="districtelectioncampaignpage"
     )
 
+    people_page_content_type = ContentType.objects.get(
+        app_label="district", model="districtpeoplepage"
+    )
+
     program_page_content_type = ContentType.objects.get(
         app_label="district", model="districtelectionprogrampage"
     )
     program_post_election_strategy_content_type = ContentType.objects.get(
         app_label="district", model="districtpostelectionstrategypage"
     )
+    new_program_page_content_type = ContentType.objects.get(
+        app_label="district", model="districtnewprogrampage"
+    )
 
     # Function to get children of a certain type
     def get_children_of_type(model, parent_page, content_type):
@@ -57,22 +70,21 @@ def migrate_programs(apps, schema_editor):
             # Title
             "title": "",  # Done
             "order": 0,
-
-            # Candidate / program lists
-            "candidate_pages": [],  
-            "candidate_blocks": [],
+            # Program lists
             "program_points": [],
             "post_election_strategies": [],
-
             # Candidates
             "candidate_list_number": "",
             "candidate_list_title": "",
-
+            "candidate_pages": [],
+            "candidate_blocks": [],  # Page creation done
+            "combined_candidates": [],
+            "primary_candidate_count": 0,
             # Program
             "program_title": "",
             "program_is_inline": False,
             "program_content_before": "",  # Done
-            
+            # Misc.
             "funding_info": "",
         }
 
@@ -101,33 +113,36 @@ def migrate_programs(apps, schema_editor):
                     "candidate_list_title"
                 ] = campaign_page.candidate_list_title
 
-                election_data[
-                    "program_title"
-                ] = campaign_page.program_point_list_title
+                election_data["program_title"] = campaign_page.program_point_list_title
                 election_data[
                     "program_is_inline"
                 ] = campaign_page.show_program_points_inline
-                election_data["program_content_before"] = campaign_page.content
 
                 election_data["funding_info"] = campaign_page.campaign_funding_info
 
+                position = 0
+
                 for candidate_list_block in campaign_page.candidates.get_prep_value():
                     candidate_list = candidate_list_block["value"]
 
-                    for position, candidate in enumerate(
-                        candidate_list["candidate_list"]
-                    ):
+                    election_data["primary_candidate_count"] = candidate_list[
+                        "candidate_list_big_count"
+                    ]
+
+                    for candidate in candidate_list["candidate_list"]:
                         position = position + 1
 
                         if candidate["type"] == "person_page":
-                            election_data["candidate_pages"].append(
-                                {
-                                    "position": position,
-                                    "page": DistrictPersonPage.objects.filter(
-                                        id=candidate["value"]
-                                    ).first(),
-                                }
-                            )
+                            candidate_data = {
+                                "position": position,
+                                "page": DistrictPersonPage.objects.filter(
+                                    id=candidate["value"]
+                                ).first(),
+                            }
+
+                            election_data["candidate_pages"].append(candidate_data)
+                            election_data["combined_candidates"].append(candidate_data)
+
                             continue
 
                         if candidate["type"] == "person_blocks":
@@ -147,7 +162,6 @@ def migrate_programs(apps, schema_editor):
                             "guarantor_page": program_page.guarantor,
                             "image": program_page.image,
                             "perex": program_page.perex,
-                            "content": program_page.content,
                             "funding_info": program_page.campaign_funding_info,
                         }
                     )
@@ -162,89 +176,178 @@ def migrate_programs(apps, schema_editor):
                     election_data["post_election_strategies"].append(
                         {
                             "perex": post_election_strategy_page.perex,
-                            "content": post_election_strategy_page.content,
                         }
                     )
 
-        if len(election_data["candidate_pages"]) == 0 and len(election_data["candidate_blocks"]) == 0 and len(election_data["program_points"]) == 0:
+        if (
+            len(election_data["candidate_pages"]) == 0
+            and len(election_data["candidate_blocks"]) == 0
+            and len(election_data["program_points"]) == 0
+        ):
             continue  # Do nothing for these
 
+        parent_people_page = get_children_of_type(
+            DistrictPeoplePage, home_page, people_page_content_type
+        )
+
+        parent_people_page = parent_people_page.first()
+
         # Create corresponding pages for the candidate blocks
         for candidate_block in election_data["candidate_blocks"]:
+            if parent_people_page is None:
+                break  # We can't do anything here
+
             social_links = []
 
-            if candidate_block["value"]["facebook_url"]:
+            if candidate_block["data"]["facebook_url"]:
                 social_links.append(
-                    SocialLinkBlock().to_python({
-                        "icon": "ico--facebook",
-                        "text": "Facebook",
-                        "link": candidate_block["value"]["facebook_url"]
-                    })
+                    SocialLinkBlock().to_python(
+                        {
+                            "icon": "ico--facebook",
+                            "text": "Facebook",
+                            "link": candidate_block["data"]["facebook_url"],
+                        }
+                    )
                 )
 
-            if candidate_block["value"]["instagram_url"]:
+            if candidate_block["data"]["instagram_url"]:
                 social_links.append(
-                    SocialLinkBlock().to_python({
-                        "icon": "ico--instagram",
-                        "text": "Instagram",
-                        "link": candidate_block["value"]["instagram_url"]
-                    })
+                    SocialLinkBlock().to_python(
+                        {
+                            "icon": "ico--instagram",
+                            "text": "Instagram",
+                            "link": candidate_block["data"]["instagram_url"],
+                        }
+                    )
                 )
 
-            if candidate_block["value"]["twitter_url"]:
+            if candidate_block["data"]["twitter_url"]:
                 social_links.append(
-                    SocialLinkBlock().to_python({
-                        "icon": "ico--twitter",
-                        "text": "Twitter",
-                        "link": candidate_block["value"]["twitter_url"]
-                    })
+                    SocialLinkBlock().to_python(
+                        {
+                            "icon": "ico--twitter",
+                            "text": "Twitter",
+                            "link": candidate_block["data"]["twitter_url"],
+                        }
+                    )
                 )
 
-            if candidate_block["value"]["youtube_url"]:
+            if candidate_block["data"]["youtube_url"]:
                 social_links.append(
-                    SocialLinkBlock().to_python({
-                        "icon": "ico--youtube",
-                        "text": "YouTube",
-                        "link": candidate_block["value"]["youtube_url"]
-                    })
+                    SocialLinkBlock().to_python(
+                        {
+                            "icon": "ico--youtube",
+                            "text": "YouTube",
+                            "link": candidate_block["data"]["youtube_url"],
+                        }
+                    )
                 )
 
-            if candidate_block["value"]["flickr_url"]:
+            if candidate_block["data"]["flickr_url"]:
                 social_links.append(
-                    SocialLinkBlock().to_python({
-                        "icon": "ico--flickr",
-                        "text": "Flickr",
-                        "link": candidate_block["value"]["flickr_url"]
-                    })
+                    SocialLinkBlock().to_python(
+                        {
+                            "icon": "ico--flickr",
+                            "text": "Flickr",
+                            "link": candidate_block["data"]["flickr_url"],
+                        }
+                    )
                 )
 
-            candidate_page = DistrictPersonPage(
-                title=candidate_block["data"]["title"],
-                job=candidate_block["data"]["job"],
-                profile_image_id=candidate_block["data"]["profile_photo"],
-                email=candidate_block["data"]["email"],
-                city=candidate_block["data"]["city"],
-                age=candidate_block["data"]["age"],
-                is_pirate=candidate_block["data"]["is_pirate"],
-                other_party=candidate_block["data"]["other_party"],
-                other_party_logo_id=candidate_block["data"]["other_party_logo"],
-                social_links=social_links,
+            max_path_page = (
+                Page.objects.filter(
+                    path__startswith=people_page.path,
+                    depth=parent_people_page.depth + 1,
+                )
+                .order_by("-path")
+                .first()
             )
 
-            candidate_page.save()
+            if max_path_page:
+                max_path = max_path_page.path
+                next_path_suffix = (
+                    int(max_path[-4:], 36) + 1
+                )  # Base-36 to handle alphanumeric paths
+                next_path = (
+                    max_path[:-4] + f"{next_path_suffix:04X}"
+                )  # Convert back to base-36
+            else:
+                next_path = parent_people_page.path + "0001"
+
+            with transaction.atomic():
+                candidate_page = DistrictPersonPage(
+                    title=candidate_block["data"]["title"],
+                    job=candidate_block["data"]["job"],
+                    profile_image_id=candidate_block["data"]["profile_photo"],
+                    email=candidate_block["data"]["email"],
+                    city=candidate_block["data"]["city"],
+                    age=candidate_block["data"]["age"],
+                    is_pirate=candidate_block["data"]["is_pirate"],
+                    other_party=candidate_block["data"]["other_party"],
+                    other_party_logo_id=candidate_block["data"]["other_party_logo"],
+                    social_links=social_links,
+                    content_type_id=people_page_content_type.id,
+                    locale_id=default_locale.id,
+                )
+
+                candidate_page.numchild = candidate_page.numchild + 1
+                candidate_page.save(update_fields=["numchild"])
+
+            election_data["combined_candidates"].append(
+                {
+                    "position": candidate_block["position"],
+                    "data": candidate_page,
+                }
+            )
+
+        max_path_page = (
+            Page.objects.filter(
+                path__startswith=home_page.path, depth=home_page.depth + 1
+            )
+            .order_by("-path")
+            .first()
+        )
 
+        if max_path_page:
+            max_path = max_path_page.path
+            next_path_suffix = (
+                int(max_path[-4:], 36) + 1
+            )  # Base-36 to handle alphanumeric paths
+            next_path = (
+                max_path[:-4] + f"{next_path_suffix:04X}"
+            )  # Convert back to base-36
+        else:
+            next_path = home_page.path + "0001"
+
+        with transaction.atomic():
             new_program_page = DistrictNewProgramPage(
-                title="Programy"
+                title="Programy",
+                slug="programy",  # Make sure the slug is unique among siblings
+                path=next_path,
+                depth=home_page.depth + 1,
+                numchild=0,
+                content_type_id=new_program_page_content_type.id,
+                locale_id=default_locale.id,
             )
             new_program_page.save()
 
-            new_program_block = ProgramGroupWithCandidatesBlock().to_python({
-                "title": election_data["title"],
-                "preamble_content": election_data["program_content_before"],
+            # Update numchild on the home page
+            home_page.numchild = home_page.numchild + 1
+            home_page.save(update_fields=["numchild"])
 
-            })
+        election_data["combined_candidates"] = sorted(
+            election_data["combined_candidates"],
+            key=lambda value: value["position"],
+        )
 
-        print(election_data)
+        new_program_block = ProgramGroupWithCandidatesBlock().to_python(
+            {
+                "title": election_data["title"],
+                "preamble_content": election_data["program_content_before"],
+                "primary_candidates": [],
+                "secondary_candidates": [],
+            }
+        )
 
     # Stop migration for debugging purposes
     raise ValueError("Stopping migration for debugging purposes")