diff --git a/.tugboat/config.yml b/.tugboat/config.yml
index 443bbca6d83e12acb83a0dfe5686f561435db922..935f9c00a3232aa2b1b9a4128171d45d930a316f 100644
--- a/.tugboat/config.yml
+++ b/.tugboat/config.yml
@@ -50,6 +50,7 @@ services:
           # Enable the module.
           vendor/bin/drush --yes pm:install \
             experience_builder \
+            xb_dev_standard \
             media_library \
             components
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6a2b2aa04c68cd78c217e92e4b3a5ff4f1f7169b..f583bdee66043b8912137d22f5ad96baebafd5e1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,7 +2,7 @@
 1. Drupal 11 (preferably a clone for Git archeology: `git clone https://git.drupalcode.org/project/drupal.git` — 10.3 will work too).
 2. `composer require drush/drush`
 3. `drush si standard`
-4. `drush pm:install experience_builder`
+4. `drush pm:install experience_builder xb_dev_standard`
 5. Build the front end: `cd modules/contrib/experience_builder/ui` and then either
     * With Node.js available: `npm install && npm run build`
     * With Docker available: `docker build --output dist .`
diff --git a/experience_builder.install b/experience_builder.install
index 0aeea5106e309900c97fe750578f8ff7fd53ac79..65a3d479def7aa91e5ad4de1b0647420498ab00f 100644
--- a/experience_builder.install
+++ b/experience_builder.install
@@ -2,7 +2,6 @@
 
 declare(strict_types=1);
 
-use Drupal\node\Entity\NodeType;
 use Drupal\Core\Extension\ThemeInstallerInterface;
 
 /**
@@ -14,23 +13,6 @@ function experience_builder_install(): void {
   // @see \Drupal\Core\Theme\ThemeNegotiator::determineActiveTheme()
   \Drupal::service(ThemeInstallerInterface::class)->install(['xb_stark']);
 
-  // Automatically set up the Standard install profile's "article" content type
-  // to demo/test Experience Builder.
-  if (!\Drupal::moduleHandler()->moduleExists('node')) {
-    return;
-  }
-  if (NodeType::load('article')) {
-    \Drupal::service('entity_display.repository')
-      ->getViewDisplay('node', 'article')
-      ->setComponent('field_xb_demo', [
-        'label' => 'hidden',
-        'type' => 'experience_builder_naive_render_sdc_tree',
-        // The image field has weight -1 by default.
-        'weight' => -2,
-      ])
-      ->save();
-  }
-
   // Cache flush ensures the contextual form works.
   drupal_flush_all_caches();
 }
diff --git a/experience_builder.module b/experience_builder.module
index 9a1d96663a0e1e8c5bb9f8797510baef6fa55b09..1fda346ad64aac3c36e0508be5c2beb26ca1e948 100644
--- a/experience_builder.module
+++ b/experience_builder.module
@@ -15,11 +15,9 @@ use Drupal\Core\Entity\TypedData\EntityDataDefinition;
 use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Url;
 use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;
 use Drupal\experience_builder\Entity\Component;
 use Drupal\experience_builder\Form\FormIdPreRender;
-use Drupal\experience_builder\InternalXbFieldNameResolver;
 use Drupal\experience_builder\Entity\PageTemplate;
 use Drupal\experience_builder\Plugin\ComponentPluginManager;
 use Drupal\Core\Validation\Plugin\Validation\Constraint\FullyValidatableConstraint;
@@ -42,52 +40,6 @@ require_once __DIR__ . '/experience_builder.shape_matching.inc';
 
 require_once __DIR__ . '/experience_builder.force_render_with_twig.inc';
 
-/**
- * Implements hook_toolbar().
- */
-function experience_builder_toolbar(): array {
-  $user = \Drupal::currentUser();
-
-  $items = [];
-  $items['experience_builder'] = [
-    '#cache' => [
-      'contexts' => [
-        'user.permissions',
-        'url',
-      ],
-    ],
-  ];
-
-  // @see experience_builder.routing.yml
-  // ⚠️ This is HORRIBLY HACKY way to provide a XB link for articles using `field_xb_demo` and will go away! ☺️
-  if ($user->hasPermission('access administration pages')) {
-    $node = \Drupal::routeMatch()->getParameter('node');
-    if ($node) {
-      try {
-        InternalXbFieldNameResolver::getXbFieldName($node);
-      }
-      catch (\LogicException) {
-        return $items;
-      }
-      $items['experience_builder'] += [
-        '#type' => 'toolbar_item',
-        'tab' => [
-          '#type' => 'link',
-          '#title' => t('Experience Builder: %title', ['%title' => $node->label()]),
-          '#url' => Url::fromRoute('experience_builder.experience_builder', ['entity_type' => 'node', 'entity' => $node->id()]),
-          '#attributes' => [
-            'title' => t('Experience Builder'),
-            'class' => ['toolbar-icon', 'toolbar-icon-edit'],
-          ],
-        ],
-        '#weight' => 1000,
-      ];
-    }
-  }
-
-  return $items;
-}
-
 /**
  * Implements hook_form_alter().
  */
