diff --git a/config_normalizer.services.yml b/config_normalizer.services.yml
index dca7b3450b6b35d15bf46994b73868484a5d87b8..3480b0117ba3e365b8a68c67d9add5ebe879ad56 100644
--- a/config_normalizer.services.yml
+++ b/config_normalizer.services.yml
@@ -2,3 +2,7 @@ services:
   plugin.manager.config_normalizer:
     class: Drupal\config_normalizer\Plugin\ConfigNormalizerManager
     parent: default_plugin_manager
+  config_normalizer.config_sorter:
+    class: Drupal\config_normalizer\Config\ConfigSorter
+    arguments:
+      - '@config.typed'
diff --git a/src/Config/ConfigSorter.php b/src/Config/ConfigSorter.php
new file mode 100644
index 0000000000000000000000000000000000000000..b767219eb209be3968149a9fec88c65d002a58c2
--- /dev/null
+++ b/src/Config/ConfigSorter.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace Drupal\config_normalizer\Config;
+
+use Drupal\Core\Config\StorableConfigBase;
+use Drupal\Core\Config\TypedConfigManagerInterface;
+
+/**
+ * Provides schema-based sorting of configuration arrays.
+ *
+ * This class leverages Drupal's internal sorting logic introduced in
+ * https://www.drupal.org/project/drupal/issues/2852557 to sort configuration
+ * data based on its schema.
+ */
+class ConfigSorter {
+
+  /**
+   * The typed configuration manager service.
+   *
+   * @var \Drupal\Core\Config\TypedConfigManagerInterface
+   */
+  protected TypedConfigManagerInterface $typedConfigManager;
+
+  /**
+   * Constructs a ConfigSorter object.
+   *
+   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager
+   *   The typed configuration manager service to manage configuration schemas.
+   */
+  public function __construct(TypedConfigManagerInterface $typedConfigManager) {
+    $this->typedConfigManager = $typedConfigManager;
+  }
+
+  /**
+   * Sorts a configuration array based on its schema.
+   *
+   * This method creates an anonymous class that extends StorableConfigBase
+   * and uses the internal sorting mechanism to sort the provided configuration
+   * data according to the schema for the given configuration name.
+   *
+   * @param string $name
+   *   The name of the configuration to be sorted.
+   * @param array $data
+   *   The configuration data to be sorted.
+   *
+   * @return array
+   *   The sorted configuration data.
+   */
+  public function sort(string $name, array $data): array {
+    // Create an anonymous class that extends StorableConfigBase
+    // for sorting the configuration data based on its schema.
+    $sorter = new class($this->typedConfigManager) extends StorableConfigBase {
+
+      /**
+       * Constructs the anonymous class instance.
+       *
+       * @param \Drupal\Core\Config\TypedConfigManagerInterface $typedConfigManager
+       *   The typed configuration manager service.
+       */
+      public function __construct(TypedConfigManagerInterface $typedConfigManager) {
+        $this->typedConfigManager = $typedConfigManager;
+      }
+
+      /**
+       * Retrieves the schema wrapper for the configuration data.
+       *
+       * This method creates and returns the schema wrapper for the given
+       * configuration data using the TypedConfigManager service.
+       *
+       * @return \Drupal\Core\Config\ConfigSchemaInterface
+       *   The schema wrapper for the configuration data.
+       */
+      protected function getSchemaWrapper() {
+        if (!isset($this->schemaWrapper)) {
+          // Create the schema wrapper if it hasn't been created already.
+          $this->schemaWrapper = $this->typedConfigManager->createFromNameAndData($this->name, $this->data);
+        }
+        return $this->schemaWrapper;
+      }
+
+      /**
+       * Sorts the configuration data based on the schema.
+       *
+       * This method checks if the configuration has a schema, casts the value
+       * if necessary, and validates the data values before returning
+       * the sorted data.
+       *
+       * @param string $name
+       *   The name of the configuration to be sorted.
+       * @param array $data
+       *   The configuration data to be sorted.
+       *
+       * @return array
+       *   The sorted configuration data.
+       */
+      public function anonymousSort(string $name, array $data): array {
+        // Set the name and initialize the data for sorting.
+        $this->setName($name)->initWithData($data);
+
+        // If a schema exists, cast the value according to the schema.
+        if ($this->typedConfigManager->hasConfigSchema($name)) {
+          $this->data = $this->castValue(NULL, $this->data);
+        }
+        else {
+          // If no schema, validate the data values.
+          foreach ($this->data as $key => $value) {
+            $this->validateValue($key, $value);
+          }
+        }
+
+        // Return the sorted configuration data.
+        return $this->data;
+      }
+
+      /**
+       * Throws a LogicException when attempting to save the configuration.
+       *
+       * This method is not supported in the current class and will always throw
+       * an exception.
+       *
+       * @param bool $has_trusted_data
+       *   Whether the data has been trusted. Not used in this case.
+       *
+       * @throws \LogicException
+       *   Always throws an exception.
+       */
+      public function save($has_trusted_data = FALSE) {
+        throw new \LogicException('Saving is not supported.');
+      }
+
+      /**
+       * Throws a LogicException when attempting to delete the configuration.
+       *
+       * This method is not supported in the current class and will always throw
+       * an exception.
+       *
+       * @throws \LogicException
+       *   Always throws an exception.
+       */
+      public function delete() {
+        throw new \LogicException('Deletion is not supported.');
+      }
+
+    };
+
+    // Return the sorted configuration data.
+    return $sorter->anonymousSort($name, $data);
+  }
+
+}
diff --git a/src/Plugin/ConfigNormalizer/ConfigNormalizerSort.php b/src/Plugin/ConfigNormalizer/ConfigNormalizerSort.php
index e6274543d356543feb611e296fef4d708d14ba70..c9960a22e1041d2c22dd8943223e7cf8113b56a6 100644
--- a/src/Plugin/ConfigNormalizer/ConfigNormalizerSort.php
+++ b/src/Plugin/ConfigNormalizer/ConfigNormalizerSort.php
@@ -3,11 +3,13 @@
 namespace Drupal\config_normalizer\Plugin\ConfigNormalizer;
 
 use Drupal\config_normalizer\Plugin\ConfigNormalizerBase;
