diff --git a/core/.eslintignore b/core/.eslintignore
index 570792e1b3e6a9fd6e0b538adcaeb8ca66610299..223205a2ada8df3009938ce5c27c226976df578e 100644
--- a/core/.eslintignore
+++ b/core/.eslintignore
@@ -11,7 +11,7 @@ tests/Drupal/Tests/Core/Asset/library_test_files/empty.libraries.yml
 tests/Drupal/Tests/Core/Asset/library_test_files/invalid_file.libraries.yml
 tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/drupal-assets-fixture/assets/default.services.yml
 tests/Drupal/Tests/Composer/Plugin/Scaffold/fixtures/drupal-profile/assets/profile.default.services.yml
-modules/sdc/tests/themes/sdc_theme_test/components/bar/bar.component.yml
+modules/system/tests/themes/sdc_theme_test/components/bar/bar.component.yml
 
 # Temporary until they are brought up to standards
 scripts/**/*
diff --git a/core/modules/sdc/src/metadata-full.schema.json b/core/assets/schemas/v1/metadata-full.schema.json
similarity index 97%
rename from core/modules/sdc/src/metadata-full.schema.json
rename to core/assets/schemas/v1/metadata-full.schema.json
index d53f5a9befb3d3c26f3c0354df217df32050cef6..8df83fb05c961415a81dc4583d5880f09bc26f7a 100644
--- a/core/modules/sdc/src/metadata-full.schema.json
+++ b/core/assets/schemas/v1/metadata-full.schema.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json",
+  "$id": "https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata-full.schema.json",
   "$schema": "http://json-schema.org/draft-04/schema#",
   "$defs": {
     "slotDefinition": {
diff --git a/core/modules/sdc/src/metadata.schema.json b/core/assets/schemas/v1/metadata.schema.json
similarity index 97%
rename from core/modules/sdc/src/metadata.schema.json
rename to core/assets/schemas/v1/metadata.schema.json
index b22360b84c5200b605c4e258459c52da148b9413..4cbeffebff1b445906a504c588c6b054cac45f72 100644
--- a/core/modules/sdc/src/metadata.schema.json
+++ b/core/assets/schemas/v1/metadata.schema.json
@@ -1,5 +1,5 @@
 {
-  "$id": "https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json",
+  "$id": "https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json",
   "$schema": "http://json-schema.org/draft-04/schema#",
   "$defs": {
     "slotDefinition": {
diff --git a/core/core.services.yml b/core/core.services.yml
index 22cb21e24deaca9a7f965e2bb69e10efbce5f4de..6442cae48c7aa4a5dacd15b01d7e061d4cdd0a70 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1684,7 +1684,7 @@ services:
       - { name: needs_destruction }
   library.discovery.parser:
     class: Drupal\Core\Asset\LibraryDiscoveryParser
-    arguments: ['%app.root%', '@module_handler', '@theme.manager', '@stream_wrapper_manager', '@library.libraries_directory_file_finder', '@extension.path.resolver']
+    arguments: ['%app.root%', '@module_handler', '@theme.manager', '@stream_wrapper_manager', '@library.libraries_directory_file_finder', '@extension.path.resolver', '@plugin.manager.sdc']
   Drupal\Core\Asset\LibraryDiscoveryParser: '@library.discovery.parser'
   library.libraries_directory_file_finder:
     class: Drupal\Core\Asset\LibrariesDirectoryFileFinder
@@ -1713,6 +1713,10 @@ services:
     arguments: ['@renderer', '@url_generator', '@theme.manager', '@date.formatter', '@file_url_generator']
     tags:
       - { name: twig.extension, priority: 100 }
+  Drupal\Core\Template\ComponentsTwigExtension:
+    arguments: ['@plugin.manager.sdc', '@Drupal\Core\Theme\Component\ComponentValidator']
+    tags:
+      - { name: twig.extension, priority: 101 }
   twig.extension.debug:
     class: Twig\Extension\DebugExtension
     tags:
@@ -1845,3 +1849,32 @@ services:
     class: Drupal\Core\Pager\PagerParameters
     arguments: ['@request_stack']
   Drupal\Core\Pager\PagerParametersInterface: '@pager.parameters'
+  Drupal\Core\Theme\Component\SchemaCompatibilityChecker: {}
+  Drupal\Core\Theme\Component\ComponentValidator:
+    calls:
+      - [setValidator, []]
+  Drupal\Core\Theme\ComponentNegotiator:
+    arguments:
+      - '@theme.manager'
+      - '@extension.list.module'
+  plugin.manager.sdc:
+    public: true
+    class: Drupal\Core\Theme\ComponentPluginManager
+    arguments:
+      - '@module_handler'
+      - '@theme_handler'
+      - '@cache.discovery'
+      - '@config.factory'
+      - '@theme.manager'
+      - '@Drupal\Core\Theme\ComponentNegotiator'
+      - '@file_system'
+      - '@Drupal\Core\Theme\Component\SchemaCompatibilityChecker'
+      - '@Drupal\Core\Theme\Component\ComponentValidator'
+      - '%app.root%'
+  Drupal\Core\Theme\ComponentPluginManager: '@plugin.manager.sdc'
+  Drupal\Core\Template\Loader\ComponentLoader:
+    arguments:
+      - '@plugin.manager.sdc'
+      - '@logger.channel.default'
+    tags:
+      - { name: twig.loader, priority: 5 }
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
index 0114e9a96bb918188bf48807cd073b0b5ac875dd..a5722b41f5e665e2b1b3bad1b4baf3cd9272ca9d 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
@@ -14,7 +14,9 @@
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Serialization\Yaml;
 use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
+use Drupal\Core\Theme\ComponentPluginManager;
 use Drupal\Core\Theme\ThemeManagerInterface;
+use Drupal\Core\Plugin\Component;
 
 /**
  * Parses library files to get extension data.
@@ -56,6 +58,13 @@ class LibraryDiscoveryParser {
    */
   protected $librariesDirectoryFileFinder;
 
+  /**
+   * The component plugin manager.
+   *
+   * @var \Drupal\Core\Theme\ComponentPluginManager
+   */
+  protected $componentPluginManager;
+
   /**
    * The extension path resolver.
    *
@@ -85,8 +94,10 @@ class LibraryDiscoveryParser {
    *   The libraries directory file finder.
    * @param \Drupal\Core\Extension\ExtensionPathResolver $extension_path_resolver
    *   The extension path resolver.
+   * @param \Drupal\Core\Theme\ComponentPluginManager|null $component_plugin_manager
+   *   The component plugin manager.
    */
-  public function __construct($root, ModuleHandlerInterface $module_handler, ThemeManagerInterface $theme_manager, StreamWrapperManagerInterface $stream_wrapper_manager, LibrariesDirectoryFileFinder $libraries_directory_file_finder, ExtensionPathResolver $extension_path_resolver) {
+  public function __construct($root, ModuleHandlerInterface $module_handler, ThemeManagerInterface $theme_manager, StreamWrapperManagerInterface $stream_wrapper_manager, LibrariesDirectoryFileFinder $libraries_directory_file_finder, ExtensionPathResolver $extension_path_resolver, ?ComponentPluginManager $component_plugin_manager = NULL) {
     $this->root = $root;
     $this->moduleHandler = $module_handler;
     $this->themeManager = $theme_manager;
@@ -94,6 +105,11 @@ public function __construct($root, ModuleHandlerInterface $module_handler, Theme
     $this->librariesDirectoryFileFinder = $libraries_directory_file_finder;
     $this->extensionPathResolver = $extension_path_resolver;
     $this->fileCache = FileCacheFactory::get('library_parser');
+    if (!isset($component_plugin_manager)) {
+      @trigger_error('Calling ' . __METHOD__ . '() without the $component_plugin_manager argument is deprecated in drupal:10.3.0 and will be required in drupal:11.0.0. See https://www.drupal.org/node/3410260', E_USER_DEPRECATED);
+      $component_plugin_manager = \Drupal::service('plugin.manager.sdc');
+    }
+    $this->componentPluginManager = $component_plugin_manager;
   }
 
   /**
@@ -383,6 +399,13 @@ protected function parseLibraryInfo($extension, $path) {
         }
       }
     }
+    // Core also provides additional libraries that don't come from the YAML,
+    // file nor the hook_library_info_build. They come from single directory
+    // component definitions.
+    $additional_libraries = $extension === 'core'
+      ? $this->librariesForComponents()
+      : [];
+    $libraries = array_merge($additional_libraries, $libraries);
 
     // Allow modules to add dynamic library definitions.
     $hook = 'library_info_build';
@@ -397,6 +420,37 @@ protected function parseLibraryInfo($extension, $path) {
     return $libraries;
   }
 
+  /**
+   * Builds the dynamic library definitions for single directory components.
+   *
+   * @return array
+   *   The core library definitions for Single Directory Components.
+   */
+  protected function librariesForComponents(): array {
+    // Iterate over all the components to get the CSS and JS files.
+    $components = $this->componentPluginManager->getAllComponents();
+    $libraries = array_reduce(
+      $components,
+      static function (array $libraries, Component $component) {
+        $library = $component->library;
+        if (empty($library)) {
+          return $libraries;
+        }
+        $library_name = $component->getLibraryName();
+        [, $library_id] = explode('/', $library_name);
+        return array_merge($libraries, [$library_id => $library]);
+      },
+      []
+    );
+    $libraries['components.all'] = [
+      'dependencies' => array_map(
+        static fn(Component $component) => $component->getLibraryName(),
+        $components
+      ),
+    ];
+    return $libraries;
+  }
+
   /**
    * Apply libraries overrides specified for the current active theme.
    *
diff --git a/core/modules/sdc/src/Plugin/Component.php b/core/lib/Drupal/Core/Plugin/Component.php
similarity index 83%
rename from core/modules/sdc/src/Plugin/Component.php
rename to core/lib/Drupal/Core/Plugin/Component.php
index 8fc3f22a1e9f35de855d3c1a4bc40bcc74e4d5c0..8d900ccaab7f28ee2fa7c1b8ef5f73b9a271ce22 100644
--- a/core/modules/sdc/src/Plugin/Component.php
+++ b/core/lib/Drupal/Core/Plugin/Component.php
@@ -1,22 +1,19 @@
 <?php
 
-namespace Drupal\sdc\Plugin;
+namespace Drupal\Core\Plugin;
 
-use Drupal\Core\Plugin\PluginBase;
-use Drupal\sdc\Component\ComponentMetadata;
-use Drupal\sdc\Exception\InvalidComponentException;
+use Drupal\Core\Theme\Component\ComponentMetadata;
+use Drupal\Core\Render\Component\Exception\InvalidComponentException;
 
 /**
  * Simple value object that contains information about the component.
- *
- * @internal
  */
-final class Component extends PluginBase {
+class Component extends PluginBase {
 
   /**
    * The component's metadata.
    *
-   * @var \Drupal\sdc\Component\ComponentMetadata
+   * @var \Drupal\Core\Theme\Component\ComponentMetadata
    */
   public readonly ComponentMetadata $metadata;
 
@@ -44,7 +41,7 @@ final class Component extends PluginBase {
   /**
    * Component constructor.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   public function __construct(array $configuration, $plugin_id, $plugin_definition) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
@@ -89,7 +86,7 @@ public function getTemplatePath(): ?string {
   public function getLibraryName(): string {
     $library_id = $this->getPluginId();
     $library_id = str_replace(':', '--', $library_id);
-    return sprintf('sdc/%s', $library_id);
+    return sprintf('core/components.%s', $library_id);
   }
 
 }
diff --git a/core/modules/sdc/src/Plugin/Discovery/DirectoryWithMetadataDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataDiscovery.php
similarity index 96%
rename from core/modules/sdc/src/Plugin/Discovery/DirectoryWithMetadataDiscovery.php
rename to core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataDiscovery.php
index 094cc552c7addd58a7c712a6cac35a3231d35745..c589840289ed6b6f4b86bf1f4129615e957c2b95 100644
--- a/core/modules/sdc/src/Plugin/Discovery/DirectoryWithMetadataDiscovery.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataDiscovery.php
@@ -1,16 +1,14 @@
 <?php
 
-namespace Drupal\sdc\Plugin\Discovery;
+namespace Drupal\Core\Plugin\Discovery;
 
 use Drupal\Component\Discovery\YamlDirectoryDiscovery;
 use Drupal\Core\File\FileSystemInterface;
 
 /**
  * Does the actual finding of the directories with metadata files.
- *
- * @internal
  */
-final class DirectoryWithMetadataDiscovery extends YamlDirectoryDiscovery {
+class DirectoryWithMetadataDiscovery extends YamlDirectoryDiscovery {
 
   /**
    * Constructs a DirectoryWithMetadataDiscovery object.
diff --git a/core/modules/sdc/src/Plugin/Discovery/DirectoryWithMetadataPluginDiscovery.php b/core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataPluginDiscovery.php
similarity index 80%
rename from core/modules/sdc/src/Plugin/Discovery/DirectoryWithMetadataPluginDiscovery.php
rename to core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataPluginDiscovery.php
index 8c201af3589a8b01069531f292a50de7fed675bb..5af50c0918124b9ef40cc348fab8b98439dc7d3f 100644
--- a/core/modules/sdc/src/Plugin/Discovery/DirectoryWithMetadataPluginDiscovery.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/DirectoryWithMetadataPluginDiscovery.php
@@ -1,19 +1,16 @@
 <?php
 
-namespace Drupal\sdc\Plugin\Discovery;
+namespace Drupal\Core\Plugin\Discovery;
 
 use Drupal\Core\File\FileSystemInterface;
-use Drupal\Core\Plugin\Discovery\YamlDiscovery;
 
 /**
  * Discover directories that contain a specific metadata file.
- *
- * @internal
  */
-final class DirectoryWithMetadataPluginDiscovery extends YamlDiscovery {
+class DirectoryWithMetadataPluginDiscovery extends YamlDiscovery {
 
   /**
-   * Constructs a YamlDirectoryDiscovery object.
+   * Constructs a DirectoryWithMetadataPluginDiscovery object.
    *
    * @param array $directories
    *   An array of directories to scan, keyed by the provider. The value can
diff --git a/core/modules/sdc/src/Plugin/Discovery/RegexRecursiveFilterIterator.php b/core/lib/Drupal/Core/Plugin/Discovery/RegexRecursiveFilterIterator.php
similarity index 86%
rename from core/modules/sdc/src/Plugin/Discovery/RegexRecursiveFilterIterator.php
rename to core/lib/Drupal/Core/Plugin/Discovery/RegexRecursiveFilterIterator.php
index 15c444dbb0bffaf4ec8fd45de629d58a0f8e6eb5..1d86e1bba0264cfbaf4efff6e407e58c2aa9ab61 100644
--- a/core/modules/sdc/src/Plugin/Discovery/RegexRecursiveFilterIterator.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/RegexRecursiveFilterIterator.php
@@ -1,16 +1,14 @@
 <?php
 
-namespace Drupal\sdc\Plugin\Discovery;
+namespace Drupal\Core\Plugin\Discovery;
 
 /**
  * Iterates over files whose names match a regular expression in a directory.
- *
- * @internal
  */
-final class RegexRecursiveFilterIterator extends \RecursiveFilterIterator {
+class RegexRecursiveFilterIterator extends \RecursiveFilterIterator {
 
   /**
-   * RegexDirectoryIterator constructor.
+   * RegexRecursiveFilterIterator constructor.
    *
    * @param \RecursiveIterator $iterator
    *   The iterator.
diff --git a/core/lib/Drupal/Core/Render/Component/Exception/ComponentNotFoundException.php b/core/lib/Drupal/Core/Render/Component/Exception/ComponentNotFoundException.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e33e3432aaf0fc23baaf0a5f2d3c188f40473c0
--- /dev/null
+++ b/core/lib/Drupal/Core/Render/Component/Exception/ComponentNotFoundException.php
@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Core\Render\Component\Exception;
+
+/**
+ * Raised when a component cannot be found.
+ */
+class ComponentNotFoundException extends \Exception {
+
+}
diff --git a/core/lib/Drupal/Core/Render/Component/Exception/IncompatibleComponentSchema.php b/core/lib/Drupal/Core/Render/Component/Exception/IncompatibleComponentSchema.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ac5bcd622fd0a2e6bc3685e1e01e613a858c3d2
--- /dev/null
+++ b/core/lib/Drupal/Core/Render/Component/Exception/IncompatibleComponentSchema.php
@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Core\Render\Component\Exception;
+
+/**
+ * Custom exception for incompatible schemas.
+ */
+class IncompatibleComponentSchema extends \Exception {
+
+}
diff --git a/core/lib/Drupal/Core/Render/Component/Exception/InvalidComponentDataException.php b/core/lib/Drupal/Core/Render/Component/Exception/InvalidComponentDataException.php
new file mode 100644
index 0000000000000000000000000000000000000000..9c02bcbf51e9ea861925ce2aad1e46450406ea6a
--- /dev/null
+++ b/core/lib/Drupal/Core/Render/Component/Exception/InvalidComponentDataException.php
@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Core\Render\Component\Exception;
+
+/**
+ * Raised when a component is rendering with invalid data.
+ */
+class InvalidComponentDataException extends \Exception {
+
+}
diff --git a/core/lib/Drupal/Core/Render/Component/Exception/InvalidComponentException.php b/core/lib/Drupal/Core/Render/Component/Exception/InvalidComponentException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ff3d9704ad57631992ce25a506f49d4644adbb27
--- /dev/null
+++ b/core/lib/Drupal/Core/Render/Component/Exception/InvalidComponentException.php
@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Core\Render\Component\Exception;
+
+/**
+ * Custom exception for invalid components.
+ */
+class InvalidComponentException extends \Exception {
+
+}
diff --git a/core/lib/Drupal/Core/Render/Element.php b/core/lib/Drupal/Core/Render/Element.php
index 1fd24219c5ca2cb5443871370afad1152165b27f..ae329e8aee5b00457b4270f1907705b71141e51f 100644
--- a/core/lib/Drupal/Core/Render/Element.php
+++ b/core/lib/Drupal/Core/Render/Element.php
@@ -206,4 +206,34 @@ public static function isEmpty(array $elements) {
     return \array_diff(\array_keys($elements), ['#cache', '#weight']) === [];
   }
 
+  /**
+   * Checks if a candidate is a render array.
+   *
+   * @param mixed $candidate
+   *   The candidate.
+   *
+   * @return bool
+   *   TRUE if it's a render array. FALSE otherwise.
+   */
+  public static function isRenderArray($candidate): bool {
+    if (!is_array($candidate)) {
+      return FALSE;
+    }
+    if (empty($candidate)) {
+      return FALSE;
+    }
+    foreach ($candidate as $key => $value) {
+      if (!is_int($key) && $key !== '' && $key[0] === '#') {
+        continue;
+      }
+      if (!is_array($value)) {
+        return FALSE;
+      }
+      if (!static::isRenderArray($value)) {
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+
 }
diff --git a/core/modules/sdc/src/Element/ComponentElement.php b/core/lib/Drupal/Core/Render/Element/ComponentElement.php
similarity index 89%
rename from core/modules/sdc/src/Element/ComponentElement.php
rename to core/lib/Drupal/Core/Render/Element/ComponentElement.php
index 946997b1b24b8a01a9f130dac691f21bbce5c92a..d91aa7341579d05179c67a9ef7481edd436aef7a 100644
--- a/core/modules/sdc/src/Element/ComponentElement.php
+++ b/core/lib/Drupal/Core/Render/Element/ComponentElement.php
@@ -1,12 +1,12 @@
 <?php
 
-namespace Drupal\sdc\Element;
+namespace Drupal\Core\Render\Element;
 
 use Drupal\Core\Render\Attribute\RenderElement;
+use Drupal\Core\Render\Element;
 use Drupal\Core\Render\Element\RenderElement as RenderElementBase;
 use Drupal\Core\Security\DoTrustedCallbackTrait;
-use Drupal\sdc\Exception\InvalidComponentDataException;
-use Drupal\sdc\Utilities;
+use Drupal\Core\Render\Component\Exception\InvalidComponentDataException;
 
 /**
  * Provides a Single Directory Component render element.
@@ -39,7 +39,7 @@ class ComponentElement extends RenderElementBase {
   use DoTrustedCallbackTrait;
 
   /**
-   * Expands a sdc into an inline template with an attachment.
+   * Expands a component into an inline template with an attachment.
    *
    * @param array $element
    *   The element to process. See main class documentation for properties.
@@ -47,7 +47,7 @@ class ComponentElement extends RenderElementBase {
    * @return array
    *   The form element.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentDataException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentDataException
    */
   public function preRenderComponent(array $element): array {
     $props = $element['#props'];
@@ -92,7 +92,7 @@ public function preRenderComponent(array $element): array {
    * @return string
    *   The template.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentDataException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentDataException
    *   When slots are not render arrays.
    */
   private function generateComponentTemplate(
@@ -101,7 +101,7 @@ private function generateComponentTemplate(
     array $slots_alter_callbacks,
     array &$context,
   ): string {
-    $template = '{# This template was dynamically generated by sdc #}' . PHP_EOL;
+    $template = '{# This template was dynamically generated by single directory components #}' . PHP_EOL;
     $template .= sprintf('{%% embed \'%s\' %%}', $id);
     $template .= PHP_EOL;
     foreach ($slots as $slot_name => $slot_value) {
@@ -110,7 +110,7 @@ private function generateComponentTemplate(
           "#plain_text" => (string) $slot_value,
         ];
       }
-      if (!Utilities::isRenderArray($slot_value)) {
+      if (!Element::isRenderArray($slot_value)) {
         $message = sprintf(
           'Unable to render component "%s". A render array or a scalar is expected for the slot "%s" when using the render element with the "#slots" property',
           $id,
diff --git a/core/modules/sdc/src/Twig/ComponentNodeVisitor.php b/core/lib/Drupal/Core/Template/ComponentNodeVisitor.php
similarity index 91%
rename from core/modules/sdc/src/Twig/ComponentNodeVisitor.php
rename to core/lib/Drupal/Core/Template/ComponentNodeVisitor.php
index 53fd666ab0768c9c9ef00ebee3fc97e42b58fbec..da7a5e85bbfe3ef9d546dc54402b9a61b279ee7e 100644
--- a/core/modules/sdc/src/Twig/ComponentNodeVisitor.php
+++ b/core/lib/Drupal/Core/Template/ComponentNodeVisitor.php
@@ -2,12 +2,12 @@
 
 declare(strict_types=1);
 
-namespace Drupal\sdc\Twig;
+namespace Drupal\Core\Template;
 
-use Drupal\sdc\ComponentPluginManager;
-use Drupal\sdc\Exception\ComponentNotFoundException;
-use Drupal\sdc\Exception\InvalidComponentException;
-use Drupal\sdc\Plugin\Component;
+use Drupal\Core\Plugin\Component;
+use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
+use Drupal\Core\Render\Component\Exception\InvalidComponentException;
+use Drupal\Core\Theme\ComponentPluginManager;
 use Twig\Environment;
 use Twig\Node\Expression\ConstantExpression;
 use Twig\Node\Expression\FunctionExpression;
@@ -18,15 +18,13 @@
 
 /**
  * Provides a ComponentNodeVisitor to change the generated parse-tree.
- *
- * @internal
  */
-final class ComponentNodeVisitor implements NodeVisitorInterface {
+class ComponentNodeVisitor implements NodeVisitorInterface {
 
   /**
    * Creates a new ComponentNodeVisitor object.
    *
-   * @param \Drupal\sdc\ComponentPluginManager $pluginManager
+   * @param \Drupal\Core\Theme\ComponentPluginManager $pluginManager
    *   The plugin manager for components.
    */
   public function __construct(protected ComponentPluginManager $pluginManager) {}
@@ -62,12 +60,12 @@ public function leaveNode(Node $node, Environment $env): ?Node {
       $line
     ), $line);
     $print_nodes[] = new PrintNode(new FunctionExpression(
-      'sdc_additional_context',
+      'add_component_context',
       new Node([new ConstantExpression($component_id, $line)]),
       $line
     ), $line);
     $print_nodes[] = new PrintNode(new FunctionExpression(
-      'sdc_validate_props',
+      'validate_component_props',
       new Node([new ConstantExpression($component_id, $line)]),
       $line
     ), $line);
@@ -103,7 +101,7 @@ public function leaveNode(Node $node, Environment $env): ?Node {
    * @param \Twig\Node\Node $node
    *   The node.
    *
-   * @return \Drupal\sdc\Plugin\Component|null
+   * @return \Drupal\Core\Plugin\Component|null
    *   The component, if any.
    */
   protected function getComponent(Node $node): ?Component {
@@ -135,7 +133,7 @@ public function getPriority(): int {
    * undeclared slots. This cheap validation lets us validate during runtime
    * even in production.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    *   When the slots don't pass validation.
    */
   protected function validateSlots(Component $component, Node $node): void {
diff --git a/core/modules/sdc/src/Twig/TwigExtension.php b/core/lib/Drupal/Core/Template/ComponentsTwigExtension.php
similarity index 65%
rename from core/modules/sdc/src/Twig/TwigExtension.php
rename to core/lib/Drupal/Core/Template/ComponentsTwigExtension.php
index 8205080cb05fc43303a9305b3f225d3afdc8f5d3..b4f5365021b710259e1b66f32c2e67d6249ffdb2 100644
--- a/core/modules/sdc/src/Twig/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/ComponentsTwigExtension.php
@@ -1,13 +1,12 @@
 <?php
 
-namespace Drupal\sdc\Twig;
+namespace Drupal\Core\Template;
 
-use Drupal\Core\Template\Attribute;
-use Drupal\sdc\Component\ComponentValidator;
-use Drupal\sdc\ComponentPluginManager;
-use Drupal\sdc\Exception\ComponentNotFoundException;
-use Drupal\sdc\Exception\InvalidComponentException;
-use Drupal\sdc\Plugin\Component;
+use Drupal\Core\Plugin\Component;
+use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
+use Drupal\Core\Render\Component\Exception\InvalidComponentException;
+use Drupal\Core\Theme\Component\ComponentValidator;
+use Drupal\Core\Theme\ComponentPluginManager;
 use Twig\Extension\AbstractExtension;
 use Twig\TwigFunction;
 
@@ -16,14 +15,14 @@
  *
  * @internal
  */
-final class TwigExtension extends AbstractExtension {
+final class ComponentsTwigExtension extends AbstractExtension {
 
   /**
    * Creates TwigExtension.
    *
-   * @param \Drupal\sdc\ComponentPluginManager $pluginManager
+   * @param \Drupal\Core\Theme\ComponentPluginManager $pluginManager
    *   The component plugin manager.
-   * @param \Drupal\sdc\Component\ComponentValidator $componentValidator
+   * @param \Drupal\Core\Theme\Component\ComponentValidator $componentValidator
    *   The component validator.
    */
   public function __construct(
@@ -43,16 +42,14 @@ public function getNodeVisitors(): array {
    */
   public function getFunctions(): array {
     return [
-      new TwigFunction(
-        'sdc_additional_context',
-        [$this, 'addAdditionalContext'],
-        ['needs_context' => TRUE]
-      ),
-      new TwigFunction(
-        'sdc_validate_props',
-        [$this, 'validateProps'],
-        ['needs_context' => TRUE]
-      ),
+      new TwigFunction('add_component_context', [$this, 'addAdditionalContext'], ['needs_context' => TRUE]),
+      new TwigFunction('validate_component_props', [$this, 'validateProps'], ['needs_context' => TRUE]),
+      // @todo remove in drupal:11.0.0.
+      // @see https://www.drupal.org/project/drupal/issues/3409456.
+      // Start of BC layer.
+      new TwigFunction('sdc_additional_context', [$this, 'addAdditionalContext'], ['needs_context' => TRUE, 'deprecated' => '10.3.0', 'alternative' => 'add_component_context']),
+      new TwigFunction('sdc_validate_props', [$this, 'validateProps'], ['needs_context' => TRUE, 'deprecated' => '10.3.0', 'alternative' => 'validate_component_props']),
+      // End of BC layer.
     ];
   }
 
@@ -64,7 +61,7 @@ public function getFunctions(): array {
    * @param string $component_id
    *   The component ID.
    *
-   * @throws \Drupal\sdc\Exception\ComponentNotFoundException
+   * @throws \Drupal\Core\Render\Component\Exception\ComponentNotFoundException
    */
   public function addAdditionalContext(array &$context, string $component_id): void {
     $context = $this->mergeAdditionalRenderContext(
@@ -76,7 +73,7 @@ public function addAdditionalContext(array &$context, string $component_id): voi
   /**
    * Calculates additional context for this template.
    *
-   * @param \Drupal\sdc\Plugin\Component $component
+   * @param \Drupal\Core\Plugin\Component $component
    *   The component.
    * @param array $context
    *   The context to update.
@@ -106,7 +103,7 @@ protected function mergeAdditionalRenderContext(Component $component, array $con
    * @param string $component_id
    *   The component ID.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   public function validateProps(array &$context, string $component_id): void {
     assert($this->doValidateProps($context, $component_id));
@@ -123,7 +120,7 @@ public function validateProps(array &$context, string $component_id): void {
    * @return bool
    *   TRUE if it's valid.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   protected function doValidateProps(array $context, string $component_id): bool {
     try {
diff --git a/core/modules/sdc/src/Twig/TwigComponentLoader.php b/core/lib/Drupal/Core/Template/Loader/ComponentLoader.php
similarity index 91%
rename from core/modules/sdc/src/Twig/TwigComponentLoader.php
rename to core/lib/Drupal/Core/Template/Loader/ComponentLoader.php
index baa069a7584aeab5a2726247a5d9e351f630ee84..2be45eb0abd633942fd0404ea76c89c8c5cfe96d 100644
--- a/core/modules/sdc/src/Twig/TwigComponentLoader.php
+++ b/core/lib/Drupal/Core/Template/Loader/ComponentLoader.php
@@ -1,11 +1,11 @@
 <?php
 
-namespace Drupal\sdc\Twig;
+namespace Drupal\Core\Template\Loader;
 
-use Drupal\Core\Utility\Error;
-use Drupal\sdc\ComponentPluginManager;
-use Drupal\sdc\Exception\ComponentNotFoundException;
 use Drupal\Component\Discovery\YamlDirectoryDiscovery;
+use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
+use Drupal\Core\Theme\ComponentPluginManager;
+use Drupal\Core\Utility\Error;
 use Psr\Log\LoggerInterface;
 use Twig\Error\LoaderError;
 use Twig\Loader\LoaderInterface;
@@ -13,15 +13,13 @@
 
 /**
  * Lets you load templates using the component ID.
- *
- * @internal
  */
-final class TwigComponentLoader implements LoaderInterface {
+class ComponentLoader implements LoaderInterface {
 
   /**
    * Constructs a new ComponentLoader object.
    *
-   * @param \Drupal\sdc\ComponentPluginManager $pluginManager
+   * @param \Drupal\Core\Theme\ComponentPluginManager $pluginManager
    *   The plugin manager.
    * @param \Psr\Log\LoggerInterface $logger
    *   The logger.
@@ -107,7 +105,7 @@ public function getCacheKey($name): string {
       throw new LoaderError('Unable to find component');
     }
     return implode('--', array_filter([
-      'sdc',
+      'components',
       $name,
       $component->getPluginDefinition()['provider'] ?? '',
     ]));
diff --git a/core/modules/sdc/src/Component/ComponentMetadata.php b/core/lib/Drupal/Core/Theme/Component/ComponentMetadata.php
similarity index 94%
rename from core/modules/sdc/src/Component/ComponentMetadata.php
rename to core/lib/Drupal/Core/Theme/Component/ComponentMetadata.php
index 45f394e26ba1d4ea7ad1b7c7425d21d2475b6ce3..f5c2866bd605416316bd3a0805854e27609d75c8 100644
--- a/core/modules/sdc/src/Component/ComponentMetadata.php
+++ b/core/lib/Drupal/Core/Theme/Component/ComponentMetadata.php
@@ -1,17 +1,15 @@
 <?php
 
-namespace Drupal\sdc\Component;
+namespace Drupal\Core\Theme\Component;
 
 use Drupal\Core\Extension\ExtensionLifecycle;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\sdc\Exception\InvalidComponentException;
+use Drupal\Core\Render\Component\Exception\InvalidComponentException;
 
 /**
  * Component metadata.
- *
- * @internal
  */
-final class ComponentMetadata {
+class ComponentMetadata {
 
   use StringTranslationTrait;
 
@@ -103,7 +101,7 @@ final class ComponentMetadata {
    * @param bool $enforce_schemas
    *   Enforces the definition of schemas for props and slots.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   public function __construct(array $metadata_info, string $app_root, bool $enforce_schemas) {
     $path = $metadata_info['path'];
@@ -137,7 +135,7 @@ public function __construct(array $metadata_info, string $app_root, bool $enforc
    * @param array $metadata_info
    *   The metadata information as decoded from the component definition file.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   private function parseSchemaInfo(array $metadata_info): void {
     if (empty($metadata_info['props'])) {
diff --git a/core/modules/sdc/src/Component/ComponentValidator.php b/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
similarity index 94%
rename from core/modules/sdc/src/Component/ComponentValidator.php
rename to core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
index e1d76f6b1da368ff01b33ead32a49e45a1475ede..41cd4b35bfb231cf8ea0e86d8021fa126b6a9554 100644
--- a/core/modules/sdc/src/Component/ComponentValidator.php
+++ b/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php
@@ -1,19 +1,17 @@
 <?php
 
-namespace Drupal\sdc\Component;
+namespace Drupal\Core\Theme\Component;
 
-use Drupal\sdc\Exception\InvalidComponentException;
-use Drupal\sdc\Plugin\Component;
-use Drupal\sdc\Utilities;
+use Drupal\Core\Render\Component\Exception\InvalidComponentException;
+use Drupal\Core\Render\Element;
+use Drupal\Core\Plugin\Component;
 use JsonSchema\Constraints\Constraint;
 use JsonSchema\Validator;
 
 /**
  * Validates a component based on its definition and the component schema.
- *
- * @internal
  */
-final class ComponentValidator {
+class ComponentValidator {
 
   /**
    * The schema validator.
@@ -52,7 +50,7 @@ public function setValidator(Validator $validator = NULL): void {
    * @return bool
    *   TRUE if the component is valid.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   public function validateDefinition(array $definition, bool $enforce_schemas): bool {
     // First ensure there are no name collisions between props and slots.
@@ -105,7 +103,7 @@ public function validateDefinition(array $definition, bool $enforce_schemas): bo
     $definition_object = Validator::arrayToObjectRecursive($definition);
     $this->validator->validate(
       $definition_object,
-      (object) ['$ref' => 'file://' . dirname(__DIR__) . '/metadata-full.schema.json']
+      (object) ['$ref' => 'file://' . dirname(__DIR__, 5) . '/assets/schemas/v1/metadata-full.schema.json']
     );
     if (empty($missing_class_errors) && $this->validator->isValid()) {
       return TRUE;
@@ -131,13 +129,13 @@ public function validateDefinition(array $definition, bool $enforce_schemas): bo
    *
    * @param array $context
    *   The Twig context that contains the prop data.
-   * @param \Drupal\sdc\Plugin\Component $component
+   * @param \Drupal\Core\Plugin\Component $component
    *   The component to validate the props against.
    *
    * @return bool
    *   TRUE if the props adhere to the component definition.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   public function validateProps(array $context, Component $component): bool {
     // If the validator isn't set, then the validation library is not installed.
@@ -181,7 +179,7 @@ function (array $error) use ($context): bool {
         if (($error['constraint'] ?? '') !== 'type') {
           return TRUE;
         }
-        return !Utilities::isRenderArray($context[$error['property']] ?? NULL);
+        return !Element::isRenderArray($context[$error['property']] ?? NULL);
       }
     );
     if (empty($errors)) {
@@ -226,7 +224,7 @@ static function (array $error): string {
    *   Schema. We can do this because we have already validated these props
    *   manually.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   private function validateClassProps(array $props_schema, array $props_raw, string $component_id): array {
     $error_messages = [];
diff --git a/core/modules/sdc/src/Component/SchemaCompatibilityChecker.php b/core/lib/Drupal/Core/Theme/Component/SchemaCompatibilityChecker.php
similarity index 96%
rename from core/modules/sdc/src/Component/SchemaCompatibilityChecker.php
rename to core/lib/Drupal/Core/Theme/Component/SchemaCompatibilityChecker.php
index 0744fd0ef3173c3de85fe3a3b226d3debd547a77..9bc36826d34e69696a9066169687e828e31d5ce1 100644
--- a/core/modules/sdc/src/Component/SchemaCompatibilityChecker.php
+++ b/core/lib/Drupal/Core/Theme/Component/SchemaCompatibilityChecker.php
@@ -1,8 +1,8 @@
 <?php
 
-namespace Drupal\sdc\Component;
+namespace Drupal\Core\Theme\Component;
 
-use Drupal\sdc\Exception\IncompatibleComponentSchema;
+use Drupal\Core\Render\Component\Exception\IncompatibleComponentSchema;
 
 /**
  * Checks whether two schemas are compatible.
@@ -11,10 +11,8 @@
  * component if the schemas are not compatible. Component authors must consider
  * their component schema as part of their module/theme API. Breaking changes
  * to the schema must be done in a new major version.
- *
- * @internal
  */
-final class SchemaCompatibilityChecker {
+class SchemaCompatibilityChecker {
 
   /**
    * Checks if the replacement schema is compatible with the old one.
@@ -32,7 +30,7 @@ final class SchemaCompatibilityChecker {
    * @param array $new_schema
    *   The new schema that should be compatible with.
    *
-   * @throws \Drupal\sdc\Exception\IncompatibleComponentSchema
+   * @throws \Drupal\Core\Render\Component\Exception\IncompatibleComponentSchema
    */
   public function isCompatible(array $original_schema, array $new_schema): void {
     $error_messages = [];
diff --git a/core/modules/sdc/src/ComponentNegotiator.php b/core/lib/Drupal/Core/Theme/ComponentNegotiator.php
similarity index 90%
rename from core/modules/sdc/src/ComponentNegotiator.php
rename to core/lib/Drupal/Core/Theme/ComponentNegotiator.php
index 68a8f5500808ca67e9576d98a29d1b38cb1fb0ed..43cf466c07f4c32a1539c1516a2179d2880ac215 100644
--- a/core/modules/sdc/src/ComponentNegotiator.php
+++ b/core/lib/Drupal/Core/Theme/ComponentNegotiator.php
@@ -1,25 +1,14 @@
 <?php
 
-namespace Drupal\sdc;
+namespace Drupal\Core\Theme;
 
 use Drupal\Core\Extension\Extension;
 use Drupal\Core\Extension\ModuleExtensionList;
-use Drupal\Core\Theme\ActiveTheme;
-use Drupal\Core\Theme\ThemeManagerInterface;
 
 /**
  * Determines which component should be used.
- *
- * @internal
  */
-final class ComponentNegotiator {
-
-  /**
-   * The active theme.
-   *
-   * @var \Drupal\Core\Theme\ActiveTheme
-   */
-  protected ActiveTheme $activeTheme;
+class ComponentNegotiator {
 
   /**
    * Holds the component IDs from previous negotiations.
@@ -40,7 +29,6 @@ public function __construct(
     protected ThemeManagerInterface $themeManager,
     protected ModuleExtensionList $moduleExtensionList
   ) {
-    $this->activeTheme = $this->themeManager->getActiveTheme();
   }
 
   /**
@@ -48,7 +36,7 @@ public function __construct(
    *
    * @param string $component_id
    *   The requested component id. Ex: 'my-button', 'my-button--primary',
-   *   'sdc_example:my-button--primary', ...
+   *   'component_example:my-button--primary', ...
    * @param array[] $all_definitions
    *   All the plugin definitions for components keyed by plugin ID.
    *
@@ -71,7 +59,7 @@ public function negotiate(string $component_id, array $all_definitions): ?string
    *
    * @param string $component_id
    *   The requested component id. Ex: 'my-button', 'my-button--primary',
-   *   'sdc_example:my-button--primary', ...
+   *   'component_example:my-button--primary', ...
    * @param array[] $all_definitions
    *   All the plugin definitions for components keyed by plugin ID.
    *
@@ -103,11 +91,11 @@ private function doNegotiate(string $component_id, array $all_definitions): ?str
    */
   private function maybeNegotiateByTheme(array $candidates): ?string {
     // Prepare the error message.
-    $theme_name = $this->activeTheme->getName();
+    $theme_name = $this->themeManager->getActiveTheme()->getName();
     // Let's do theme based negotiation.
     $base_theme_names = array_map(
       static fn(Extension $extension) => $extension->getName(),
-      $this->activeTheme->getBaseThemeExtensions()
+      $this->themeManager->getActiveTheme()->getBaseThemeExtensions()
     );
     $considered_themes = [$theme_name, ...$base_theme_names];
     // Only consider components in the theme hierarchy tree.
@@ -169,9 +157,9 @@ private function maybeNegotiateByModule(array $candidates): ?string {
    */
   private function generateCacheKey(string $component_id): string {
     return sprintf(
-      'sdc-negotiation::%s::%s',
+      'component-negotiation::%s::%s',
       $component_id,
-      $this->activeTheme->getName()
+      $this->themeManager->getActiveTheme()->getName()
     );
   }
 
diff --git a/core/modules/sdc/src/ComponentPluginManager.php b/core/lib/Drupal/Core/Theme/ComponentPluginManager.php
similarity index 88%
rename from core/modules/sdc/src/ComponentPluginManager.php
rename to core/lib/Drupal/Core/Theme/ComponentPluginManager.php
index 6a825febe0231ae1940fb08e707c0202a0b45372..9b33c7af2b93a6a4805f08203ddd421ac556044d 100644
--- a/core/modules/sdc/src/ComponentPluginManager.php
+++ b/core/lib/Drupal/Core/Theme/ComponentPluginManager.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\sdc;
+namespace Drupal\Core\Theme;
 
 use Drupal\Component\Assertion\Inspector;
 use Drupal\Component\Discovery\YamlDirectoryDiscovery;
@@ -13,25 +13,22 @@
 use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\Plugin\DefaultPluginManager;
 use Drupal\Core\Plugin\Factory\ContainerFactory;
-use Drupal\Core\Theme\ThemeManagerInterface;
-use Drupal\sdc\Component\ComponentValidator;
-use Drupal\sdc\Component\SchemaCompatibilityChecker;
-use Drupal\sdc\Exception\ComponentNotFoundException;
-use Drupal\sdc\Exception\IncompatibleComponentSchema;
-use Drupal\sdc\Plugin\Component;
-use Drupal\sdc\Plugin\Discovery\DirectoryWithMetadataPluginDiscovery;
+use Drupal\Core\Theme\Component\ComponentValidator;
+use Drupal\Core\Theme\Component\SchemaCompatibilityChecker;
+use Drupal\Core\Plugin\Component;
+use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
+use Drupal\Core\Render\Component\Exception\IncompatibleComponentSchema;
+use Drupal\Core\Plugin\Discovery\DirectoryWithMetadataPluginDiscovery;
 
 /**
- * Defines a plugin manager to deal with sdc.
+ * Defines a plugin manager to deal with components.
  *
  * Modules and themes can create components by adding a folder under
- * MODULENAME/components/my-component/my-component.sdc.yml.
+ * MODULENAME/components/my-component/my-component.component.yml.
  *
  * @see plugin_api
- *
- * @internal
  */
-final class ComponentPluginManager extends DefaultPluginManager {
+class ComponentPluginManager extends DefaultPluginManager {
 
   /**
    * {@inheritdoc}
@@ -41,7 +38,7 @@ final class ComponentPluginManager extends DefaultPluginManager {
   ];
 
   /**
-   * Constructs SdcPluginManager object.
+   * Constructs ComponentPluginManager object.
    *
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
@@ -53,13 +50,13 @@ final class ComponentPluginManager extends DefaultPluginManager {
    *   The configuration factory.
    * @param \Drupal\Core\Theme\ThemeManagerInterface $themeManager
    *   The theme manager.
-   * @param \Drupal\sdc\ComponentNegotiator $componentNegotiator
+   * @param \Drupal\Core\Theme\ComponentNegotiator $componentNegotiator
    *   The component negotiator.
    * @param \Drupal\Core\File\FileSystemInterface $fileSystem
    *   The file system service.
-   * @param \Drupal\sdc\Component\SchemaCompatibilityChecker $compatibilityChecker
+   * @param \Drupal\Core\Theme\Component\SchemaCompatibilityChecker $compatibilityChecker
    *   The compatibility checker.
-   * @param \Drupal\sdc\Component\ComponentValidator $componentValidator
+   * @param \Drupal\Core\Theme\Component\ComponentValidator $componentValidator
    *   The component validator.
    * @param string $appRoot
    *   The application root.
@@ -82,8 +79,8 @@ public function __construct(
     // like LinkRelationTypeManager.
     $this->moduleHandler = $module_handler;
     $this->factory = new ContainerFactory($this);
-    $this->setCacheBackend($cacheBackend, 'sdc_plugins');
-    // Note that we are intentionally skipping $this->alterInfo('sdc_info');
+    $this->setCacheBackend($cacheBackend, 'component_plugins');
+    // Note that we are intentionally skipping $this->alterInfo('component_info');
     // We want to ensure that everything related to a component is in the
     // single directory. If the alteration of a component is necessary,
     // component replacement is the preferred tool for that.
@@ -92,7 +89,7 @@ public function __construct(
   /**
    * Creates an instance.
    *
-   * @throws \Drupal\sdc\Exception\ComponentNotFoundException
+   * @throws \Drupal\Core\Render\Component\Exception\ComponentNotFoundException
    *
    * @internal
    */
@@ -128,12 +125,10 @@ public function createInstance($plugin_id, array $configuration = []): Component
    * @param string $component_id
    *   The component ID.
    *
-   * @return \Drupal\sdc\Plugin\Component
+   * @return \Drupal\Core\Plugin\Component
    *   The component.
    *
-   * @throws \Drupal\sdc\Exception\ComponentNotFoundException
-   *
-   * @internal
+   * @throws \Drupal\Core\Render\Component\Exception\ComponentNotFoundException
    */
   public function find(string $component_id): Component {
     $definitions = $this->getDefinitions();
@@ -147,10 +142,8 @@ public function find(string $component_id): Component {
   /**
    * Gets all components.
    *
-   * @return \Drupal\sdc\Plugin\Component[]
+   * @return \Drupal\Core\Plugin\Component[]
    *   An array of Component objects.
-   *
-   * @internal
    */
   public function getAllComponents(): array {
     $plugin_ids = array_keys($this->getDefinitions());
@@ -227,7 +220,7 @@ protected function libraryFromDefinition(array $definition): array {
   protected function getDiscovery(): DirectoryWithMetadataPluginDiscovery {
     if (!isset($this->discovery)) {
       $directories = $this->getScanDirectories();
-      $this->discovery = new DirectoryWithMetadataPluginDiscovery($directories, 'sdc', $this->fileSystem);
+      $this->discovery = new DirectoryWithMetadataPluginDiscovery($directories, 'component', $this->fileSystem);
     }
     return $this->discovery;
   }
@@ -338,7 +331,7 @@ protected function alterDefinition(array $definition): array {
    * @return bool
    *   TRUE if it's valid.
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   private function isValidDefinition(array $definition): bool {
     return $this->componentValidator->validateDefinition(
@@ -441,10 +434,10 @@ private function shouldEnforceSchemas(array $definition): bool {
    * @param string $file_extension
    *   The file extension to detect.
    * @param bool $make_relative
-   *   TRUE to make the filename relative to the SDC module location.
+   *   TRUE to make the filename relative to the core folder.
    *
    * @return string|null
-   *   Filenames, maybe relative to the sdc module.
+   *   Filenames, maybe relative to the core folder.
    */
   private function findAsset(string $component_directory, string $machine_name, string $file_extension, bool $make_relative = FALSE): ?string {
     $absolute_path = sprintf('%s%s%s.%s', $component_directory, DIRECTORY_SEPARATOR, $machine_name, $file_extension);
@@ -460,11 +453,11 @@ private function findAsset(string $component_directory, string $machine_name, st
    * Takes a path and makes it relative to the library provider.
    *
    * Drupal will take a path relative to the library provider in order to put
-   * CSS and JS in the HTML page. The SDC module is the provider for all the
+   * CSS and JS in the HTML page. Core is the provider for all the
    * auto-generated libraries for the components. This means that in order to
    * add <root>/themes/custom/my_theme/components/my-component/my-component.css
-   * in the page, we need to crawl back up from <root>/core/modules/sdc first:
-   * ../../../../themes/custom/my_theme/components/my-component/my-component.css
+   * in the page, we need to crawl back up from <root>/core first:
+   * ../themes/custom/my_theme/components/my-component/my-component.css.
    *
    * @param string $path
    *   The path to the file.
@@ -473,17 +466,12 @@ private function findAsset(string $component_directory, string $machine_name, st
    *   The path relative to the library provider root.
    */
   private function makePathRelativeToLibraryRoot(string $path): string {
-    $library_provider_root = $this->moduleHandler
-      ->getModule('sdc')
-      ->getPath();
-    $num_dots = count(
-      array_filter(explode(DIRECTORY_SEPARATOR, $library_provider_root))
-    );
-    $dots = str_repeat('../', $num_dots);
     $path_from_root = str_starts_with($path, $this->appRoot)
       ? substr($path, strlen($this->appRoot) + 1)
       : $path;
-    return $dots . $path_from_root;
+    // The library owner is in <root>/core, so we need to go one level up to
+    // find the app root.
+    return '../' . $path_from_root;
   }
 
 }
diff --git a/core/modules/sdc/src/ExtensionType.php b/core/lib/Drupal/Core/Theme/ExtensionType.php
similarity index 90%
rename from core/modules/sdc/src/ExtensionType.php
rename to core/lib/Drupal/Core/Theme/ExtensionType.php
index 40ca8f59a8d55c33b4bfccff0e2c1f5a63f55691..a47bbb1ae3ec9cf3fe2c1024e3d4b0cf2fb8d45f 100644
--- a/core/modules/sdc/src/ExtensionType.php
+++ b/core/lib/Drupal/Core/Theme/ExtensionType.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\sdc;
+namespace Drupal\Core\Theme;
 
 /**
  * Enum for supported extension types.
diff --git a/core/modules/sdc/README.txt b/core/modules/sdc/README.txt
index 6029812210c7cb2ee1693d96374248e1b24a25c7..fdb7db73186dd5ec1a292d5cf5032ad6ba046301 100644
--- a/core/modules/sdc/README.txt
+++ b/core/modules/sdc/README.txt
@@ -10,7 +10,7 @@ The API of Single Directory Components includes:
   - The structure of the component metadata (the my-component.component.yml).
     Note that the metadata of the component is described, and optionally
     validated, by the schema in metadata.schema.json (this file is for internal validation and not part of the API).
-  - The render element and its class \Drupal\sdc\Element\ComponentElement.
+  - The render element and its class \Drupal\Core\Render\Element\ComponentElement.
   - The naming convention for the ID when using Twig's include, embed, and
     extends. This naming convention is [module/theme]:[component machine name].
     See the example below.
diff --git a/core/modules/sdc/sdc.info.yml b/core/modules/sdc/sdc.info.yml
index 816437c609945209320f903141a98d80d50135a2..98ef12cc4312e6bc47336fe8609c28fb94085bb4 100644
--- a/core/modules/sdc/sdc.info.yml
+++ b/core/modules/sdc/sdc.info.yml
@@ -3,6 +3,7 @@ type: module
 description: 'Allows discovery and rendering of self-contained UI components.'
 version: VERSION
 package: Core (Experimental)
-lifecycle: experimental
+lifecycle: deprecated
+lifecycle_link: 'https://www.drupal.org/docs/core-modules-and-themes/deprecated-and-obsolete#s-understanding-deprecated-extensions'
 dependencies:
   - drupal:serialization
diff --git a/core/modules/sdc/sdc.module b/core/modules/sdc/sdc.module
index 931de0189d595132df3a667df5bdf598717319f4..89da82a3448aaa5abbdd38abb3ae608efb1a7590 100644
--- a/core/modules/sdc/sdc.module
+++ b/core/modules/sdc/sdc.module
@@ -5,73 +5,60 @@
  * Module implementation file.
  */
 
-use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\sdc\Plugin\Component;
-use Drupal\sdc\ComponentPluginManager;
+use Drupal\Core\Theme\ComponentPluginManager;
+use Drupal\Core\Plugin\Component;
 
-/**
- * @file
- * Module implementation file.
- */
-
-// Set class aliases for the classes that will go into core.
-// See the experimental modules policy https://www.drupal.org/core/experimental
-// @todo: remove class aliases in #3354389
-@class_alias('Drupal\sdc\Element\ComponentElement', 'Drupal\Core\Render\Element\ComponentElement');
-@class_alias('Drupal\sdc\Exception\ComponentNotFoundException', 'Drupal\Core\Render\Component\Exception\ComponentNotFoundException');
-@class_alias('Drupal\sdc\Exception\IncompatibleComponentSchema', 'Drupal\Core\Render\Component\Exception\IncompatibleComponentSchema');
-@class_alias('Drupal\sdc\Exception\InvalidComponentDataException', 'Drupal\Core\Render\Component\Exception\InvalidComponentDataException');
-@class_alias('Drupal\sdc\Exception\InvalidComponentException', 'Drupal\Core\Render\Component\Exception\InvalidComponentException');
-
-/**
- * Implements hook_help().
- */
-function sdc_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    case 'help.page.sdc':
-      $output = '<h2>' . t('About') . '</h2>';
-      $output .= '<p>' . t('Single Directory Components is a module that aims to simplify the front-end development workflow, and improve maintainability of core and contrib themes. For more information, see the <a href=":docs">online documentation for the Single Directory Components module</a>.', [
-        ':docs' => 'https://www.drupal.org/docs/develop/theming-drupal/using-single-directory-components',
-      ]) . '</p>';
-      $output .= '<dl>';
-      $output .= '<dt>' . t('General') . '</dt>';
-      $output .= '<dd>' . t('Single Directory Components introduces the concept of UI components to Drupal core. A component is a combination of a Twig template, stylesheets, scripts, assets, and metadata, that live in the same directory. Components represent an encapsulated and re-usable UI element.') . '</dd>';
-      $output .= '<dd>' . t('<a href=":sdc-docs">Single Directory Components</a> reduce the number of framework implementation details required to put templated HTML, CSS, and JS in a Drupal page. They also define explicit component APIs, and provide a methodology to replace a component provided upstream (in a parent theme or module).', [
-        ':sdc-docs' => 'https://www.drupal.org/docs/develop/theming-drupal/using-single-directory-components',
-      ]) . '</dd>';
-      $output .= '</dl>';
-
-      return $output;
-  }
-  return NULL;
-}
+@class_alias('Drupal\Core\Render\Element', 'Drupal\sdc\Utilities');
+@class_alias('Drupal\Core\Render\Element\ComponentElement', 'Drupal\sdc\Element\ComponentElement');
+@class_alias('Drupal\Core\Render\Component\Exception\ComponentNotFoundException', 'Drupal\sdc\Exception\ComponentNotFoundException');
+@class_alias('Drupal\Core\Render\Component\Exception\IncompatibleComponentSchema', 'Drupal\sdc\Exception\IncompatibleComponentSchema');
+@class_alias('Drupal\Core\Render\Component\Exception\InvalidComponentDataException', 'Drupal\sdc\Exception\InvalidComponentDataException');
+@class_alias('Drupal\Core\Render\Component\Exception\InvalidComponentException', 'Drupal\sdc\Exception\InvalidComponentException');
+@class_alias('Drupal\Core\Theme\Component\ComponentMetadata', 'Drupal\sdc\Component\ComponentMetadata');
+@class_alias('Drupal\Core\Theme\Component\ComponentValidator', 'Drupal\sdc\Component\ComponentValidator');
+@class_alias('Drupal\Core\Theme\Component\SchemaCompatibilityChecker', 'Drupal\sdc\Component\SchemaCompatibilityChecker');
+@class_alias('Drupal\Core\Plugin\Component', 'Drupal\sdc\Plugin\Component');
+@class_alias('Drupal\Core\Plugin\Discovery\DirectoryWithMetadataDiscovery', 'Drupal\sdc\Plugin\Discovery\DirectoryWithMetadataDiscovery');
+@class_alias('Drupal\Core\Plugin\Discovery\DirectoryWithMetadataPluginDiscovery', 'Drupal\sdc\Plugin\Discovery\DirectoryWithMetadataPluginDiscovery');
+@class_alias('Drupal\Core\Plugin\Discovery\RegexRecursiveFilterIterator', 'Drupal\sdc\Plugin\Discovery\RegexRecursiveFilterIterator');
+@class_alias('Drupal\Core\Template\ComponentNodeVisitor', 'Drupal\sdc\Twig\ComponentNodeVisitor');
+@class_alias('Drupal\Core\Template\Loader\ComponentLoader', 'Drupal\sdc\Twig\TwigComponentLoader');
+@class_alias('Drupal\Core\Theme\ComponentNegotiator', 'Drupal\sdc\ComponentNegotiator');
+@class_alias('Drupal\Core\Theme\ComponentPluginManager', 'Drupal\sdc\ComponentPluginManager');
+@class_alias('Drupal\Core\Theme\ExtensionType', 'Drupal\sdc\ExtensionType');
 
 /**
  * Implements hook_library_info_build().
  */
 function sdc_library_info_build() {
+  $deprecation_message = 'The %library_id% asset library is deprecated in Drupal 10.3.0 and will be removed in Drupal 11.0.0. Use the core/components.[component-id] library instead. See https://www.drupal.org/node/3410260';
   // Iterate over all the components to get the CSS and JS files.
   $plugin_manager = \Drupal::service('plugin.manager.sdc');
   assert($plugin_manager instanceof ComponentPluginManager);
   $components = $plugin_manager->getAllComponents();
+  // Generate backwards compatible deprecated libraries that depend on the new
+  // library name scheme.
   $libraries = array_reduce(
     $components,
-    static function (array $libraries, Component $component) {
-      $library = $component->library;
-      if (empty($library)) {
-        return $libraries;
-      }
+    static function (array $libraries, Component $component) use ($deprecation_message) {
+      // The library name is something like core/components.my-theme--my-comp.
       $library_name = $component->getLibraryName();
-      [, $library_id] = explode('/', $library_name);
-      return array_merge($libraries, [$library_id => $library]);
+      // The library ID is something like my-theme--my-comp.
+      $library_id = str_replace('core/components.', '', $library_name);
+      // Adding these libraries will result in the old 'sdc/my-theme--my-comp'.
+      return array_merge($libraries, [
+        $library_id => [
+          'dependencies' => [$library_name],
+          'deprecated' => $deprecation_message,
+        ],
+      ]);
     },
     []
   );
+  // Alias the library sdc/all to core/components.all.
   $libraries['all'] = [
-    'dependencies' => array_map(
-      static fn(Component $component) => $component->getLibraryName(),
-      $components
-    ),
+    'dependencies' => ['core/components.all'],
+    'deprecated' => 'The %library_id% asset library is deprecated in Drupal 10.3.0 and will be removed in Drupal 11.0.0. Use the core/components.all library instead. See https://www.drupal.org/node/3410260',
   ];
   return $libraries;
 }
diff --git a/core/modules/sdc/sdc.services.yml b/core/modules/sdc/sdc.services.yml
index 519acef6100d9d18d00d59f28e56a54a400b5ce3..379762e1d7938f30847578de1566d0f910adbf76 100644
--- a/core/modules/sdc/sdc.services.yml
+++ b/core/modules/sdc/sdc.services.yml
@@ -2,55 +2,43 @@ services:
   _defaults:
     public: false
 
-  # Twig loader to allow embedding templates with a component identifier.
-  # Note that this service name is not guaranteed to remain the same once this
-  # module is out of the experimental phase.
+  # This service is deprecated, use the one defined in core instead.
   Drupal\sdc\Twig\TwigComponentLoader:
-    arguments:
-      - '@plugin.manager.sdc'
-      - '@logger.channel.default'
-    tags:
-      - { name: twig.loader, priority: 5 }
+    alias: 'Drupal\Core\Template\Loader\ComponentLoader'
+    deprecated:
+      package: 'drupal/core'
+      version: '10.3.0'
+      message: The "%alias_id%" service is deprecated since drupal/core 10.3.0 and will be removed in 11.0.
 
-  # Note that this service name is not guaranteed to remain the same once this
-  # module is out of the experimental phase.
+  # This service is deprecated, use the one defined in core instead.
   Drupal\sdc\ComponentNegotiator:
-    arguments:
-      - '@theme.manager'
-      - '@extension.list.module'
+    alias: 'Drupal\Core\Theme\ComponentNegotiator'
+    deprecated:
+      package: 'drupal/core'
+      version: '10.3.0'
+      message: The "%alias_id%" service is deprecated since drupal/core 10.3.0 and will be removed in 11.0.
 
-  # Note that this service name is not guaranteed to remain the same once this
-  # module is out of the experimental phase.
+  # This service defines the deprecated twig functions related to SDC.
+  # Use the ones defined in core instead.
   Drupal\sdc\Twig\TwigExtension:
-    arguments:
-      - '@plugin.manager.sdc'
-      - '@Drupal\sdc\Component\ComponentValidator'
-    tags:
-      - { name: twig.extension }
+    alias: 'Drupal\Core\Template\ComponentsTwigExtension'
+    deprecated:
+      package: 'drupal/core'
+      version: '10.3.0'
+      message: The "%alias_id%" service is deprecated since drupal/core 10.3.0 and will be removed in 11.0.
 
-  # This service is part of the module's API and it's guaranteed to have the
-  # same name once the module is stable.
-  plugin.manager.sdc:
-    public: true
-    class: Drupal\sdc\ComponentPluginManager
-    arguments:
-      - '@module_handler'
-      - '@theme_handler'
-      - '@cache.discovery'
-      - '@config.factory'
-      - '@theme.manager'
-      - '@Drupal\sdc\ComponentNegotiator'
-      - '@file_system'
-      - '@Drupal\sdc\Component\SchemaCompatibilityChecker'
-      - '@Drupal\sdc\Component\ComponentValidator'
-      - '%app.root%'
+  # This service is deprecated, use the one defined in core instead.
+  Drupal\sdc\Component\SchemaCompatibilityChecker:
+    alias: 'Drupal\Core\Theme\Component\SchemaCompatibilityChecker'
+    deprecated:
+      package: 'drupal/core'
+      version: '10.3.0'
+      message: The "%alias_id%" service is deprecated since drupal/core 10.3.0 and will be removed in 11.0.
 
-  # Note that this service name is not guaranteed to remain the same once this
-  # module is out of the experimental phase.
-  Drupal\sdc\Component\SchemaCompatibilityChecker: {}
-
-  # Note that this service name is not guaranteed to remain the same once this
-  # module is out of the experimental phase.
+  # This service is deprecated, use the one defined in core instead.
   Drupal\sdc\Component\ComponentValidator:
-    calls:
-      - [setValidator, []]
+    alias: 'Drupal\Core\Theme\Component\ComponentValidator'
+    deprecated:
+      package: 'drupal/core'
+      version: '10.3.0'
+      message: The "%alias_id%" service is deprecated since drupal/core 10.3.0 and will be removed in 11.0.
diff --git a/core/modules/sdc/src/Exception/ComponentNotFoundException.php b/core/modules/sdc/src/Exception/ComponentNotFoundException.php
deleted file mode 100644
index 677572cd4f307f0deac0740113ff13112a09b644..0000000000000000000000000000000000000000
--- a/core/modules/sdc/src/Exception/ComponentNotFoundException.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-namespace Drupal\sdc\Exception;
-
-/**
- * Raised when a component cannot be found.
- *
- * @internal
- */
-final class ComponentNotFoundException extends \Exception {
-
-}
diff --git a/core/modules/sdc/src/Exception/IncompatibleComponentSchema.php b/core/modules/sdc/src/Exception/IncompatibleComponentSchema.php
deleted file mode 100644
index d614fabab1bc4be46d24a0887ee637a4650a12e1..0000000000000000000000000000000000000000
--- a/core/modules/sdc/src/Exception/IncompatibleComponentSchema.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-namespace Drupal\sdc\Exception;
-
-/**
- * Custom exception for incompatible schemas.
- *
- * @internal
- */
-final class IncompatibleComponentSchema extends \Exception {
-
-}
diff --git a/core/modules/sdc/src/Exception/InvalidComponentDataException.php b/core/modules/sdc/src/Exception/InvalidComponentDataException.php
deleted file mode 100644
index 971b767d7dec50e125510536cb04a35b74742b5f..0000000000000000000000000000000000000000
--- a/core/modules/sdc/src/Exception/InvalidComponentDataException.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-namespace Drupal\sdc\Exception;
-
-/**
- * Raised when a component is rendering with invalid data.
- *
- * @internal
- */
-final class InvalidComponentDataException extends \Exception {
-
-}
diff --git a/core/modules/sdc/src/Exception/InvalidComponentException.php b/core/modules/sdc/src/Exception/InvalidComponentException.php
deleted file mode 100644
index b276b14fc5893c794e51c032e9ad7937eb6449ab..0000000000000000000000000000000000000000
--- a/core/modules/sdc/src/Exception/InvalidComponentException.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-namespace Drupal\sdc\Exception;
-
-/**
- * Custom exception for invalid components.
- *
- * @internal
- */
-final class InvalidComponentException extends \Exception {
-
-}
diff --git a/core/modules/sdc/src/Utilities.php b/core/modules/sdc/src/Utilities.php
deleted file mode 100644
index 35010419b81ac27a2e8dc526bab07be79d1fbffc..0000000000000000000000000000000000000000
--- a/core/modules/sdc/src/Utilities.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-namespace Drupal\sdc;
-
-/**
- * Shared utilities for SDC.
- *
- * @internal
- */
-final class Utilities {
-
-  /**
-   * This class should not be instantiated.
-   */
-  private function __construct() {
-  }
-
-  /**
-   * Checks if a candidate is a render array.
-   *
-   * @param mixed $candidate
-   *   The candidate.
-   *
-   * @return bool
-   *   TRUE if it's a render array. FALSE otherwise.
-   *
-   * @todo Move this to the \Drupal\Core\Render\Element class.
-   * @see https://www.drupal.org/i/3352858
-   */
-  public static function isRenderArray($candidate): bool {
-    if (!is_array($candidate)) {
-      return FALSE;
-    }
-    if (empty($candidate)) {
-      return FALSE;
-    }
-    foreach ($candidate as $key => $value) {
-      if (!is_int($key) && $key !== '' && $key[0] === '#') {
-        continue;
-      }
-      if (!is_array($value)) {
-        return FALSE;
-      }
-      if (!static::isRenderArray($value)) {
-        return FALSE;
-      }
-    }
-    return TRUE;
-  }
-
-}
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/no-props/no-props.component.yml b/core/modules/sdc/tests/modules/sdc_test/components/no-props/no-props.component.yml
deleted file mode 100644
index 61c9bcd4de7266e1a29d81a768473f9101546356..0000000000000000000000000000000000000000
--- a/core/modules/sdc/tests/modules/sdc_test/components/no-props/no-props.component.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
-name: No props
-description: Component without properties
-props:
-  type: object
-  properties: {}
diff --git a/core/modules/sdc/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.component.yml b/core/modules/sdc/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.component.yml
deleted file mode 100644
index aea87d1e670f87eef5213a3590e361b8dc5961b1..0000000000000000000000000000000000000000
--- a/core/modules/sdc/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.component.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
-name: Card Without Schema
-status: experimental
diff --git a/core/modules/sdc/tests/src/Functional/GenericTest.php b/core/modules/sdc/tests/src/Functional/GenericTest.php
deleted file mode 100644
index c5740f9f0379d450fa86343d85c75ae10bbcf812..0000000000000000000000000000000000000000
--- a/core/modules/sdc/tests/src/Functional/GenericTest.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Tests\sdc\Functional;
-
-use Drupal\Tests\system\Functional\Module\GenericModuleTestBase;
-
-/**
- * Generic module test for sdc.
- *
- * @group sdc
- */
-class GenericTest extends GenericModuleTestBase {}
diff --git a/core/modules/sdc/tests/src/Functional/LibrariesBCLayerTest.php b/core/modules/sdc/tests/src/Functional/LibrariesBCLayerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e3417be3c89c71b429a0100c9e9c674bb2937058
--- /dev/null
+++ b/core/modules/sdc/tests/src/Functional/LibrariesBCLayerTest.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\sdc\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Tests the correct rendering of components.
+ *
+ * @group sdc
+ * @group legacy
+ *
+ * @internal
+*/
+final class LibrariesBCLayerTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['system', 'sdc', 'sdc_test'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'sdc_theme_test';
+
+  /**
+   * Tests libraryOverrides.
+   */
+  public function testLibraryBCLayer(): void {
+    $this->expectDeprecation('The module \'sdc\' is deprecated. See https://www.drupal.org/docs/core-modules-and-themes/deprecated-and-obsolete#s-understanding-deprecated-extensions');
+    $this->expectDeprecation('The sdc/sdc_theme_test--my-card asset library is deprecated in Drupal 10.3.0 and will be removed in Drupal 11.0.0. Use the core/components.[component-id] library instead. See https://www.drupal.org/node/3410260');
+    $build = [
+      '#type' => 'inline_template',
+      '#template' => "<h2>Foo</h2>{{ attach_library('sdc/sdc_theme_test--my-card') }}",
+    ];
+    \Drupal::state()->set('sdc_test_component', $build);
+    $output = $this->drupalGet('sdc-test-component');
+    // Ensure the CSS from the component is properly added to the page.
+    $this->assertStringContainsString('my-card.css', $output);
+  }
+
+}
diff --git a/core/modules/sdc/tests/src/Kernel/ComponentKernelTestBase.php b/core/modules/sdc/tests/src/Kernel/ComponentKernelTestBase.php
deleted file mode 100644
index 4e361d0ce009b959e299e7cdbdd542ccbc6af821..0000000000000000000000000000000000000000
--- a/core/modules/sdc/tests/src/Kernel/ComponentKernelTestBase.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Tests\sdc\Kernel;
-
-use Drupal\KernelTests\KernelTestBase;
-use Drupal\sdc\ComponentNegotiator;
-use Drupal\sdc\ComponentPluginManager;
-use Drupal\Tests\sdc\Traits\ComponentRendererTrait;
-
-/**
- * Defines a base class for component kernel tests.
- *
- * @internal
- */
-abstract class ComponentKernelTestBase extends KernelTestBase {
-
-  use ComponentRendererTrait;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected static $modules = [
-    'sdc',
-    'system',
-    'user',
-    'serialization',
-  ];
-
-  /**
-   * Themes to install.
-   *
-   * @var string[]
-   */
-  protected static $themes = [];
-
-  /**
-   * The component negotiator.
-   *
-   * @return \Drupal\sdc\ComponentNegotiator
-   */
-  protected ComponentNegotiator $negotiator;
-
-  /**
-   * The component plugin manager.
-   *
-   * @var \Drupal\sdc\ComponentPluginManager
-   */
-  protected ComponentPluginManager $manager;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp(): void {
-    parent::setUp();
-    if (empty(static::$themes)) {
-      throw new \Exception('You need to set the protected static $themes property on your test class, with the first item being the default theme.');
-    }
-    $this->container->get('theme_installer')->install(static::$themes);
-    $this->installConfig('system');
-
-    $system_theme_config = $this->container->get('config.factory')->getEditable('system.theme');
-    $system_theme_config
-      ->set('default', reset(static::$themes))
-      ->save();
-    $this->negotiator = new ComponentNegotiator(
-      \Drupal::service('theme.manager'),
-      \Drupal::service('extension.list.module'),
-    );
-    $this->manager = \Drupal::service('plugin.manager.sdc');
-  }
-
-}
diff --git a/core/modules/sdc/tests/src/Traits/ComponentRendererTrait.php b/core/modules/sdc/tests/src/Traits/ComponentRendererTrait.php
deleted file mode 100644
index 25eec0e340c0e68590de050d39cd3153f577915c..0000000000000000000000000000000000000000
--- a/core/modules/sdc/tests/src/Traits/ComponentRendererTrait.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Tests\sdc\Traits;
-
-use Drupal\Core\Render\BubbleableMetadata;
-use Drupal\Core\Render\RenderContext;
-use Symfony\Component\DomCrawler\Crawler;
-
-/**
- * Defines a trait for rendering components.
- *
- * @internal
- */
-trait ComponentRendererTrait {
-
-  /**
-   * Renders a component for testing sake.
-   *
-   * @param array $component
-   *   Component render array.
-   * @param \Drupal\Core\Render\BubbleableMetadata|null $metadata
-   *   Bubble metadata.
-   *
-   * @return \Symfony\Component\DomCrawler\Crawler
-   *   Crawler for introspecting the rendered component.
-   */
-  protected function renderComponentRenderArray(array $component, ?BubbleableMetadata $metadata = NULL): Crawler {
-    $component = [
-      '#type' => 'container',
-      '#attributes' => [
-        'id' => 'sdc-wrapper',
-      ],
-      'component' => $component,
-    ];
-    $metadata = $metadata ?: new BubbleableMetadata();
-    $context = new RenderContext();
-    $renderer = \Drupal::service('renderer');
-    $output = $renderer->executeInRenderContext($context, fn () => $renderer->render($component));
-    if (!$context->isEmpty()) {
-      $metadata->addCacheableDependency($context->pop());
-    }
-    return new Crawler((string) $output);
-  }
-
-}
diff --git a/core/modules/sdc/tests/src/Unit/UtilitiesTest.php b/core/modules/sdc/tests/src/Unit/UtilitiesTest.php
deleted file mode 100644
index ce10ba880655ee463ea08619f72635b5d28dc28e..0000000000000000000000000000000000000000
--- a/core/modules/sdc/tests/src/Unit/UtilitiesTest.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Tests\sdc\Unit;
-
-use Drupal\sdc\Utilities;
-use PHPUnit\Framework\TestCase;
-
-/**
- * Unit tests for the Utilities class.
- *
- * @coversDefaultClass \Drupal\sdc\Utilities
- *
- * @group sdc
- */
-final class UtilitiesTest extends TestCase {
-
-  /**
-   * @covers ::isRenderArray
-   * @dataProvider dataProviderIsRenderArray
-   */
-  public function testIsRenderArray($build, $expected) {
-    $this->assertSame(
-      $expected,
-      Utilities::isRenderArray($build)
-    );
-  }
-
-  public static function dataProviderIsRenderArray() {
-    return [
-      'valid markup render array' => [['#markup' => 'hello world'], TRUE],
-      'invalid "foo" string' => [['foo', '#markup' => 'hello world'], FALSE],
-      'null is not an array' => [NULL, FALSE],
-      'an empty array is not a render array' => [[], FALSE],
-      'funny enough a key with # is valid' => [['#' => TRUE], TRUE],
-      'nested arrays can be valid too' => [['one' => [2 => ['#three' => 'charm!']]], TRUE],
-    ];
-  }
-
-}
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.component.yml b/core/modules/sdc/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.component.yml
deleted file mode 100644
index aea87d1e670f87eef5213a3590e361b8dc5961b1..0000000000000000000000000000000000000000
--- a/core/modules/sdc/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.component.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
-name: Card Without Schema
-status: experimental
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.component.yml b/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.component.yml
deleted file mode 100644
index aea87d1e670f87eef5213a3590e361b8dc5961b1..0000000000000000000000000000000000000000
--- a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.component.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
-name: Card Without Schema
-status: experimental
diff --git a/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml b/core/modules/system/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml
similarity index 70%
rename from core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml
rename to core/modules/system/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml
index ba20067f05346b92727c656cc4e4816d50f7bda7..3038f56af06a654cae3b8deae3aa9bcb62a357ca 100644
--- a/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml
+++ b/core/modules/system/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.info.yml
@@ -1,5 +1,3 @@
 name: 'Add another node visitor'
 type: module
-dependencies:
-  - sdc:sdc
 package: Testing
diff --git a/core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.services.yml b/core/modules/system/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.services.yml
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.services.yml
rename to core/modules/system/tests/modules/sdc_other_node_visitor/sdc_other_node_visitor.services.yml
diff --git a/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Extension/TestProfilerExtension.php b/core/modules/system/tests/modules/sdc_other_node_visitor/src/Twig/Extension/TestProfilerExtension.php
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Extension/TestProfilerExtension.php
rename to core/modules/system/tests/modules/sdc_other_node_visitor/src/Twig/Extension/TestProfilerExtension.php
diff --git a/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/NodeVisitor/TestNodeVisitor.php b/core/modules/system/tests/modules/sdc_other_node_visitor/src/Twig/NodeVisitor/TestNodeVisitor.php
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/NodeVisitor/TestNodeVisitor.php
rename to core/modules/system/tests/modules/sdc_other_node_visitor/src/Twig/NodeVisitor/TestNodeVisitor.php
diff --git a/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/EnterProfileNode.php b/core/modules/system/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/EnterProfileNode.php
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/EnterProfileNode.php
rename to core/modules/system/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/EnterProfileNode.php
diff --git a/core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/LeaveProfileNode.php b/core/modules/system/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/LeaveProfileNode.php
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/LeaveProfileNode.php
rename to core/modules/system/tests/modules/sdc_other_node_visitor/src/Twig/Profiler/LeaveProfileNode.php
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/array-to-object/array-to-object.component.yml b/core/modules/system/tests/modules/sdc_test/components/array-to-object/array-to-object.component.yml
similarity index 52%
rename from core/modules/sdc/tests/modules/sdc_test/components/array-to-object/array-to-object.component.yml
rename to core/modules/system/tests/modules/sdc_test/components/array-to-object/array-to-object.component.yml
index 1d70540cde52cec48d5eb4360f50c510964068cf..fafe2ae3f4328d75e4b234f3e7132c678f556aa5 100644
--- a/core/modules/sdc/tests/modules/sdc_test/components/array-to-object/array-to-object.component.yml
+++ b/core/modules/system/tests/modules/sdc_test/components/array-to-object/array-to-object.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Array to Object
 props:
   type: object
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/array-to-object/array-to-object.twig b/core/modules/system/tests/modules/sdc_test/components/array-to-object/array-to-object.twig
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/array-to-object/array-to-object.twig
rename to core/modules/system/tests/modules/sdc_test/components/array-to-object/array-to-object.twig
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-banner/my-banner.component.yml b/core/modules/system/tests/modules/sdc_test/components/my-banner/my-banner.component.yml
similarity index 88%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-banner/my-banner.component.yml
rename to core/modules/system/tests/modules/sdc_test/components/my-banner/my-banner.component.yml
index fe38719d72c8d1da64248f720e982cfe5d2393c9..195903e9ee74a493055b61e81319a4aa45fb1f20 100644
--- a/core/modules/sdc/tests/modules/sdc_test/components/my-banner/my-banner.component.yml
+++ b/core/modules/system/tests/modules/sdc_test/components/my-banner/my-banner.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Banner
 description: Banner with title and a CTA link
 libraryOverrides:
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-banner/my-banner.css b/core/modules/system/tests/modules/sdc_test/components/my-banner/my-banner.css
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-banner/my-banner.css
rename to core/modules/system/tests/modules/sdc_test/components/my-banner/my-banner.css
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-banner/my-banner.twig b/core/modules/system/tests/modules/sdc_test/components/my-banner/my-banner.twig
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-banner/my-banner.twig
rename to core/modules/system/tests/modules/sdc_test/components/my-banner/my-banner.twig
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.component.yml b/core/modules/system/tests/modules/sdc_test/components/my-button/my-button.component.yml
similarity index 82%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.component.yml
rename to core/modules/system/tests/modules/sdc_test/components/my-button/my-button.component.yml
index c68b6b0025f3649cacef91796f67babc017e6d83..65b3c472096be1395e3c0fa595b3ab3814ee4862 100644
--- a/core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.component.yml
+++ b/core/modules/system/tests/modules/sdc_test/components/my-button/my-button.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Button
 description: JavaScript enhanced button that tracks the number of times a user clicked it.
 libraryOverrides:
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.css b/core/modules/system/tests/modules/sdc_test/components/my-button/my-button.css
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.css
rename to core/modules/system/tests/modules/sdc_test/components/my-button/my-button.css
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.js b/core/modules/system/tests/modules/sdc_test/components/my-button/my-button.js
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.js
rename to core/modules/system/tests/modules/sdc_test/components/my-button/my-button.js
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.twig b/core/modules/system/tests/modules/sdc_test/components/my-button/my-button.twig
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-button/my-button.twig
rename to core/modules/system/tests/modules/sdc_test/components/my-button/my-button.twig
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.component.yml b/core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.component.yml
similarity index 82%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.component.yml
rename to core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.component.yml
index c9dc85d51fe062633c8a0a52035bd13e90effeb3..015b3e16319b27aff64b010ad0014ff3e757fa39 100644
--- a/core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.component.yml
+++ b/core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Call to Action
 description: Call to action link.
 props:
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.css b/core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.css
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.css
rename to core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.css
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.js b/core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.js
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.js
rename to core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.js
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.twig b/core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.twig
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/my-cta/my-cta.twig
rename to core/modules/system/tests/modules/sdc_test/components/my-cta/my-cta.twig
diff --git a/core/modules/system/tests/modules/sdc_test/components/no-props/no-props.component.yml b/core/modules/system/tests/modules/sdc_test/components/no-props/no-props.component.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7b33dc1447f0d56d7caf5ec09008a4e15817bdb2
--- /dev/null
+++ b/core/modules/system/tests/modules/sdc_test/components/no-props/no-props.component.yml
@@ -0,0 +1,6 @@
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
+name: No props
+description: Component without properties
+props:
+  type: object
+  properties: {}
diff --git a/core/modules/sdc/tests/modules/sdc_test/components/no-props/no-props.twig b/core/modules/system/tests/modules/sdc_test/components/no-props/no-props.twig
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/components/no-props/no-props.twig
rename to core/modules/system/tests/modules/sdc_test/components/no-props/no-props.twig
diff --git a/core/modules/sdc/tests/modules/sdc_test/sdc_test.info.yml b/core/modules/system/tests/modules/sdc_test/sdc_test.info.yml
similarity index 67%
rename from core/modules/sdc/tests/modules/sdc_test/sdc_test.info.yml
rename to core/modules/system/tests/modules/sdc_test/sdc_test.info.yml
index 5c282867d4596dc88696cf9fa89e877cd2da035d..e03e7bd69c2246dd19b4498e9ff901b1d479e4ce 100644
--- a/core/modules/sdc/tests/modules/sdc_test/sdc_test.info.yml
+++ b/core/modules/system/tests/modules/sdc_test/sdc_test.info.yml
@@ -1,5 +1,3 @@
 name: 'Components Test'
 type: module
-dependencies:
-  - sdc:sdc
 package: Testing
diff --git a/core/modules/sdc/tests/modules/sdc_test/sdc_test.routing.yml b/core/modules/system/tests/modules/sdc_test/sdc_test.routing.yml
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/sdc_test.routing.yml
rename to core/modules/system/tests/modules/sdc_test/sdc_test.routing.yml
diff --git a/core/modules/sdc/tests/modules/sdc_test/src/Controller/ServerEndpointController.php b/core/modules/system/tests/modules/sdc_test/src/Controller/ServerEndpointController.php
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test/src/Controller/ServerEndpointController.php
rename to core/modules/system/tests/modules/sdc_test/src/Controller/ServerEndpointController.php
diff --git a/core/modules/system/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.component.yml b/core/modules/system/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.component.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2859616a3f4071de4b569ced9bb9797d81933367
--- /dev/null
+++ b/core/modules/system/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.component.yml
@@ -0,0 +1,3 @@
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
+name: Card Without Schema
+status: experimental
diff --git a/core/modules/sdc/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.twig b/core/modules/system/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.twig
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.twig
rename to core/modules/system/tests/modules/sdc_test_invalid/components/my-card-no-schema/my-card-no-schema.twig
diff --git a/core/modules/sdc/tests/modules/sdc_test_invalid/sdc_test_invalid.info.yml b/core/modules/system/tests/modules/sdc_test_invalid/sdc_test_invalid.info.yml
similarity index 67%
rename from core/modules/sdc/tests/modules/sdc_test_invalid/sdc_test_invalid.info.yml
rename to core/modules/system/tests/modules/sdc_test_invalid/sdc_test_invalid.info.yml
index 5c282867d4596dc88696cf9fa89e877cd2da035d..e03e7bd69c2246dd19b4498e9ff901b1d479e4ce 100644
--- a/core/modules/sdc/tests/modules/sdc_test_invalid/sdc_test_invalid.info.yml
+++ b/core/modules/system/tests/modules/sdc_test_invalid/sdc_test_invalid.info.yml
@@ -1,5 +1,3 @@
 name: 'Components Test'
 type: module
-dependencies:
-  - sdc:sdc
 package: Testing
diff --git a/core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.component.yml b/core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.component.yml
similarity index 82%
rename from core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.component.yml
rename to core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.component.yml
index 2a97ee5c1b50c84cf3f1d2ce15193f5c2383e7d7..b87f1180111ee70645bd2b3dbd1c437c53c9758c 100644
--- a/core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.component.yml
+++ b/core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Button
 replaces: 'sdc_test:my-button'
 description: JavaScript enhanced button that tracks the number of times a user clicked it.
diff --git a/core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.css b/core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.css
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.css
rename to core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.css
diff --git a/core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.js b/core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.js
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.js
rename to core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.js
diff --git a/core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.twig b/core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.twig
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test_replacements/components/my-button/my-button.twig
rename to core/modules/system/tests/modules/sdc_test_replacements/components/my-button/my-button.twig
diff --git a/core/modules/sdc/tests/modules/sdc_test_replacements/sdc_test_replacements.info.yml b/core/modules/system/tests/modules/sdc_test_replacements/sdc_test_replacements.info.yml
similarity index 72%
rename from core/modules/sdc/tests/modules/sdc_test_replacements/sdc_test_replacements.info.yml
rename to core/modules/system/tests/modules/sdc_test_replacements/sdc_test_replacements.info.yml
index 4ac1285fef80c5378a6fdf7da13a6c439eebd282..f721cc3e6f60eed1323f9575bbc8f254957075ce 100644
--- a/core/modules/sdc/tests/modules/sdc_test_replacements/sdc_test_replacements.info.yml
+++ b/core/modules/system/tests/modules/sdc_test_replacements/sdc_test_replacements.info.yml
@@ -1,5 +1,3 @@
 name: 'Components Test Replacements'
 type: module
-dependencies:
-  - sdc:sdc
 package: Testing
diff --git a/core/modules/sdc/tests/modules/sdc_test_replacements_invalid/components/foo/foo.component.yml b/core/modules/system/tests/modules/sdc_test_replacements_invalid/components/foo/foo.component.yml
similarity index 60%
rename from core/modules/sdc/tests/modules/sdc_test_replacements_invalid/components/foo/foo.component.yml
rename to core/modules/system/tests/modules/sdc_test_replacements_invalid/components/foo/foo.component.yml
index 1f5613efa0bbca3f11d926dbf265905829162157..efb13416dc907164335daa18f33fe251c4c6e840 100644
--- a/core/modules/sdc/tests/modules/sdc_test_replacements_invalid/components/foo/foo.component.yml
+++ b/core/modules/system/tests/modules/sdc_test_replacements_invalid/components/foo/foo.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Foo
 status: experimental
 replaces: sdc_theme_test:foo
diff --git a/core/modules/sdc/tests/modules/sdc_test_replacements_invalid/components/foo/foo.twig b/core/modules/system/tests/modules/sdc_test_replacements_invalid/components/foo/foo.twig
similarity index 100%
rename from core/modules/sdc/tests/modules/sdc_test_replacements_invalid/components/foo/foo.twig
rename to core/modules/system/tests/modules/sdc_test_replacements_invalid/components/foo/foo.twig
diff --git a/core/modules/sdc/tests/modules/sdc_test_replacements_invalid/sdc_test_replacements_invalid.info.yml b/core/modules/system/tests/modules/sdc_test_replacements_invalid/sdc_test_replacements_invalid.info.yml
similarity index 74%
rename from core/modules/sdc/tests/modules/sdc_test_replacements_invalid/sdc_test_replacements_invalid.info.yml
rename to core/modules/system/tests/modules/sdc_test_replacements_invalid/sdc_test_replacements_invalid.info.yml
index e45e3b8c162d7669d23e0e672b1ed3fdad304c84..b122930ff29b863a64fe19cb8dbbfdd1decff5c9 100644
--- a/core/modules/sdc/tests/modules/sdc_test_replacements_invalid/sdc_test_replacements_invalid.info.yml
+++ b/core/modules/system/tests/modules/sdc_test_replacements_invalid/sdc_test_replacements_invalid.info.yml
@@ -1,5 +1,3 @@
 name: 'Components Test Replacements (invalid)'
 type: module
-dependencies:
-  - sdc:sdc
 package: Testing
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/bar/bar.component.yml b/core/modules/system/tests/themes/sdc_theme_test/components/bar/bar.component.yml
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/bar/bar.component.yml
rename to core/modules/system/tests/themes/sdc_theme_test/components/bar/bar.component.yml
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/bar/bar.twig b/core/modules/system/tests/themes/sdc_theme_test/components/bar/bar.twig
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/bar/bar.twig
rename to core/modules/system/tests/themes/sdc_theme_test/components/bar/bar.twig
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/another-stylesheet.css b/core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/another-stylesheet.css
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/another-stylesheet.css
rename to core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/another-stylesheet.css
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.component.yml b/core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.component.yml
similarity index 76%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.component.yml
rename to core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.component.yml
index 1c2eebd2e3b7a5698fc1c4806921bf753216a2aa..9433f4f3700d9139cc13d11d767a96abdf18c814 100644
--- a/core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.component.yml
+++ b/core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Lib Overrides
 status: stable
 libraryOverrides:
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.css b/core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.css
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.css
rename to core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.css
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.js b/core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.js
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.js
rename to core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.js
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.twig b/core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.twig
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.twig
rename to core/modules/system/tests/themes/sdc_theme_test/components/lib-overrides/lib-overrides.twig
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.component.yml b/core/modules/system/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.component.yml
similarity index 55%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.component.yml
rename to core/modules/system/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.component.yml
index 1fc8b701b93c8b6412ba6132c32a937cf61e6959..37e85fdfa8952576434402867f39cb83b36c1f34 100644
--- a/core/modules/sdc/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.component.yml
+++ b/core/modules/system/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Foo
 status: experimental
 libraryOverrides:
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.twig b/core/modules/system/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.twig
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.twig
rename to core/modules/system/tests/themes/sdc_theme_test/components/mismatching-folder-name/foo.twig
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/my-card/my-card.component.yml b/core/modules/system/tests/themes/sdc_theme_test/components/my-card/my-card.component.yml
similarity index 77%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/my-card/my-card.component.yml
rename to core/modules/system/tests/themes/sdc_theme_test/components/my-card/my-card.component.yml
index 64b6ea45be8b8c24f327468f03c7dfd24813d476..67d3a01657a88ff5a9b8706dbacd6458b87ff1a3 100644
--- a/core/modules/sdc/tests/themes/sdc_theme_test/components/my-card/my-card.component.yml
+++ b/core/modules/system/tests/themes/sdc_theme_test/components/my-card/my-card.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Card
 status: experimental
 props:
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/my-card/my-card.css b/core/modules/system/tests/themes/sdc_theme_test/components/my-card/my-card.css
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/my-card/my-card.css
rename to core/modules/system/tests/themes/sdc_theme_test/components/my-card/my-card.css
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/components/my-card/my-card.twig b/core/modules/system/tests/themes/sdc_theme_test/components/my-card/my-card.twig
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/components/my-card/my-card.twig
rename to core/modules/system/tests/themes/sdc_theme_test/components/my-card/my-card.twig
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test/sdc_theme_test.info.yml b/core/modules/system/tests/themes/sdc_theme_test/sdc_theme_test.info.yml
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test/sdc_theme_test.info.yml
rename to core/modules/system/tests/themes/sdc_theme_test/sdc_theme_test.info.yml
diff --git a/core/modules/system/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.component.yml b/core/modules/system/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.component.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2859616a3f4071de4b569ced9bb9797d81933367
--- /dev/null
+++ b/core/modules/system/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.component.yml
@@ -0,0 +1,3 @@
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
+name: Card Without Schema
+status: experimental
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.twig b/core/modules/system/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.twig
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.twig
rename to core/modules/system/tests/themes/sdc_theme_test_base/components/my-card-no-schema/my-card-no-schema.twig
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_base/sdc_theme_test_base.info.yml b/core/modules/system/tests/themes/sdc_theme_test_base/sdc_theme_test_base.info.yml
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test_base/sdc_theme_test_base.info.yml
rename to core/modules/system/tests/themes/sdc_theme_test_base/sdc_theme_test_base.info.yml
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.component.yml b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.component.yml
similarity index 78%
rename from core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.component.yml
rename to core/modules/system/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.component.yml
index 4b2a101df6daed5e984a6e87b85ee6960606dbef..d586a21349af9dbf4c795a488d13fe74b033e682 100644
--- a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.component.yml
+++ b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.component.yml
@@ -1,4 +1,4 @@
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 name: Card
 status: experimental
 replaces: 'sdc_theme_test:my-card'
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.css b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.css
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.css
rename to core/modules/system/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.css
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.twig b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.twig
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.twig
rename to core/modules/system/tests/themes/sdc_theme_test_enforce_schema/components/my-card/my-card.twig
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/sdc_theme_test_enforce_schema.info.yml b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema/sdc_theme_test_enforce_schema.info.yml
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema/sdc_theme_test_enforce_schema.info.yml
rename to core/modules/system/tests/themes/sdc_theme_test_enforce_schema/sdc_theme_test_enforce_schema.info.yml
diff --git a/core/modules/system/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.component.yml b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.component.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2859616a3f4071de4b569ced9bb9797d81933367
--- /dev/null
+++ b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.component.yml
@@ -0,0 +1,3 @@
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
+name: Card Without Schema
+status: experimental
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.twig b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.twig
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.twig
rename to core/modules/system/tests/themes/sdc_theme_test_enforce_schema_invalid/components/my-card-no-schema/my-card-no-schema.twig
diff --git a/core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema_invalid/sdc_theme_test_enforce_schema_invalid.info.yml b/core/modules/system/tests/themes/sdc_theme_test_enforce_schema_invalid/sdc_theme_test_enforce_schema_invalid.info.yml
similarity index 100%
rename from core/modules/sdc/tests/themes/sdc_theme_test_enforce_schema_invalid/sdc_theme_test_enforce_schema_invalid.info.yml
rename to core/modules/system/tests/themes/sdc_theme_test_enforce_schema_invalid/sdc_theme_test_enforce_schema_invalid.info.yml
diff --git a/core/profiles/demo_umami/demo_umami.info.yml b/core/profiles/demo_umami/demo_umami.info.yml
index 731ebf1b85b99de38fd59c9dbe5855e4b296bb70..407380d564459ee3a5634e5349ca173053f1b235 100644
--- a/core/profiles/demo_umami/demo_umami.info.yml
+++ b/core/profiles/demo_umami/demo_umami.info.yml
@@ -29,7 +29,6 @@ install:
   - dynamic_page_cache
   - taxonomy
   - dblog
-  - sdc
   - search
   - shortcut
   - toolbar
diff --git a/core/profiles/demo_umami/themes/umami/components/badge/badge.component.yml b/core/profiles/demo_umami/themes/umami/components/badge/badge.component.yml
index 44fed982416e8e019be1522850004d836578f477..1d68092cc07fe81c78afa1a4fc08efe6fa6dec58 100644
--- a/core/profiles/demo_umami/themes/umami/components/badge/badge.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/badge/badge.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Umami Badge
diff --git a/core/profiles/demo_umami/themes/umami/components/banner/banner.component.yml b/core/profiles/demo_umami/themes/umami/components/banner/banner.component.yml
index 698efa5ccb7ca7942b37098c361dceed34107568..3e2289108efe67eabb3a6734c14e42deb03b6fba 100644
--- a/core/profiles/demo_umami/themes/umami/components/banner/banner.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/banner/banner.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Banner
diff --git a/core/profiles/demo_umami/themes/umami/components/branding/branding.component.yml b/core/profiles/demo_umami/themes/umami/components/branding/branding.component.yml
index 1f2203d349737b7c59ce6031f1f0d4bf7b22f0c6..8ec4f4e752a8249b1fedec0618097a4803fdf7af 100644
--- a/core/profiles/demo_umami/themes/umami/components/branding/branding.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/branding/branding.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Branding
diff --git a/core/profiles/demo_umami/themes/umami/components/card/card.component.yml b/core/profiles/demo_umami/themes/umami/components/card/card.component.yml
index f9b2d36c90c11dde1c1bb632082c9ef1318221df..58dbae5400827c9e35a9537442f241fac227ecf0 100644
--- a/core/profiles/demo_umami/themes/umami/components/card/card.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/card/card.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Card
diff --git a/core/profiles/demo_umami/themes/umami/components/disclaimer/disclaimer.component.yml b/core/profiles/demo_umami/themes/umami/components/disclaimer/disclaimer.component.yml
index 95fcd2f2017eb84aa6c6510e8fdca6b8fcf8f1f3..4d676d3031030a85ff914b176844a5b6e5ef055d 100644
--- a/core/profiles/demo_umami/themes/umami/components/disclaimer/disclaimer.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/disclaimer/disclaimer.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Disclaimer
diff --git a/core/profiles/demo_umami/themes/umami/components/footer-block/footer-block.component.yml b/core/profiles/demo_umami/themes/umami/components/footer-block/footer-block.component.yml
index 371151941e7e42257e4e96a9d5e005722665c774..3bfef5b9f4b3ee371375853974e356e6225750f0 100644
--- a/core/profiles/demo_umami/themes/umami/components/footer-block/footer-block.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/footer-block/footer-block.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Footer Block
diff --git a/core/profiles/demo_umami/themes/umami/components/header/header.component.yml b/core/profiles/demo_umami/themes/umami/components/header/header.component.yml
index 7fce771f338e1a0593baab9360fa7c505a597785..32c1b357b0475d0b46781641a990e44e3f50caed 100644
--- a/core/profiles/demo_umami/themes/umami/components/header/header.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/header/header.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Umami header
diff --git a/core/profiles/demo_umami/themes/umami/components/read-more/read-more.component.yml b/core/profiles/demo_umami/themes/umami/components/read-more/read-more.component.yml
index e9b016ada3ddf9a5a6d8a96e8042513e1b5daac2..3b004915e4e59569998b4257c175bf21593ed05c 100644
--- a/core/profiles/demo_umami/themes/umami/components/read-more/read-more.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/read-more/read-more.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Read More
diff --git a/core/profiles/demo_umami/themes/umami/components/title/title.component.yml b/core/profiles/demo_umami/themes/umami/components/title/title.component.yml
index fd8d9c91208452007b3b48a0c77328c61e629942..df26ee3abf883335f5e73c43cd4b9ba310248bae 100644
--- a/core/profiles/demo_umami/themes/umami/components/title/title.component.yml
+++ b/core/profiles/demo_umami/themes/umami/components/title/title.component.yml
@@ -1,5 +1,5 @@
 # This is so your IDE knows about the syntax for fixes and autocomplete.
-$schema: https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json
+$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json
 
 # The human readable name.
 name: Title
diff --git a/core/profiles/demo_umami/themes/umami/umami.info.yml b/core/profiles/demo_umami/themes/umami/umami.info.yml
index 451d07d3a38260ec905b07f1382e6ead257f2d97..441ebdaf763cc85b7f33f700670bac476d932ad7 100644
--- a/core/profiles/demo_umami/themes/umami/umami.info.yml
+++ b/core/profiles/demo_umami/themes/umami/umami.info.yml
@@ -7,8 +7,6 @@ libraries:
   - umami/classy.base
   - core/normalize
   - umami/global
-dependencies:
-  - drupal:sdc
 
 libraries-override:
   layout_builder/twocol_section:
diff --git a/core/modules/sdc/tests/src/FunctionalJavascript/ComponentRenderTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Components/ComponentRenderTest.php
similarity index 90%
rename from core/modules/sdc/tests/src/FunctionalJavascript/ComponentRenderTest.php
rename to core/tests/Drupal/FunctionalJavascriptTests/Components/ComponentRenderTest.php
index 4d113806caf43f6dbc5947b0adbb2bb9fc8e8689..c479411006af23a7e7d9cd659a91f859a52c22fa 100644
--- a/core/modules/sdc/tests/src/FunctionalJavascript/ComponentRenderTest.php
+++ b/core/tests/Drupal/FunctionalJavascriptTests/Components/ComponentRenderTest.php
@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace Drupal\Tests\sdc\FunctionalJavascript;
+namespace Drupal\FunctionalJavascriptTests\Components;
 
 use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
 
@@ -10,15 +10,13 @@
  * Tests the correct rendering of components.
  *
  * @group sdc
- *
- * @internal
  */
-final class ComponentRenderTest extends WebDriverTestBase {
+class ComponentRenderTest extends WebDriverTestBase {
 
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['sdc', 'sdc_test'];
+  protected static $modules = ['system', 'sdc_test'];
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/sdc/tests/src/Functional/ComponentRenderTest.php b/core/tests/Drupal/FunctionalTests/Components/ComponentRenderTest.php
similarity index 90%
rename from core/modules/sdc/tests/src/Functional/ComponentRenderTest.php
rename to core/tests/Drupal/FunctionalTests/Components/ComponentRenderTest.php
index 2c80bfbacf211ed5a595ad8163696c26f71839d8..963661a0cc8eebfb02ff1b4e48b5920fe14d367f 100644
--- a/core/modules/sdc/tests/src/Functional/ComponentRenderTest.php
+++ b/core/tests/Drupal/FunctionalTests/Components/ComponentRenderTest.php
@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace Drupal\Tests\sdc\Functional;
+namespace Drupal\FunctionalTests\Components;
 
 use Drupal\Tests\BrowserTestBase;
 
@@ -10,15 +10,13 @@
  * Tests the correct rendering of components.
  *
  * @group sdc
- *
- * @internal
  */
-final class ComponentRenderTest extends BrowserTestBase {
+class ComponentRenderTest extends BrowserTestBase {
 
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['sdc', 'sdc_test'];
+  protected static $modules = ['system', 'sdc_test'];
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/sdc/tests/src/Kernel/ComponentInvalidReplacementTest.php b/core/tests/Drupal/KernelTests/Components/ComponentInvalidReplacementTest.php
similarity index 67%
rename from core/modules/sdc/tests/src/Kernel/ComponentInvalidReplacementTest.php
rename to core/tests/Drupal/KernelTests/Components/ComponentInvalidReplacementTest.php
index 53e07e1ea37f8ac42ba127c442820a16066a255e..9d510646f7e810d9281058bdfc9b8a0ef430b588 100644
--- a/core/modules/sdc/tests/src/Kernel/ComponentInvalidReplacementTest.php
+++ b/core/tests/Drupal/KernelTests/Components/ComponentInvalidReplacementTest.php
@@ -1,17 +1,16 @@
 <?php
 
-namespace Drupal\Tests\sdc\Kernel;
+namespace Drupal\KernelTests\Components;
 
-use Drupal\sdc\Exception\IncompatibleComponentSchema;
+use Drupal\Core\Render\Component\Exception\IncompatibleComponentSchema;
+use Drupal\Tests\Core\Theme\Component\ComponentKernelTestBase;
 
 /**
  * Tests invalid render options for components.
  *
  * @group sdc
- *
- * @internal
  */
-final class ComponentInvalidReplacementTest extends ComponentKernelTestBase {
+class ComponentInvalidReplacementTest extends ComponentKernelTestBase {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/sdc/tests/src/Kernel/ComponentNodeVisitorTest.php b/core/tests/Drupal/KernelTests/Components/ComponentNodeVisitorTest.php
similarity index 67%
rename from core/modules/sdc/tests/src/Kernel/ComponentNodeVisitorTest.php
rename to core/tests/Drupal/KernelTests/Components/ComponentNodeVisitorTest.php
index ef541d0aa532c7dbd0ec910e163a3d17a8331be6..2ff8743a2af6209b225551250cb886896776b2a6 100644
--- a/core/modules/sdc/tests/src/Kernel/ComponentNodeVisitorTest.php
+++ b/core/tests/Drupal/KernelTests/Components/ComponentNodeVisitorTest.php
@@ -1,21 +1,21 @@
 <?php
 
-namespace Drupal\Tests\sdc\Kernel;
+namespace Drupal\KernelTests\Components;
+
+use Drupal\Tests\Core\Theme\Component\ComponentKernelTestBase;
 
 /**
  * Tests the node visitor.
  *
- * @coversDefaultClass \Drupal\sdc\Twig\ComponentNodeVisitor
+ * @coversDefaultClass \Drupal\Core\Template\ComponentNodeVisitor
  * @group sdc
- *
- * @internal
  */
-final class ComponentNodeVisitorTest extends ComponentKernelTestBase {
+class ComponentNodeVisitorTest extends ComponentKernelTestBase {
 
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['sdc', 'sdc_other_node_visitor'];
+  protected static $modules = ['system', 'sdc_other_node_visitor'];
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/sdc/tests/src/Kernel/ComponentRenderInvalidTest.php b/core/tests/Drupal/KernelTests/Components/ComponentRenderInvalidTest.php
similarity index 87%
rename from core/modules/sdc/tests/src/Kernel/ComponentRenderInvalidTest.php
rename to core/tests/Drupal/KernelTests/Components/ComponentRenderInvalidTest.php
index 6c6c744f241034d32e0fbddbe39ba216ce6d5558..fbb5b82569d7a43d39c10651454521409979b5c1 100644
--- a/core/modules/sdc/tests/src/Kernel/ComponentRenderInvalidTest.php
+++ b/core/tests/Drupal/KernelTests/Components/ComponentRenderInvalidTest.php
@@ -1,17 +1,16 @@
 <?php
 
-namespace Drupal\Tests\sdc\Kernel;
+namespace Drupal\KernelTests\Components;
 
-use Drupal\sdc\Exception\InvalidComponentException;
+use Drupal\Core\Render\Component\Exception\InvalidComponentException;
+use Drupal\Tests\Core\Theme\Component\ComponentKernelTestBase;
 
 /**
  * Tests invalid render options for components.
  *
  * @group sdc
- *
- * @internal
  */
-final class ComponentRenderInvalidTest extends ComponentKernelTestBase {
+class ComponentRenderInvalidTest extends ComponentKernelTestBase {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/sdc/tests/src/Kernel/ComponentRenderTest.php b/core/tests/Drupal/KernelTests/Components/ComponentRenderTest.php
similarity index 94%
rename from core/modules/sdc/tests/src/Kernel/ComponentRenderTest.php
rename to core/tests/Drupal/KernelTests/Components/ComponentRenderTest.php
index f30ad92caadac7e9ca63b71537f47d70b9f795eb..cc88cdb3e347cf095746aeff3e00e98af826c90d 100644
--- a/core/modules/sdc/tests/src/Kernel/ComponentRenderTest.php
+++ b/core/tests/Drupal/KernelTests/Components/ComponentRenderTest.php
@@ -1,28 +1,27 @@
 <?php
 
-namespace Drupal\Tests\sdc\Kernel;
+namespace Drupal\KernelTests\Components;
 
 use Drupal\Core\Render\BubbleableMetadata;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Template\Attribute;
-use Drupal\sdc\ComponentPluginManager;
-use Drupal\sdc\Exception\InvalidComponentDataException;
+use Drupal\Core\Theme\ComponentPluginManager;
+use Drupal\Core\Render\Component\Exception\InvalidComponentDataException;
+use Drupal\Tests\Core\Theme\Component\ComponentKernelTestBase;
 
 /**
  * Tests the correct rendering of components.
  *
  * @group sdc
- *
- * @internal
  */
-final class ComponentRenderTest extends ComponentKernelTestBase {
+class ComponentRenderTest extends ComponentKernelTestBase {
 
   use StringTranslationTrait;
 
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['sdc', 'sdc_test'];
+  protected static $modules = ['system', 'sdc_test'];
 
   /**
    * {@inheritdoc}
@@ -124,7 +123,7 @@ protected function checkEmbedWithNested(): void {
     ];
     $metadata = new BubbleableMetadata();
     $this->renderComponentRenderArray($build, $metadata);
-    $this->assertEquals(['sdc/sdc_test--my-cta', 'sdc/sdc_test--my-banner'], $metadata->getAttachments()['library']);
+    $this->assertEquals(['core/components.sdc_test--my-cta', 'core/components.sdc_test--my-banner'], $metadata->getAttachments()['library']);
   }
 
   /**
@@ -137,7 +136,7 @@ protected function checkLibraryOverrides(): void {
     ];
     $metadata = new BubbleableMetadata();
     $this->renderComponentRenderArray($build, $metadata);
-    $this->assertEquals(['sdc/sdc_theme_test--lib-overrides'], $metadata->getAttachments()['library']);
+    $this->assertEquals(['core/components.sdc_theme_test--lib-overrides'], $metadata->getAttachments()['library']);
   }
 
   /**
@@ -362,7 +361,7 @@ public function testPluginDefinition(): void {
     assert($plugin_manager instanceof ComponentPluginManager);
     $definition = $plugin_manager->getDefinition('sdc_test:my-banner');
     $this->assertSame('my-banner', $definition['machineName']);
-    $this->assertStringEndsWith('sdc/tests/modules/sdc_test/components/my-banner', $definition['path']);
+    $this->assertStringEndsWith('system/tests/modules/sdc_test/components/my-banner', $definition['path']);
     $this->assertEquals(['core/drupal'], $definition['library']['dependencies']);
     $this->assertNotEmpty($definition['library']['css']['component']);
     $this->assertSame('my-banner.twig', $definition['template']);
diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
index 3724faaf3f0b35567fa270d00f393ba4624ff94e..1e92c3da121b2525f7e6a631a6018046dd04ce47 100644
--- a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Extension\ExtensionPathResolver;
 use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
 use Drupal\Core\Theme\ActiveTheme;
+use Drupal\Core\Theme\ComponentPluginManager;
 use Drupal\Core\Theme\ThemeManagerInterface;
 use Drupal\Tests\UnitTestCase;
 
@@ -85,6 +86,13 @@ class LibraryDiscoveryParserTest extends UnitTestCase {
    */
   protected $extensionPathResolver;
 
+  /**
+   * The mocked extension path resolver.
+   *
+   * @var \Drupal\Core\Theme\ComponentPluginManager|\PHPUnit\Framework\MockObject\MockObject
+   */
+  protected $componentPluginManager;
+
   /**
    * {@inheritdoc}
    */
@@ -105,7 +113,8 @@ protected function setUp(): void {
     $this->streamWrapperManager = $this->createMock(StreamWrapperManagerInterface::class);
     $this->librariesDirectoryFileFinder = $this->createMock(LibrariesDirectoryFileFinder::class);
     $this->extensionPathResolver = $this->createMock(ExtensionPathResolver::class);
-    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->streamWrapperManager, $this->librariesDirectoryFileFinder, $this->extensionPathResolver);
+    $this->componentPluginManager = $this->createMock(ComponentPluginManager::class);
+    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->streamWrapperManager, $this->librariesDirectoryFileFinder, $this->extensionPathResolver, $this->componentPluginManager);
   }
 
   /**
@@ -121,7 +130,7 @@ public function testBuildByExtensionSimple() {
     FileCacheFactory::setConfiguration([
       'library_parser' => [],
     ]);
-    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->streamWrapperManager, $this->librariesDirectoryFileFinder, $this->extensionPathResolver);
+    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->streamWrapperManager, $this->librariesDirectoryFileFinder, $this->extensionPathResolver, $this->componentPluginManager);
     $this->moduleHandler->expects($this->atLeastOnce())
       ->method('moduleExists')
       ->with('example_module')
@@ -655,8 +664,9 @@ public function testLibraryOverride() {
       ->method('getPath')
       ->with('module', 'example_module')
       ->willReturn($path);
+    $this->componentPluginManager = $this->createMock(ComponentPluginManager::class);
 
-    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->streamWrapperManager, $this->librariesDirectoryFileFinder, $this->extensionPathResolver);
+    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->streamWrapperManager, $this->librariesDirectoryFileFinder, $this->extensionPathResolver, $this->componentPluginManager);
 
     $this->moduleHandler->expects($this->atLeastOnce())
       ->method('moduleExists')
@@ -709,7 +719,8 @@ public function testLibraryOverrideDeprecated() {
       ->method('getPath')
       ->with('module', 'deprecated')
       ->willReturn($path);
-    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->streamWrapperManager, $this->librariesDirectoryFileFinder, $this->extensionPathResolver);
+    $this->componentPluginManager = $this->createMock(ComponentPluginManager::class);
+    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->streamWrapperManager, $this->librariesDirectoryFileFinder, $this->extensionPathResolver, $this->componentPluginManager);
 
     $this->moduleHandler->expects($this->atLeastOnce())
       ->method('moduleExists')
diff --git a/core/tests/Drupal/Tests/Core/Extension/GenericTestExistsTest.php b/core/tests/Drupal/Tests/Core/Extension/GenericTestExistsTest.php
index 63696bb5d93c1002e30e33f7970f46ff6663cb90..fb540f943375c7f509145027ac1bd0ee58be4d8f 100644
--- a/core/tests/Drupal/Tests/Core/Extension/GenericTestExistsTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/GenericTestExistsTest.php
@@ -19,7 +19,7 @@ class GenericTestExistsTest extends UnitTestCase {
   /**
    * Lists module that do not require a Generic test.
    */
-  protected $modulesNoTest = ['help_topics'];
+  protected $modulesNoTest = ['help_topics', 'sdc'];
 
   /**
    * Tests that the Generic module test exists for all modules.
diff --git a/core/tests/Drupal/Tests/Core/Render/ElementTest.php b/core/tests/Drupal/Tests/Core/Render/ElementTest.php
index 5795e8da7a1b222487a717825a92d13fd6b0ba81..bc1b0217c6deb6abeb5d20d5ef1d267a6582ee41 100644
--- a/core/tests/Drupal/Tests/Core/Render/ElementTest.php
+++ b/core/tests/Drupal/Tests/Core/Render/ElementTest.php
@@ -225,4 +225,26 @@ public static function providerTestIsEmpty() {
     ];
   }
 
+  /**
+   * @covers ::isRenderArray
+   * @dataProvider dataProviderIsRenderArray
+   */
+  public function testIsRenderArray($build, $expected) {
+    $this->assertSame(
+      $expected,
+      Element::isRenderArray($build)
+    );
+  }
+
+  public function dataProviderIsRenderArray() {
+    return [
+      'valid markup render array' => [['#markup' => 'hello world'], TRUE],
+      'invalid "foo" string' => [['foo', '#markup' => 'hello world'], FALSE],
+      'null is not an array' => [NULL, FALSE],
+      'an empty array is not a render array' => [[], FALSE],
+      'funny enough a key with # is valid' => [['#' => TRUE], TRUE],
+      'nested arrays can be valid too' => [['one' => [2 => ['#three' => 'charm!']]], TRUE],
+    ];
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Theme/Component/ComponentKernelTestBase.php b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentKernelTestBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..0c71ae846b9d365547fee9cf62c847574b657f4b
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentKernelTestBase.php
@@ -0,0 +1,105 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\Core\Theme\Component;
+
+use Drupal\Core\Render\BubbleableMetadata;
+use Drupal\Core\Render\RenderContext;
+use Drupal\Core\Theme\ComponentNegotiator;
+use Drupal\Core\Theme\ComponentPluginManager;
+use Drupal\KernelTests\KernelTestBase;
+use Symfony\Component\DomCrawler\Crawler;
+
+/**
+ * Defines a base class for component kernel tests.
+ */
+abstract class ComponentKernelTestBase extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'system',
+    'user',
+    'serialization',
+  ];
+
+  /**
+   * Themes to install.
+   *
+   * @var string[]
+   */
+  protected static $themes = [];
+
+  /**
+   * The component negotiator.
+   *
+   * @return \Drupal\Core\Theme\ComponentNegotiator
+   */
+  protected ComponentNegotiator $negotiator;
+
+  /**
+   * The component plugin manager.
+   *
+   * @var \Drupal\Core\Theme\ComponentPluginManager
+   */
+  protected ComponentPluginManager $manager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    if (empty(static::$themes)) {
+      throw new \Exception('You need to set the protected static $themes property on your test class, with the first item being the default theme.');
+    }
+    $this->container->get('theme_installer')->install(static::$themes);
+    $this->installConfig('system');
+
+    $system_theme_config = $this->container->get('config.factory')->getEditable('system.theme');
+    $theme_name = reset(static::$themes);
+    $system_theme_config
+      ->set('default', $theme_name)
+      ->save();
+    $theme_manager = \Drupal::service('theme.manager');
+    $active_theme = \Drupal::service('theme.initialization')->initTheme($theme_name);
+    $theme_manager->setActiveTheme($active_theme);
+
+    $this->negotiator = new ComponentNegotiator(
+      $theme_manager,
+      \Drupal::service('extension.list.module'),
+    );
+    $this->manager = \Drupal::service('plugin.manager.sdc');
+  }
+
+  /**
+   * Renders a component for testing sake.
+   *
+   * @param array $component
+   *   Component render array.
+   * @param \Drupal\Core\Render\BubbleableMetadata|null $metadata
+   *   Bubble metadata.
+   *
+   * @return \Symfony\Component\DomCrawler\Crawler
+   *   Crawler for introspecting the rendered component.
+   */
+  protected function renderComponentRenderArray(array $component, ?BubbleableMetadata $metadata = NULL): Crawler {
+    $component = [
+      '#type' => 'container',
+      '#attributes' => [
+        'id' => 'sdc-wrapper',
+      ],
+      'component' => $component,
+    ];
+    $metadata = $metadata ?: new BubbleableMetadata();
+    $context = new RenderContext();
+    $renderer = \Drupal::service('renderer');
+    $output = $renderer->executeInRenderContext($context, fn () => $renderer->render($component));
+    if (!$context->isEmpty()) {
+      $metadata->addCacheableDependency($context->pop());
+    }
+    return new Crawler((string) $output);
+  }
+
+}
diff --git a/core/modules/sdc/tests/src/Unit/ComponentMetadataTest.php b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentMetadataTest.php
similarity index 89%
rename from core/modules/sdc/tests/src/Unit/ComponentMetadataTest.php
rename to core/tests/Drupal/Tests/Core/Theme/Component/ComponentMetadataTest.php
index d486eda26b6c91000ed218da8736bf256bf6ce2f..8eec15748d4c74c3503ea7253c46a6b3037a1dcc 100644
--- a/core/modules/sdc/tests/src/Unit/ComponentMetadataTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentMetadataTest.php
@@ -2,21 +2,19 @@
 
 declare(strict_types=1);
 
-namespace Drupal\Tests\sdc\Unit;
+namespace Drupal\Tests\Core\Theme\Component;
 
-use Drupal\sdc\Component\ComponentMetadata;
-use Drupal\sdc\Exception\InvalidComponentException;
+use Drupal\Core\Theme\Component\ComponentMetadata;
+use Drupal\Core\Render\Component\Exception\InvalidComponentException;
 use Drupal\Tests\UnitTestCaseTest;
 
 /**
  * Unit tests for the component metadata class.
  *
- * @coversDefaultClass \Drupal\sdc\Component\ComponentMetadata
+ * @coversDefaultClass \Drupal\Core\Theme\Component\ComponentMetadata
  * @group sdc
- *
- * @internal
  */
-final class ComponentMetadataTest extends UnitTestCaseTest {
+class ComponentMetadataTest extends UnitTestCaseTest {
 
   /**
    * Tests that the correct data is returned for each property.
@@ -59,7 +57,7 @@ public static function dataProviderMetadata(): array {
       'minimal example without schemas' => [
         [
           'path' => 'foo/bar/component-name',
-          'id' => 'sdc:component-name',
+          'id' => 'core:component-name',
           'name' => 'Component Name',
           'libraryOverrides' => ['dependencies' => ['core/drupal']],
           'group' => 'my-group',
@@ -75,8 +73,8 @@ public static function dataProviderMetadata(): array {
       ],
       'complete example with schema' => [
         [
-          '$schema' => 'https://git.drupalcode.org/project/sdc/-/raw/1.x/src/metadata.schema.json',
-          'id' => 'sdc:my-button',
+          '$schema' => 'https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json',
+          'id' => 'core:my-button',
           'machineName' => 'my-button',
           'path' => 'foo/my-other/path',
           'name' => 'Button',
diff --git a/core/modules/sdc/tests/src/Kernel/ComponentNegotiatorTest.php b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentNegotiatorTest.php
similarity index 91%
rename from core/modules/sdc/tests/src/Kernel/ComponentNegotiatorTest.php
rename to core/tests/Drupal/Tests/Core/Theme/Component/ComponentNegotiatorTest.php
index 48028a414fa78acc1fd883c2eb8b70b7ba043686..c2f40242ba959aa76cca6eda0330591cf0b3c3ce 100644
--- a/core/modules/sdc/tests/src/Kernel/ComponentNegotiatorTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentNegotiatorTest.php
@@ -1,16 +1,16 @@
 <?php
 
-namespace Drupal\Tests\sdc\Kernel;
+declare(strict_types=1);
+
+namespace Drupal\Tests\Core\Theme\Component;
 
 /**
  * Tests the component negotiator.
  *
- * @coversDefaultClass \Drupal\sdc\ComponentNegotiator
+ * @coversDefaultClass \Drupal\Core\Theme\ComponentNegotiator
  * @group sdc
- *
- * @internal
  */
-final class ComponentNegotiatorTest extends ComponentKernelTestBase {
+class ComponentNegotiatorTest extends ComponentKernelTestBase {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/sdc/tests/src/Kernel/ComponentPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentPluginManagerTest.php
similarity index 83%
rename from core/modules/sdc/tests/src/Kernel/ComponentPluginManagerTest.php
rename to core/tests/Drupal/Tests/Core/Theme/Component/ComponentPluginManagerTest.php
index 231f1bd7719bccad1d41375046ba8078363c9103..f962d50de020a0dd688e767f9692d519dd37cba9 100644
--- a/core/modules/sdc/tests/src/Kernel/ComponentPluginManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentPluginManagerTest.php
@@ -1,6 +1,8 @@
 <?php
 
-namespace Drupal\Tests\sdc\Kernel;
+declare(strict_types=1);
+
+namespace Drupal\Tests\Core\Theme\Component;
 
 use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
 
@@ -8,15 +10,13 @@
  * Tests the component plugin manager.
  *
  * @group sdc
- *
- * @internal
  */
-final class ComponentPluginManagerTest extends ComponentKernelTestBase {
+class ComponentPluginManagerTest extends ComponentKernelTestBase {
 
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['sdc', 'sdc_test', 'sdc_test_replacements'];
+  protected static $modules = ['system', 'sdc_test', 'sdc_test_replacements'];
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/sdc/tests/src/Unit/ComponentValidatorTest.php b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
similarity index 89%
rename from core/modules/sdc/tests/src/Unit/ComponentValidatorTest.php
rename to core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
index ddabdae49e569b8bccc2db90646f3440c9067d02..7c76a1830558981e7fb37b261ab313a93ff46396 100644
--- a/core/modules/sdc/tests/src/Unit/ComponentValidatorTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/Component/ComponentValidatorTest.php
@@ -2,31 +2,29 @@
 
 declare(strict_types=1);
 
-namespace Drupal\Tests\sdc\Unit;
+namespace Drupal\Tests\Core\Theme\Component;
 
 use Drupal\Core\Template\Attribute;
-use Drupal\sdc\Component\ComponentValidator;
-use Drupal\sdc\Exception\InvalidComponentException;
-use Drupal\sdc\Plugin\Component;
+use Drupal\Core\Theme\Component\ComponentValidator;
+use Drupal\Core\Render\Component\Exception\InvalidComponentException;
+use Drupal\Core\Plugin\Component;
 use PHPUnit\Framework\TestCase;
 use Symfony\Component\Yaml\Yaml;
 
 /**
  * Unit tests for the component validation.
  *
- * @coversDefaultClass \Drupal\sdc\Component\ComponentValidator
+ * @coversDefaultClass \Drupal\Core\Theme\Component\ComponentValidator
  * @group sdc
- *
- * @internal
  */
-final class ComponentValidatorTest extends TestCase {
+class ComponentValidatorTest extends TestCase {
 
   /**
    * Tests that valid component definitions don't cause errors.
    *
    * @dataProvider dataProviderValidateDefinitionValid
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   public function testValidateDefinitionValid(array $definition): void {
     $component_validator = new ComponentValidator();
@@ -92,7 +90,7 @@ public static function dataProviderValidateDefinitionInvalid(): array {
    *
    * @dataProvider dataProviderValidatePropsValid
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   public function testValidatePropsValid(array $context, string $component_id, array $definition): void {
     $component = new Component(
@@ -140,7 +138,7 @@ public static function dataProviderValidatePropsValid(): array {
    *
    * @dataProvider dataProviderValidatePropsInvalid
    *
-   * @throws \Drupal\sdc\Exception\InvalidComponentException
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
    */
   public function testValidatePropsInvalid(array $context, string $component_id, array $definition): void {
     $component = new Component(
@@ -201,7 +199,7 @@ public static function dataProviderValidatePropsInvalid(): array {
   private static function loadComponentDefinitionFromFs(string $component_name): array {
     return array_merge(
       Yaml::parseFile(
-        sprintf('%s/modules/sdc_test/components/%s/%s.component.yml', dirname(__DIR__, 2), $component_name, $component_name),
+        sprintf('%s/modules/system/tests/modules/sdc_test/components/%s/%s.component.yml', dirname(__DIR__, 6), $component_name, $component_name),
       ),
       [
         'machineName' => $component_name,
diff --git a/core/modules/sdc/tests/src/Unit/SchemaCompatibilityCheckerTest.php b/core/tests/Drupal/Tests/Core/Theme/Component/SchemaCompatibilityCheckerTest.php
similarity index 90%
rename from core/modules/sdc/tests/src/Unit/SchemaCompatibilityCheckerTest.php
rename to core/tests/Drupal/Tests/Core/Theme/Component/SchemaCompatibilityCheckerTest.php
index 7f542b209ef66b57d03110040773a18a54bb9d23..723819f1ace9f55450a4857fa914d8f92674d672 100644
--- a/core/modules/sdc/tests/src/Unit/SchemaCompatibilityCheckerTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/Component/SchemaCompatibilityCheckerTest.php
@@ -2,19 +2,17 @@
 
 declare(strict_types=1);
 
-namespace Drupal\Tests\sdc\Unit;
+namespace Drupal\Tests\Core\Theme\Component;
 
-use Drupal\sdc\Component\SchemaCompatibilityChecker;
-use Drupal\sdc\Exception\IncompatibleComponentSchema;
+use Drupal\Core\Theme\Component\SchemaCompatibilityChecker;
+use Drupal\Core\Render\Component\Exception\IncompatibleComponentSchema;
 use Drupal\Tests\UnitTestCase;
 
 /**
- * @coversDefaultClass \Drupal\sdc\Component\SchemaCompatibilityChecker
+ * @coversDefaultClass \Drupal\Core\Theme\Component\SchemaCompatibilityChecker
  * @group sdc
- *
- * @internal
  */
-final class SchemaCompatibilityCheckerTest extends UnitTestCase {
+class SchemaCompatibilityCheckerTest extends UnitTestCase {
 
   /**
    * The system under test.