diff --git a/config/optional/field.field.node.article.field_xb_demo.yml b/tests/modules/xb_dev_standard/config/optional/field.field.node.article.field_xb_demo.yml
similarity index 100%
rename from config/optional/field.field.node.article.field_xb_demo.yml
rename to tests/modules/xb_dev_standard/config/optional/field.field.node.article.field_xb_demo.yml
diff --git a/config/optional/field.storage.node.field_xb_demo.yml b/tests/modules/xb_dev_standard/config/optional/field.storage.node.field_xb_demo.yml
similarity index 100%
rename from config/optional/field.storage.node.field_xb_demo.yml
rename to tests/modules/xb_dev_standard/config/optional/field.storage.node.field_xb_demo.yml
diff --git a/tests/modules/xb_dev_standard/xb_dev_standard.info.yml b/tests/modules/xb_dev_standard/xb_dev_standard.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..16f804414bcb8c1936f885c68a65ebd0eea36248
--- /dev/null
+++ b/tests/modules/xb_dev_standard/xb_dev_standard.info.yml
@@ -0,0 +1,6 @@
+name: 'Develop XB on top of the Standard install profile'
+type: module
+dependencies:
+  - experience_builder:experience_builder
+  - drupal:node
+package: Testing
diff --git a/tests/modules/xb_dev_standard/xb_dev_standard.install b/tests/modules/xb_dev_standard/xb_dev_standard.install
new file mode 100644
index 0000000000000000000000000000000000000000..9161762ccd1bb0dac2a3d65f95a9bd93d00b97c9
--- /dev/null
+++ b/tests/modules/xb_dev_standard/xb_dev_standard.install
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+use Drupal\node\Entity\NodeType;
+
+/**
+ * Implements hook_install().
+ */
+function xb_dev_standard_install(): void {
+  if (NodeType::load('article')) {
+    \Drupal::service('entity_display.repository')
+      ->getViewDisplay('node', 'article')
+      ->setComponent('field_xb_demo', [
+        'label' => 'hidden',
+        'type' => 'experience_builder_naive_render_sdc_tree',
+        // The image field has weight -1 by default.
+        'weight' => -2,
+      ])
+      ->save();
+  }
+}
diff --git a/tests/modules/xb_dev_standard/xb_dev_standard.module b/tests/modules/xb_dev_standard/xb_dev_standard.module
new file mode 100644
index 0000000000000000000000000000000000000000..e5cd2404c20ec96dd2701c2c3b3dc363eb7cdcec
--- /dev/null
+++ b/tests/modules/xb_dev_standard/xb_dev_standard.module
@@ -0,0 +1,52 @@
+<?php
+
+declare(strict_types=1);
+
+use Drupal\Core\Url;
+use Drupal\experience_builder\InternalXbFieldNameResolver;
+
+/**
+ * Implements hook_toolbar().
+ */
+function xb_dev_standard_toolbar(): array {
+  $user = \Drupal::currentUser();
+
+  $items = [];
+  $items['experience_builder'] = [
+    '#cache' => [
+      'contexts' => [
+        'user.permissions',
+        'url',
+      ],
+    ],
+  ];
+
+  // @see experience_builder.routing.yml
+  // ⚠️ This is HORRIBLY HACKY way to provide a XB link for articles using `field_xb_demo` and will go away! ☺️
+  if ($user->hasPermission('access administration pages')) {
+    $node = \Drupal::routeMatch()->getParameter('node');
+    if ($node) {
+      try {
+        InternalXbFieldNameResolver::getXbFieldName($node);
+      }
+      catch (\LogicException) {
+        return $items;
+      }
+      $items['experience_builder'] += [
+        '#type' => 'toolbar_item',
+        'tab' => [
+          '#type' => 'link',
+          '#title' => t('Experience Builder: %title', ['%title' => $node->label()]),
+          '#url' => Url::fromRoute('experience_builder.experience_builder', ['entity_type' => 'node', 'entity' => $node->id()]),
+          '#attributes' => [
+            'title' => t('Experience Builder'),
+            'class' => ['toolbar-icon', 'toolbar-icon-edit'],
+          ],
+        ],
+        '#weight' => 1000,
+      ];
+    }
+  }
+
+  return $items;
+}
diff --git a/tests/src/Functional/ApiContentUpdateForDemoControllerTest.php b/tests/src/Functional/ApiContentUpdateForDemoControllerTest.php
index 0917a8a0326d04aa95d62dc3ac90e87621762e39..43d007ebe23b5f9dab87425be67a83961dc67f89 100644
--- a/tests/src/Functional/ApiContentUpdateForDemoControllerTest.php
+++ b/tests/src/Functional/ApiContentUpdateForDemoControllerTest.php
@@ -20,7 +20,7 @@ final class ApiContentUpdateForDemoControllerTest extends FunctionalTestBase {
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['experience_builder'];
+  protected static $modules = ['experience_builder', 'xb_dev_standard'];
 
   /**
    * {@inheritdoc}
diff --git a/tests/src/Kernel/FieldTypeUninstallValidatorTest.php b/tests/src/Kernel/FieldTypeUninstallValidatorTest.php
index 01c5108d4dfb659bea3749fc207ce8056d1be2a5..f7f517629e4c8f275889d3a128c79b529e8af37c 100644
--- a/tests/src/Kernel/FieldTypeUninstallValidatorTest.php
+++ b/tests/src/Kernel/FieldTypeUninstallValidatorTest.php
@@ -31,8 +31,6 @@ final class FieldTypeUninstallValidatorTest extends KernelTestBase {
   use NodeCreationTrait;
   use TestDataUtilitiesTrait;
 
-  private const XB_FIELD_UNINSTALL_ERROR = 'The <em class="placeholder">Experience Builder</em> field type is used in the following fields: node.field_xb_demo, node.field_xb_test';
-
   protected function setUp(): void {
     parent::setUp();
     // Clone the current connection and replace the current prefix.
@@ -87,7 +85,7 @@ final class FieldTypeUninstallValidatorTest extends KernelTestBase {
     // is dependency for 'experience_builder' we should get an error because
     // of the XB fields.
     $this->assertUninstallFailureReasons(
-      [self::XB_FIELD_UNINSTALL_ERROR],
+      ['The <em class="placeholder">Experience Builder</em> field type is used in the following field: node.field_xb_test'],
       // Ensure 'link' is not in the error message.
       'link'
     );
@@ -153,7 +151,7 @@ final class FieldTypeUninstallValidatorTest extends KernelTestBase {
     // is dependency for 'experience_builder' we should get an error because
     // of the XB fields.
     $this->assertUninstallFailureReasons(
-      [self::XB_FIELD_UNINSTALL_ERROR],
+      ['The <em class="placeholder">Experience Builder</em> field type is used in the following fields: node.field_xb_test, taxonomy_term.field_tag_test'],
       // Ensure 'link' is not in the error message.
       'link'
     );
@@ -174,9 +172,9 @@ final class FieldTypeUninstallValidatorTest extends KernelTestBase {
     catch (ModuleUninstallValidatorException $exception) {
       if ($reasons) {
         $this->assertSame($reasons, array_unique($reasons));
-        $this->assertStringContainsString(
+        $this->assertSame(
           'The following reasons prevent the modules from being uninstalled: ' . implode(', ', $reasons),
-          $exception->getMessage()
+          strtok($exception->getMessage(), ';'),
         );
       }
       if ($not_contains) {
diff --git a/tests/src/TestSite/XBTestSetup.php b/tests/src/TestSite/XBTestSetup.php
index 63badad17b8ba4ec941bfa63c415472dfc13e150..d2a8dc815c269dda9189c57cc3a72bb5aee54675 100644
--- a/tests/src/TestSite/XBTestSetup.php
+++ b/tests/src/TestSite/XBTestSetup.php
@@ -93,6 +93,7 @@ class XBTestSetup implements TestSetupInterface {
     ])->save();
     $module_installer->install([
       'experience_builder',
+      'xb_dev_standard',
       'xb_e2e_support',
     ]);