+use Drupal\config_normalizer\Config\ConfigSorter;
+use Drupal\Core\Config\TypedConfigManagerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Symfony\Component\Yaml\Inline;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
- * Recursively sorts a configuration array.
+ * ConfigNormalizer plugin to recursively sort a configuration array.
  *
  * @ConfigNormalizer(
  *   id = "sort",
@@ -19,46 +21,81 @@ use Symfony\Component\Yaml\Inline;
 class ConfigNormalizerSort extends ConfigNormalizerBase implements ContainerFactoryPluginInterface {
 
   /**
-   * {@inheritdoc}
+   * The typed configuration manager service.
+   *
+   * @var \Drupal\Core\Config\TypedConfigManagerInterface
    */
-  public function normalize($name, array &$data, array $context) {
-    // Only sort if the normalization mode is default.
-    if ($this->isDefaultModeContext($context)) {
-      // Recursively normalize and return.
-      $data = $this->normalizeArray($data);
-    }
-  }
+  protected TypedConfigManagerInterface $typedConfigManager;
 
   /**
-   * Recursively sorts an array by key.
+   * The configuration sorter service.
    *
-   * @param array $array
-   *   An array to normalize.
+   * @var \Drupal\config_normalizer\Config\ConfigSorter
+   */
+  protected ConfigSorter $configSorter;
+
+  /**
+   * ConfigNormalizerSort constructor.
    *
-   * @return array
-   *   An array that is sorted by key, at each level of the array, with empty
-   *   arrays removed.
+   * @param array $configuration
+   *   The plugin configuration.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager
+   *   The typed config manager service.
+   * @param \Drupal\config_normalizer\Config\ConfigSorter $config_sorter
+   *   The config sorter service.
    */
-  protected function normalizeArray(array $array) {
-    foreach ($array as $key => $value) {
-      if (is_array($value)) {
-        $new = $this->normalizeArray($value);
-        if (count($new)) {
-          $array[$key] = $new;
-        }
-      }
-    }
+  public function __construct(
+    array $configuration,
+    $plugin_id,
+    $plugin_definition,
+    TypedConfigManagerInterface $typed_config_manager,
+    ConfigSorter $config_sorter,
+  ) {
+    parent::__construct(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $typed_config_manager,
+    );
+    $this->typedConfigManager = $typed_config_manager;
+    $this->configSorter = $config_sorter;
+  }
 
-    // If the array is associative, sort by key.
-    if (Inline::isHash($array)) {
-      ksort($array);
-    }
-    // Otherwise, sort by value.
-    else {
-      sort($array);
-    }
+  /**
+   * Creates an instance of the ConfigNormalizerSort plugin.
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('config.typed'),
+      $container->get('config_normalizer.config_sorter')
+    );
+  }
 
-    return $array;
+  /**
+   * Normalizes the configuration data by sorting it recursively.
+   *
+   * This method is called to sort the configuration data based on its schema.
+   * It uses the ConfigSorter service to perform the sorting operation.
+   *
+   * @param string $name
+   *   The name of the configuration.
+   * @param array &$data
+   *   The configuration data to be normalized (sorted).
+   * @param array $context
+   *   The context in which the normalization takes place.
+   *
+   * @return array
+   *   The sorted configuration data.
+   */
+  public function normalize($name, array &$data, array $context = []): array {
+    return $this->configSorter->sort($name, $data);
   }
 
 }
diff --git a/tests/fixtures/config/install/core.entity_view_display.node.article.default.yml b/tests/fixtures/config/install/core.entity_view_display.node.article.default.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f2665c8849006d813014b95bb7c3e608ba1329e6
--- /dev/null
+++ b/tests/fixtures/config/install/core.entity_view_display.node.article.default.yml
@@ -0,0 +1,55 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.article.field_body
+    - field.field.node.article.field_media_image
+    - field.field.node.article.field_tags
+    - field.field.node.article.layout_builder__layout
+    - node.type.article
+  module:
+    - layout_builder
+    - text
+    - user
+third_party_settings:
+  layout_builder:
+    enabled: false
+    allow_custom: false
+id: node.article.default
+targetEntityType: node
+bundle: article
+mode: default
+content:
+  field_body:
+    type: text_default
+    label: hidden
+    settings: {  }
+    third_party_settings: {  }
+    weight: 3
+    region: content
+  field_media_image:
+    type: entity_reference_entity_view
+    label: hidden
+    settings:
+      view_mode: responsive_3x2
+      link: false
+    third_party_settings: {  }
+    weight: 2
+    region: content
+  field_tags:
+    type: entity_reference_label
+    label: above
+    settings:
+      link: true
+    third_party_settings: {  }
+    weight: 0
+    region: content
+  links:
+    settings: {  }
+    third_party_settings: {  }
+    weight: 4
+    region: content
+hidden:
+  content_moderation_control: true
+  langcode: true
+  layout_builder__layout: true
diff --git a/tests/fixtures/config/install/views.view.recipes.yml b/tests/fixtures/config/install/views.view.recipes.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3a7aae659b5c59d07fb77260a38a2b264dbd75c2
--- /dev/null
+++ b/tests/fixtures/config/install/views.view.recipes.yml
@@ -0,0 +1,275 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - core.entity_view_mode.node.card
+    - node.type.recipe
+    - system.menu.main
+  module:
+    - node
+    - user
+id: recipes
+label: Recipes
+module: views
+description: 'Recipes listing'
+tag: ''
+base_table: node_field_data
+base_field: nid
+display:
+  default:
+    id: default
+    display_title: Default
+    display_plugin: default
+    position: 0
+    display_options:
+      title: Recipes
+      fields:
+        title:
+          id: title
+          table: node_field_data
+          field: title
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: title
+          plugin_id: field
+          label: ''
+          exclude: false
+          alter:
+            alter_text: false
+            make_link: false
+            absolute: false
+            word_boundary: false
+            ellipsis: false
+            strip_tags: false
+            trim: false
+            html: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          settings:
+            link_to_entity: true
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+      pager:
+        type: mini
+        options:
+          offset: 0
+          pagination_heading_level: h4
+          items_per_page: 12
+          total_pages: null
+          id: 0
+          tags:
+            next: ››
+            previous: ‹‹
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: tag
+        options: {  }
+      empty: {  }
+      sorts:
+        created:
+          id: created
+          table: node_field_data
+          field: created
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: created
+          plugin_id: date
+          order: DESC
+          expose:
+            label: ''
+            field_identifier: created
+          exposed: false
+          granularity: second
+        nid:
+          id: nid
+          table: node_field_data
+          field: nid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: nid
+          plugin_id: standard
+          order: ASC
+          expose:
+            label: ''
+            field_identifier: nid
+          exposed: false
+      arguments: {  }
+      filters:
+        status:
+          id: status
+          table: node_field_data
+          field: status
+          entity_type: node
+          entity_field: status
+          plugin_id: boolean
+          value: '1'
+          group: 1
+          expose:
+            operator: ''
+            operator_limit_selection: false
+            operator_list: {  }
+        type:
+          id: type
+          table: node_field_data
+          field: type
+          entity_type: node
+          entity_field: type
+          plugin_id: bundle
+          value:
+            recipe: recipe
+          group: 1
+          expose:
+            operator_limit_selection: false
+            operator_list: {  }
+        default_langcode:
+          id: default_langcode
+          table: node_field_data
+          field: default_langcode
+          relationship: none
+          group_type: group
+          admin_label: ''
+          entity_type: node
+          entity_field: default_langcode
+          plugin_id: boolean
+          operator: '='
+          value: '1'
+          group: 1
+          exposed: false
+          expose:
+            operator_id: ''
+            label: ''
+            description: ''
+            use_operator: false
+            operator: ''
+            operator_limit_selection: false
+            operator_list: {  }
+            identifier: ''
+            required: false
+            remember: false
+            multiple: false
+            remember_roles:
+              authenticated: authenticated
+          is_grouped: false
+          group_info:
+            label: ''
+            description: ''
+            identifier: ''
+            optional: true
+            widget: select
+            multiple: false
+            remember: false
+            default_group: All
+            default_group_multiple: {  }
+            group_items: {  }
+      filter_groups:
+        operator: AND
+        groups:
+          1: AND
+      style:
+        type: grid_responsive
+        options:
+          uses_fields: false
+          columns: 4
+          cell_min_width: 240
+          grid_gutter: 14
+          alignment: horizontal
+      row:
+        type: 'entity:node'
+        options:
+          relationship: none
+          view_mode: card
+      query:
+        type: views_query
+        options:
+          query_comment: ''
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_tags: {  }
+      relationships: {  }
+      css_class: ''
+      header: {  }
+      footer: {  }
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url.query_args
+        - 'user.node_grants:view'
+        - user.permissions
+      tags: {  }
+  page_1:
+    id: page_1
+    display_title: Page
+    display_plugin: page
+    position: 1
+    display_options:
+      rendering_language: '***LANGUAGE_language_content***'
+      display_extenders: {  }
+      path: recipes
+      menu:
+        type: normal
+        title: Recipes
+        description: ''
+        weight: 30
+        expanded: false
+        menu_name: main
+        parent: ''
+        context: '0'
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - url.query_args
+        - 'user.node_grants:view'
+        - user.permissions
+      tags: {  }
diff --git a/tests/src/Kernel/ConfigNormalizerSortTest.php b/tests/src/Kernel/ConfigNormalizerSortTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2c921344d6201645adf7e4d01fa12888f3186792
--- /dev/null
+++ b/tests/src/Kernel/ConfigNormalizerSortTest.php
@@ -0,0 +1,149 @@
+<?php
+
+namespace Drupal\Tests\config_normalizer\Kernel;
+
+use Symfony\Component\Yaml\Yaml;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests sorting configuration.
+ *
+ * @group config_normalizer
+ */
+class ConfigNormalizerSortTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'system',
+    'user',
+    'node',
+    'views',
+    'field',
+    'filter',
+    'text',
+    'media',
+    'image',
+    'file',
+    'menu_link_content',
+    'block',
+    'block_content',
+    'layout_builder',
+    'config_normalizer',
+  ];
+
+  /**
+   * The configuration sorter service.
+   *
+   * @var \Drupal\config_normalizer\Config\ConfigSorter
+   */
+  protected $configSorter;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('media');
+    $this->installEntitySchema('file');
+    $this->installEntitySchema('block_content');
+
+    $this->installConfig([
+      'system', 'node', 'views', 'image', 'media', 'text',
+      'user', 'filter', 'block_content', 'layout_builder',
+    ]);
+
+    // Explicitly copy fixtures to sync storage:
+    foreach ([
+      'core.entity_view_display.node.article.default',
+      'views.view.recipes',
+    ] as $config_name) {
+      $this->copyFixtureToSyncStorage($config_name);
+      $data = $this->container->get('config.storage.sync')->read($config_name);
+      $this->config($config_name)->setData($data)->save(TRUE);
+    }
+    // Inject sorter properly after container rebuild:
+    $this->configSorter = $this->container->get('config_normalizer.config_sorter');
+
+    // Ensure container is properly built (critical step):
+    $this->container->get('kernel')->rebuildContainer();
+
+  }
+
+  /**
+   * Tests that configuration is normalized in a consistent manner.
+   *
+   * This ensures that configuration arrays are always sorted the same way,
+   * regardless of the original order in which they were defined or exported.
+   * The test loads known configuration from the Umami profile, shuffles its
+   * keys, and then verifies that sorting restores it to the expected order.
+   */
+  public function testUmamiConfigurationSorting(): void {
+    $config_names = [
+      'views.view.recipes',
+      'core.entity_view_display.node.article.default',
+    ];
+
+    foreach ($config_names as $config_name) {
+      // Retrieve the original configuration data.
+      $original = $this->config($config_name)->getRawData();
+      // Apply the sorting mechanism to the original data.
+      $sorted_original = $this->configSorter->sort($config_name, $original);
+
+      // Shuffle the configuration data to simulate disorder.
+      $shuffled = $this->shuffleAssocArray($original);
+      // Apply the sorting mechanism to the shuffled data.
+      $sorted_shuffled = $this->configSorter->sort($config_name, $shuffled);
+
+      // Assert shuffled data is not equal to the original.
+      $this->assertEquals(
+        $sorted_original,
+        $sorted_shuffled,
+        sprintf('The sorted shuffled version and sorted original of "%s" are not equal.', $config_name)
+      );
+
+      // The assertSame method is more strict than assertEqual,
+      // ensuring both type and value match.
+      $this->assertSame(
+        $sorted_original,
+        $sorted_shuffled,
+          sprintf('The sorted shuffled version and sorted original of "%s" are not the same.', $config_name)
+      );
+
+    }
+  }
+
+  /**
+   * Helper to shuffle associative arrays.
+   */
+  protected function shuffleAssocArray(array $array): array {
+    $keys = array_keys($array);
+    shuffle($keys);
+    $shuffled = [];
+    foreach ($keys as $key) {
+      $shuffled[$key] = is_array($array[$key]) ? $this->shuffleAssocArray($array[$key]) : $array[$key];
+    }
+    return $shuffled;
+  }
+
+  /**
+   * Copy fixture to sync storage.
+   */
+  protected function copyFixtureToSyncStorage(string $config_name): void {
+    $module_path = $this->container->get('extension.list.module')->getPath('config_normalizer');
+    $source = DRUPAL_ROOT . "/$module_path/tests/fixtures/config/install/$config_name.yml";
+
+    if (!file_exists($source)) {
+      $this->fail("Fixture file not found: $source");
+    }
+
+    $data = Yaml::parseFile($source);
+    $sync_storage = $this->container->get('config.storage.sync');
+    $sync_storage->write($config_name, $data);
+  }
+
+}