diff --git a/CRM/Contact/Page/View/Summary.php b/CRM/Contact/Page/View/Summary.php
index 3112a4ad70e8..0389b5b24428 100644
--- a/CRM/Contact/Page/View/Summary.php
+++ b/CRM/Contact/Page/View/Summary.php
@@ -425,6 +425,14 @@ public function getTabs(array $contact) {
     ];
     CRM_Utils_Hook::tabset('civicrm/contact/view', $allTabs, $context);
 
+    // Remove any tabs that don't apply to this contact type
+    foreach (array_keys($allTabs) as $key) {
+      $tabContactType = (array) ($allTabs[$key]['contact_type'] ?? []);
+      if ($tabContactType && !in_array($contact['contact_type'], $tabContactType, TRUE)) {
+        unset($allTabs[$key]);
+      }
+    }
+
     $expectedKeys = ['count', 'class', 'template', 'hideCount', 'icon'];
 
     foreach ($allTabs as &$tab) {
diff --git a/ext/afform/core/afform.php b/ext/afform/core/afform.php
index 2b085cbe1684..e72f2eca212f 100644
--- a/ext/afform/core/afform.php
+++ b/ext/afform/core/afform.php
@@ -214,7 +214,7 @@ function afform_civicrm_tabset($tabsetName, &$tabs, $context) {
   if ($tabsetName !== 'civicrm/contact/view') {
     return;
   }
-  $contactTypes = array_merge([$context['contact_type']], $context['contact_sub_type'] ?? []);
+  $contactTypes = array_merge([$context['contact_type']] ?? [], $context['contact_sub_type'] ?? []);
   $afforms = Civi\Api4\Afform::get(FALSE)
     ->addSelect('name', 'title', 'icon', 'module_name', 'directive_name', 'summary_contact_type')
     ->addWhere('contact_summary', '=', 'tab')
@@ -222,13 +222,15 @@ function afform_civicrm_tabset($tabsetName, &$tabs, $context) {
     ->execute();
   $weight = 111;
   foreach ($afforms as $afform) {
-    if (empty($afform['summary_contact_type']) || array_intersect($afform['summary_contact_type'], $contactTypes)) {
+    $summaryContactType = $afform['summary_contact_type'] ?? [];
+    if (!$summaryContactType || !$contactTypes || array_intersect($summaryContactType, $contactTypes)) {
       $tabs[] = [
         'id' => $afform['name'],
         'title' => $afform['title'],
         'weight' => $weight++,
         'icon' => 'crm-i ' . ($afform['icon'] ?: 'fa-list-alt'),
         'is_active' => TRUE,
+        'contact_type' => _afform_get_contact_types($summaryContactType) ?: NULL,
         'template' => 'afform/contactSummary/AfformTab.tpl',
         'module' => $afform['module_name'],
         'directive' => $afform['directive_name'],
@@ -298,7 +300,6 @@ function afform_civicrm_contactSummaryBlocks(&$blocks) {
     ->addWhere('contact_summary', '=', 'block')
     ->addOrderBy('title')
     ->execute();
-  $allContactTypes = \CRM_Contact_BAO_ContactType::getAllContactTypes();
   foreach ($afforms as $index => $afform) {
     // Create a group per afform type
     $blocks += [
@@ -308,17 +309,12 @@ function afform_civicrm_contactSummaryBlocks(&$blocks) {
         'blocks' => [],
       ],
     ];
-    $contactType = [];
     // If the form specifies contact types, resolve them to just the parent types (Individual, Organization, Household)
     // because ContactLayout doesn't care about sub-types
-    foreach ($afform['summary_contact_type'] ?? [] as $name) {
-      $parent = $allContactTypes[$name]['parent'] ?? $name;
-      $contactType[$parent] = $parent;
-    }
+    $contactType = _afform_get_contact_types($afform['summary_contact_type'] ?? []);
     $blocks["afform_{$afform['type']}"]['blocks'][$afform['name']] = [
       'title' => $afform['title'],
-      // ContactLayout only supports a single contact type
-      'contact_type' => count($contactType) === 1 ? CRM_Utils_Array::first($contactType) : NULL,
+      'contact_type' => $contactType ?: NULL,
       'tpl_file' => 'afform/contactSummary/AfformBlock.tpl',
       'module' => $afform['module_name'],
       'directive' => $afform['directive_name'],
@@ -331,6 +327,23 @@ function afform_civicrm_contactSummaryBlocks(&$blocks) {
   }
 }
 
+/**
+ * Resolve a mixed list of contact types and sub-types into just top-level contact types (Individual, Organization, Household)
+ *
+ * @param array $mixedTypes
+ * @return array
+ * @throws CRM_Core_Exception
+ */
+function _afform_get_contact_types(array $mixedTypes): array {
+  $allContactTypes = \CRM_Contact_BAO_ContactType::getAllContactTypes();
+  $contactTypes = [];
+  foreach ($mixedTypes as $name) {
+    $parent = $allContactTypes[$name]['parent'] ?? $name;
+    $contactTypes[$parent] = $parent;
+  }
+  return array_values($contactTypes);
+}
+
 /**
  * Implements hook_civicrm_angularModules().
  *
diff --git a/ext/afform/core/tests/phpunit/Civi/Afform/AfformContactSummaryTest.php b/ext/afform/core/tests/phpunit/Civi/Afform/AfformContactSummaryTest.php
index 3b892aed15e7..21aafaeb5ffb 100644
--- a/ext/afform/core/tests/phpunit/Civi/Afform/AfformContactSummaryTest.php
+++ b/ext/afform/core/tests/phpunit/Civi/Afform/AfformContactSummaryTest.php
@@ -15,6 +15,8 @@ class AfformContactSummaryTest extends \api\v4\Api4TestBase {
     'contact_summary_test1',
     'contact_summary_test2',
     'contact_summary_test3',
+    'contact_summary_test4',
+    'contact_summary_test5',
   ];
 
   public function setUpHeadless() {
@@ -52,6 +54,16 @@ public function testAfformContactSummaryTab(): void {
       ->addValue('title', 'Test A')
       ->addValue('contact_summary', 'tab')
       ->execute();
+    Afform::create()
+      ->addValue('name', $this->formNames[3])
+      ->addValue('title', 'Test D')
+      ->addValue('contact_summary', 'tab')
+      ->addValue('summary_contact_type', ['Individual'])
+      ->execute();
+    Afform::create()
+      ->addValue('name', $this->formNames[4])
+      ->addValue('title', 'Test E')
+      ->execute();
 
     $tabs = [];
     $context = [
@@ -67,7 +79,11 @@ public function testAfformContactSummaryTab(): void {
     $this->assertArrayHasKey($this->formNames[1], $tabs);
     $this->assertArrayHasKey($this->formNames[2], $tabs);
     $this->assertArrayNotHasKey($this->formNames[0], $tabs);
+    $this->assertArrayHasKey($this->formNames[3], $tabs);
+    $this->assertArrayNotHasKey($this->formNames[4], $tabs);
     $this->assertEquals('Test C', $tabs[$this->formNames[1]]['title']);
+    $this->assertEquals(['Individual'], $tabs[$this->formNames[1]]['contact_type']);
+    $this->assertEquals(['Individual'], $tabs[$this->formNames[3]]['contact_type']);
     $this->assertEquals('Test A', $tabs[$this->formNames[2]]['title']);
     $this->assertEquals('crm-i smiley-face', $tabs[$this->formNames[1]]['icon']);
     // Fallback icon
@@ -132,10 +148,9 @@ public function testAfformContactSummaryBlock(): void {
     $blocks = [];
     afform_civicrm_contactSummaryBlocks($blocks);
 
-    // ContactLayout doesn't support > 1 contact type, so this ought to be null
-    $this->assertNull($blocks['afform_search']['blocks'][$this->formNames[0]]['contact_type']);
+    $this->assertEquals(['Individual', 'Household'], $blocks['afform_search']['blocks'][$this->formNames[0]]['contact_type']);
     // Sub-type should have been converted to parent type
-    $this->assertEquals('Organization', $blocks['afform_form']['blocks'][$this->formNames[1]]['contact_type']);
+    $this->assertEquals(['Organization'], $blocks['afform_form']['blocks'][$this->formNames[1]]['contact_type']);
     $this->assertNull($blocks['afform_form']['blocks'][$this->formNames[2]]['contact_type']);
     // Forms should be sorted by title
     $order = array_flip(array_keys($blocks['afform_form']['blocks']));