diff --git a/src/Element/ComponentElementAlter.php b/src/Element/ComponentElementAlter.php
index f4e944e77e7b94a4c5de7e61863c4e3c0dc98752..f87f8a4f59a1590cc3978bbd3186e47ca073faa6 100644
--- a/src/Element/ComponentElementAlter.php
+++ b/src/Element/ComponentElementAlter.php
@@ -5,11 +5,9 @@ declare(strict_types=1);
 namespace Drupal\ui_patterns\Element;
 
 use Drupal\Component\Utility\NestedArray;
-use Drupal\Core\Plugin\Component;
 use Drupal\Core\Security\TrustedCallbackInterface;
 use Drupal\Core\Theme\ComponentPluginManager;
 use Drupal\ui_patterns\Plugin\UiPatterns\PropType\SlotPropType;
-use Drupal\ui_patterns\PropTypeAdapterPluginManager;
 
 /**
  * Our additions to the SDC render element.
@@ -19,23 +17,26 @@ class ComponentElementAlter implements TrustedCallbackInterface {
   /**
    * Constructs a ComponentElementAlter.
    */
-  public function __construct(protected ComponentPluginManager $componentPluginManager, protected PropTypeAdapterPluginManager $adaptersManager) {
-  }
+  public function __construct(protected ComponentPluginManager $componentPluginManager) {}
 
   /**
    * {@inheritdoc}
    */
   public static function trustedCallbacks() {
     return ['alter'];
+
   }
 
   /**
    * Alter SDC component element.
+   *
+   * There ::normalizeProps() methods logic has been moved to
+   * TwigExtension::normalizeProps() in order to be executed also when
+   * components are loaded from Twig include or embed.
    */
   public function alter(array $element): array {
     $element = $this->normalizeSlots($element);
     $component = $this->componentPluginManager->find($element['#component']);
-    $element = $this->normalizeProps($element, $component);
     // Attributes prop must never be empty, to avoid the processing of SDC's
     // ComponentsTwigExtension::mergeAdditionalRenderContext() which is adding
     // an Attribute PHP object before running the validator.
@@ -64,32 +65,6 @@ class ComponentElementAlter implements TrustedCallbackInterface {
     return $element;
   }
 
-  /**
-   * Normalize props.
-   */
-  public function normalizeProps(array $element, Component $component): array {
-    $props = $component->metadata->schema['properties'] ?? [];
-    foreach ($element["#props"] as $prop_id => $prop) {
-      if (!isset($props[$prop_id])) {
-        continue;
-      }
-      $definition = $props[$prop_id];
-      $prop_type = $definition['ui_patterns']['type_definition'];
-      // Normalizing attributes to an array is not working
-      // if the prop type is defined by type=Drupal\Core\Template\Attribute
-      // This should actually be done by the normalize function.
-      $data = $prop_type->normalize($prop);
-      if (isset($definition['ui_patterns']['prop_type_adapter'])) {
-        $prop_type_adapter_id = $definition['ui_patterns']['prop_type_adapter'];
-        /** @var \Drupal\ui_patterns\PropTypeAdapterInterface $prop_type_adapter */
-        $prop_type_adapter = $this->adaptersManager->createInstance($prop_type_adapter_id);
-        $data = $prop_type_adapter->transform($data);
-      }
-      $element["#props"][$prop_id] = $data;
-    }
-    return $element;
-  }
-
   /**
    * Process #attributes render property.
    *
diff --git a/src/Template/ComponentNodeVisitor.php b/src/Template/ComponentNodeVisitor.php
deleted file mode 100755
index 6da6ff0e1fb1b73bf360a953b7f265ecd8be4432..0000000000000000000000000000000000000000
--- a/src/Template/ComponentNodeVisitor.php
+++ /dev/null
@@ -1,153 +0,0 @@
-<?php
-
-namespace Drupal\ui_patterns\Template;
-
-use Drupal\Core\Plugin\Component;
-use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
-use Drupal\Core\Template\ComponentNodeVisitor as CoreComponentNodeVisitor;
-use Drupal\Core\Theme\ComponentPluginManager;
-use Twig\Environment;
-use Twig\Node\Expression\ConstantExpression;
-use Twig\Node\Expression\FunctionExpression;
-use Twig\Node\ModuleNode;
-use Twig\Node\Node;
-use Twig\Node\PrintNode;
-use Twig\NodeVisitor\NodeVisitorInterface;
-use Twig\TwigFunction;
-
-/**
- * Provides a ComponentNodeVisitor to change the generated parse-tree.
- *
- * @internal
- */
-class ComponentNodeVisitor implements NodeVisitorInterface {
-
-  /**
-   * Node name: expr.
-   */
-  const NODE_NAME_EXPR = 'expr';
-
-  /**
-   * The component plugin manager.
-   */
-  protected ComponentPluginManager $componentManager;
-
-  /**
-   * Constructs a new ComponentNodeVisitor object.
-   *
-   * @param \Drupal\Core\Theme\ComponentPluginManager $component_plugin_manager
-   *   The component plugin manager.
-   */
-  public function __construct(ComponentPluginManager $component_plugin_manager) {
-    $this->componentManager = $component_plugin_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function enterNode(Node $node, Environment $env): Node {
-    return $node;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function leaveNode(Node $node, Environment $env): ?Node {
-    if (!$node instanceof ModuleNode) {
-      return $node;
-    }
-    $component = $this->getComponent($node);
-    if (!($component instanceof Component)) {
-      return $node;
-    }
-    $line = $node->getTemplateLine();
-    $function = $this->buildPreprocessPropsFunction($line, $component, $env);
-    $node = $this->injectFunction($node, $function);
-    return $node;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPriority(): int {
-    $priority = &drupal_static(__METHOD__);
-    if (!isset($priority)) {
-      $original_node_visitor = new CoreComponentNodeVisitor($this->componentManager);
-      // Ensure that this component node visitor's priority is higher than
-      // core's node visitor class for components, because this class has to run
-      // core's class.
-      $priority = $original_node_visitor->getPriority() + 1;
-    }
-    return is_numeric($priority) ? (int) $priority : 0;
-  }
-
-  /**
-   * Finds the SDC for the current module node.
-   *
-   * A duplicate of \Drupal\Core\Template\ComponentNodeVisitor::getComponent()
-   *
-   * @param \Twig\Node\Node $node
-   *   The node.
-   *
-   * @return \Drupal\Core\Plugin\Component|null
-   *   The component, if any.
-   */
-  protected function getComponent(Node $node): ?Component {
-    $component_id = $node->getTemplateName();
-    if (!preg_match('/^[a-z]([a-zA-Z0-9_-]*[a-zA-Z0-9])*:[a-z]([a-zA-Z0-9_-]*[a-zA-Z0-9])*$/', $component_id)) {
-      return NULL;
-    }
-    try {
-      return $this->componentManager->find($component_id);
-    }
-    catch (ComponentNotFoundException $e) {
-      return NULL;
-    }
-  }
-
-  /**
-   * Build the _ui_patterns_preprocess_props Twig function.
-   *
-   * @param int $line
-   *   The line .
-   * @param \Drupal\Core\Plugin\Component $component
-   *   The component.
-   * @param \Twig\Environment $env
-   *   A Twig Environment instance.
-   *
-   * @return \Twig\Node\Node
-   *   The Twig function.
-   */
-  protected function buildPreprocessPropsFunction(int $line, Component $component, Environment $env): Node {
-    $component_id = $component->getPluginId();
-    $function_parameter = new ConstantExpression($component_id, $line);
-    $function_parameters_node = new Node([$function_parameter]);
-    $function = new FunctionExpression(
-      new TwigFunction('_ui_patterns_preprocess_props', [$env->getExtension(TwigExtension::class), 'preprocessProps'], ['needs_context' => TRUE]),
-      $function_parameters_node,
-      $line
-    );
-    return new PrintNode($function, $line);
-  }
-
-  /**
-   * Injects custom Twig nodes into given node as child nodes.
-   *
-   * The function will be injected direct after  validate_component_props
-   * function already injected by SDC's ComponentNodeVisitor.
-   *
-   * @param \Twig\Node\Node $node
-   *   The node where we will inject the function in.
-   * @param \Twig\Node\Node $function
-   *   The Twig function.
-   *
-   * @return \Twig\Node\Node
-   *   The node with the function inserted.
-   */
-  protected function injectFunction(Node $node, Node $function): Node {
-    $insertion = new Node([$node->getNode('display_start'), $function]);
-    $node->setNode('display_start', $insertion);
-    return $node;
-  }
-
-}
diff --git a/src/Template/ModuleNodeVisitorAfterSdc.php b/src/Template/ModuleNodeVisitorAfterSdc.php
new file mode 100755
index 0000000000000000000000000000000000000000..ecff57dc64783d97223366876e4b52fd212d0210
--- /dev/null
+++ b/src/Template/ModuleNodeVisitorAfterSdc.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Drupal\ui_patterns\Template;
+
+use Drupal\Core\Plugin\Component;
+use Drupal\Core\Template\ComponentNodeVisitor as CoreComponentNodeVisitor;
+use Twig\Environment;
+use Twig\Node\Expression\ConstantExpression;
+use Twig\Node\Expression\FunctionExpression;
+use Twig\Node\ModuleNode;
+use Twig\Node\Node;
+use Twig\Node\PrintNode;
+use Twig\TwigFunction;
+
+/**
+ * Provides a Node Visitor to change the generated parse-tree.
+ */
+class ModuleNodeVisitorAfterSdc extends ModuleNodeVisitorBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function leaveNode(Node $node, Environment $env): ?Node {
+    if (!$node instanceof ModuleNode) {
+      return $node;
+    }
+    $component = $this->getComponent($node);
+    if (!($component instanceof Component)) {
+      return $node;
+    }
+    $line = $node->getTemplateLine();
+    $function = $this->buildPreprocessPropsFunction($line, $component, $env);
+    $node = $this->injectFunction($node, $function);
+    return $node;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPriority(): int {
+    $priority = &drupal_static(__METHOD__);
+    if (!isset($priority)) {
+      $original_node_visitor = new CoreComponentNodeVisitor($this->componentManager);
+      // Ensure that this node visitor's priority is higher than core's visitor,
+      // because this class has to run after core's class.
+      $priority = $original_node_visitor->getPriority() + 1;
+    }
+    return is_numeric($priority) ? (int) $priority : 0;
+  }
+
+  /**
+   * Build the _ui_patterns_preprocess_props Twig function.
+   *
+   * @param int $line
+   *   The line .
+   * @param \Drupal\Core\Plugin\Component $component
+   *   The component.
+   * @param \Twig\Environment $env
+   *   A Twig Environment instance.
+   *
+   * @return \Twig\Node\Node
+   *   The Twig function.
+   */
+  protected function buildPreprocessPropsFunction(int $line, Component $component, Environment $env): Node {
+    $component_id = $component->getPluginId();
+    $function_parameter = new ConstantExpression($component_id, $line);
+    $function_parameters_node = new Node([$function_parameter]);
+    $function = new FunctionExpression(
+      new TwigFunction('_ui_patterns_preprocess_props', [$env->getExtension(TwigExtension::class), 'preprocessProps'], ['needs_context' => TRUE]),
+      $function_parameters_node,
+      $line
+    );
+    return new PrintNode($function, $line);
+  }
+
+}
diff --git a/src/Template/ModuleNodeVisitorBase.php b/src/Template/ModuleNodeVisitorBase.php
new file mode 100755
index 0000000000000000000000000000000000000000..d00f757bbb9b3e883953db98d950c98b6f74952f
--- /dev/null
+++ b/src/Template/ModuleNodeVisitorBase.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace Drupal\ui_patterns\Template;
+
+use Drupal\Core\Plugin\Component;
+use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
+use Drupal\Core\Theme\ComponentPluginManager;
+use Twig\Environment;
+use Twig\Node\Node;
+use Twig\NodeVisitor\NodeVisitorInterface;
+
+/**
+ * Provides a Node Visitor to change the generated parse-tree.
+ */
+abstract class ModuleNodeVisitorBase implements NodeVisitorInterface {
+
+  /**
+   * The component plugin manager.
+   */
+  protected ComponentPluginManager $componentManager;
+
+  /**
+   * Constructs a new ComponentNodeVisitor object.
+   *
+   * @param \Drupal\Core\Theme\ComponentPluginManager $component_plugin_manager
+   *   The component plugin manager.
+   */
+  public function __construct(ComponentPluginManager $component_plugin_manager) {
+    $this->componentManager = $component_plugin_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function enterNode(Node $node, Environment $env): Node {
+    return $node;
+  }
+
+  /**
+   * Finds the SDC for the current module node.
+   *
+   * A duplicate of \Drupal\Core\Template\ComponentNodeVisitor::getComponent()
+   *
+   * @param \Twig\Node\Node $node
+   *   The node.
+   *
+   * @return \Drupal\Core\Plugin\Component|null
+   *   The component, if any.
+   */
+  protected function getComponent(Node $node): ?Component {
+    $component_id = $node->getTemplateName();
+    if (!preg_match('/^[a-z]([a-zA-Z0-9_-]*[a-zA-Z0-9])*:[a-z]([a-zA-Z0-9_-]*[a-zA-Z0-9])*$/', $component_id)) {
+      return NULL;
+    }
+    try {
+      return $this->componentManager->find($component_id);
+    }
+    catch (ComponentNotFoundException $e) {
+      return NULL;
+    }
+  }
+
+  /**
+   * Injects custom Twig nodes into given node as child nodes.
+   *
+   * The function will be injected direct after  validate_component_props
+   * function already injected by SDC's ComponentNodeVisitor.
+   *
+   * @param \Twig\Node\Node $node
+   *   The node where we will inject the function in.
+   * @param \Twig\Node\Node $function
+   *   The Twig function.
+   *
+   * @return \Twig\Node\Node
+   *   The node with the function inserted.
+   */
+  protected function injectFunction(Node $node, Node $function): Node {
+    $insertion = new Node([$node->getNode('display_start'), $function]);
+    $node->setNode('display_start', $insertion);
+    return $node;
+  }
+
+}
diff --git a/src/Template/ModuleNodeVisitorBeforeSdc.php b/src/Template/ModuleNodeVisitorBeforeSdc.php
new file mode 100755
index 0000000000000000000000000000000000000000..fea34b2d707f509d27eb43dba664c872734938a5
--- /dev/null
+++ b/src/Template/ModuleNodeVisitorBeforeSdc.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Drupal\ui_patterns\Template;
+
+use Drupal\Core\Plugin\Component;
+use Drupal\Core\Template\ComponentNodeVisitor as CoreComponentNodeVisitor;
+use Twig\Environment;
+use Twig\Node\Expression\ConstantExpression;
+use Twig\Node\Expression\FunctionExpression;
+use Twig\Node\ModuleNode;
+use Twig\Node\Node;
+use Twig\Node\PrintNode;
+use Twig\TwigFunction;
+
+/**
+ * Provides a Node Visitor to change the generated parse-tree.
+ */
+class ModuleNodeVisitorBeforeSdc extends ModuleNodeVisitorBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function leaveNode(Node $node, Environment $env): ?Node {
+    if (!$node instanceof ModuleNode) {
+      return $node;
+    }
+    $component = $this->getComponent($node);
+    if (!($component instanceof Component)) {
+      return $node;
+    }
+    $line = $node->getTemplateLine();
+    $function = $this->buildNormalizePropsFunction($line, $component, $env);
+    $node = $this->injectFunction($node, $function);
+    return $node;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPriority(): int {
+    $priority = &drupal_static(__METHOD__);
+    if (!isset($priority)) {
+      $original_node_visitor = new CoreComponentNodeVisitor($this->componentManager);
+      // Ensure that this node visitor's priority is lower than core's visitor,
+      // because this class has to run before core's class.
+      $priority = $original_node_visitor->getPriority() - 1;
+    }
+    return is_numeric($priority) ? (int) $priority : 0;
+  }
+
+  /**
+   * Build the _ui_patterns_preprocess_props Twig function.
+   *
+   * @param int $line
+   *   The line .
+   * @param \Drupal\Core\Plugin\Component $component
+   *   The component.
+   * @param \Twig\Environment $env
+   *   A Twig Environment instance.
+   *
+   * @return \Twig\Node\Node
+   *   The Twig function.
+   */
+  protected function buildNormalizePropsFunction(int $line, Component $component, Environment $env): Node {
+    $component_id = $component->getPluginId();
+    $function_parameter = new ConstantExpression($component_id, $line);
+    $function_parameters_node = new Node([$function_parameter]);
+    $function = new FunctionExpression(
+      new TwigFunction('_ui_patterns_normalize_props', [$env->getExtension(TwigExtension::class), 'normalizeProps'], ['needs_context' => TRUE]),
+      $function_parameters_node,
+      $line
+    );
+    return new PrintNode($function, $line);
+  }
+
+}
diff --git a/src/Template/TwigExtension.php b/src/Template/TwigExtension.php
index d193e8ab09c636b7e2664a4e18a4764849023ffd..c6f2e79e79092b8114198ed5e05fbfe349bebe49 100644
--- a/src/Template/TwigExtension.php
+++ b/src/Template/TwigExtension.php
@@ -4,7 +4,10 @@ declare(strict_types=1);
 
 namespace Drupal\ui_patterns\Template;
 
+use Drupal\Core\Messenger\MessengerInterface;
 use Drupal\ui_patterns\ComponentPluginManager;
+use Drupal\ui_patterns\Plugin\UiPatterns\PropType\SlotPropType;
+use Drupal\ui_patterns\PropTypeAdapterPluginManager;
 use Twig\Extension\AbstractExtension;
 use Twig\TwigFilter;
 use Twig\TwigFunction;
@@ -23,9 +26,15 @@ class TwigExtension extends AbstractExtension {
    *
    * @param \Drupal\ui_patterns\ComponentPluginManager $componentManager
    *   The component plugin manager.
+   * @param \Drupal\ui_patterns\PropTypeAdapterPluginManager $adapterManager
+   *   The prop type adapter plugin manager.
+   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
+   *   The messenger.
    */
   public function __construct(
     protected ComponentPluginManager $componentManager,
+    protected PropTypeAdapterPluginManager $adapterManager,
+    protected MessengerInterface $messenger,
   ) {}
 
   /**
@@ -40,7 +49,8 @@ class TwigExtension extends AbstractExtension {
    */
   public function getNodeVisitors(): array {
     return [
-      new ComponentNodeVisitor($this->componentManager),
+      new ModuleNodeVisitorBeforeSdc($this->componentManager),
+      new ModuleNodeVisitorAfterSdc($this->componentManager),
     ];
   }
 
@@ -49,7 +59,11 @@ class TwigExtension extends AbstractExtension {
    */
   public function getFunctions() {
     return [
+      // @todo Remove component() before 2.0.0 release.
       new TwigFunction('component', [$this, 'renderComponent']),
+      // For ComponentNodeVisitorBeforeSdc.
+      new TwigFunction('_ui_patterns_normalize_props', [$this, 'normalizeProps'], ['needs_context' => TRUE]),
+      // For ComponentNodeVisitorAfterSdc.
       new TwigFunction('_ui_patterns_preprocess_props', [$this, 'preprocessProps'], ['needs_context' => TRUE]),
     ];
   }
@@ -80,6 +94,7 @@ class TwigExtension extends AbstractExtension {
    * @see \Drupal\Core\Theme\Element\ComponentElement
    */
   public function renderComponent(string $component_id, array $slots = [], array $props = []) {
+    $this->messenger->addWarning("component() Twig function is deprecated in favor of include() function and will be removed before 2.0.0.");
     return [
       '#type' => 'component',
       '#component' => $component_id,
@@ -88,6 +103,45 @@ class TwigExtension extends AbstractExtension {
     ];
   }
 
+  /**
+   * Normalize props (and slots).
+   *
+   * This function must not be used by the templates authors. In a perfect
+   * world, it would not be necessary to set such a function. We did that to be
+   * compatible with SDC's ComponentNodeVisitor, in order to execute props
+   * normalization before SDC's validate_component_props Twig function.
+   *
+   * See ModuleNodeVisitorBeforeSdc.
+   *
+   * @param array $context
+   *   The context provided to the component.
+   * @param string $component_id
+   *   The component ID.
+   *
+   * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
+   */
+  public function normalizeProps(array &$context, string $component_id): void {
+    $component = $this->componentManager->find($component_id);
+    $props = $component->metadata->schema['properties'] ?? [];
+    foreach ($context as $variable => $value) {
+      if (isset($component->metadata->slots[$variable])) {
+        $context[$variable] = SlotPropType::normalize($value);
+        continue;
+      }
+      if (!isset($props[$variable])) {
+        continue;
+      }
+      $prop_type = $props[$variable]['ui_patterns']['type_definition'];
+      $context[$variable] = $prop_type->normalize($value);
+      if (isset($props[$variable]['ui_patterns']['prop_type_adapter'])) {
+        $prop_type_adapter_id = $props[$variable]['ui_patterns']['prop_type_adapter'];
+        /** @var \Drupal\ui_patterns\PropTypeAdapterInterface $prop_type_adapter */
+        $prop_type_adapter = $this->adapterManager->createInstance($prop_type_adapter_id);
+        $context[$variable] = $prop_type_adapter->transform($context[$variable]);
+      }
+    }
+  }
+
   /**
    * Preprocess props.
    *
@@ -96,6 +150,8 @@ class TwigExtension extends AbstractExtension {
    * compatible with SDC's ComponentNodeVisitor, in order to execute props
    * preprocessing after SDC's validate_component_props Twig function.
    *
+   * See ModuleNodeVisitorAfterSdc.
+   *
    * @param array $context
    *   The context provided to the component.
    * @param string $component_id
diff --git a/tests/modules/ui_patterns_test/components/alert/alert.twig b/tests/modules/ui_patterns_test/components/alert/alert.twig
index 04952e93a93d61ce32b1105071b2d5b8aac006b3..15212aeec969d0ae9d001dea651dae803401adaf 100644
--- a/tests/modules/ui_patterns_test/components/alert/alert.twig
+++ b/tests/modules/ui_patterns_test/components/alert/alert.twig
@@ -12,10 +12,10 @@
   {% endif %}
   {{ message|add_class('alert-link') }}
   {% if dismissible %}
-    {{ component('ui_patterns_test:close_button', {}, {
-      attributes: create_attribute({
-        'data-bs-dismiss': 'alert'
-      }),
+    {{ include('ui_patterns_test:close_button', {
+      attributes: {
+        'data-bs-dismiss': 'alert',
+      },
       aria_label: 'Close'|t,
     }) }}
   {% endif %}
diff --git a/ui_patterns.services.yml b/ui_patterns.services.yml
index abffbf352b4d9e402649948f7be24826407bb364..593f10246a27be5dcc66fbb7aab491a982d0e57e 100644
--- a/ui_patterns.services.yml
+++ b/ui_patterns.services.yml
@@ -75,6 +75,8 @@ services:
       - { name: twig.extension }
     arguments:
       - "@plugin.manager.sdc"
+      - "@plugin.manager.ui_patterns_prop_type_adapter"
+      - '@messenger'
 
   ui_patterns.sample_entity_generator:
     class: Drupal\ui_patterns\Entity\SampleEntityGenerator