diff --git a/css_editor.module b/css_editor.module
index b34ac03..668b54b 100644
--- a/css_editor.module
+++ b/css_editor.module
@@ -3,7 +3,8 @@
  * @file
  * Allows users to apply customized CSS to themes.
  */
-
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\css_editor\Hook\CssEditorHooks;
 use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
@@ -11,105 +12,36 @@ use Drupal\Core\Url;
 /**
  * Implements hook_library_info_alter().
  */
-function css_editor_library_info_alter(&$libraries, $extension) {
-  $theme = \Drupal::theme()->getActiveTheme()->getName();
-  if ($extension == $theme) {
-    if ($file = _css_editor_get_stylesheet($theme)) {
-      // Append custom style sheet to theme libraries.
-      $libraries['css_editor']['css']['theme'][$file]['weight'] = 9999;
-    }
-  }
+#[LegacyHook]
+function css_editor_library_info_alter(&$libraries, $extension)
+{
+    \Drupal::service(CssEditorHooks::class)->libraryInfoAlter($libraries, $extension);
 }
 
 /**
  * Implements hook_page_attachments().
  */
-function css_editor_page_attachments(array &$page) {
-  $theme = \Drupal::theme()->getActiveTheme()->getName();
-  if (_css_editor_get_stylesheet($theme)) {
-    $page['#attached']['library'][] = $theme . '/css_editor';
-  }
+#[LegacyHook]
+function css_editor_page_attachments(array &$page)
+{
+    \Drupal::service(CssEditorHooks::class)->pageAttachments($page);
 }
 
 /**
  * Implements hook_cache_flush().
  */
+#[LegacyHook]
 function css_editor_cache_flush() {
-  // Regenerate all CSS files when cache is cleared.
-  \Drupal::service('css_editor.css_generator')->regenerateAllCssFiles();
+  \Drupal::service(CssEditorHooks::class)->cacheFlush();
 }
 
 /**
  * Implements hook_form_FORM_ID_alter() for `system_theme_settings`.
  */
-function css_editor_form_system_theme_settings_alter(&$form, FormStateInterface $form_state, $form_id) {
-  $theme = _css_editor_get_edited_theme($form_state);
-  if ($theme) {
-    $config = \Drupal::config('css_editor.theme.' . $theme);
-    // Add CSS customization fieldset.
-    $form['css_editor'] = array(
-      '#type' => 'details',
-      '#title' => t('Custom CSS'),
-      '#open' => TRUE,
-      '#tree' => TRUE,
-    );
-    // Switch to enable/disable customization.
-    $form['css_editor']['enabled'] = array(
-      '#title' => t('Enable or disable custom CSS:'),
-      '#type' => 'checkbox',
-      '#default_value' => $config->get('enabled'),
-    );
-    // Editor box.
-    $form['css_editor']['css'] = array(
-      '#type' => 'textarea',
-      '#prefix' => '<div id="css-editor-field">',
-      '#description' => t('Type or paste custom CSS code for this theme.'),
-      '#default_value' => $config->get('css'),
-      '#attributes' => array('id' => 'css-editor-textarea'),
-      '#suffix' => '</div>',
-    );
-    // Switch to enable/disable the plain text editor.
-    $form['css_editor']['plaintext_enabled'] = array(
-      '#title' => t('Use plain text editor'),
-      '#type' => 'checkbox',
-      '#default_value' => $config->get('plaintext_enabled'),
-      '#attributes' => [
-        'id' => 'edit-plaintext-enabled',
-      ],
-    );
-    // Switch to enable/disable autopreview.
-    $form['css_editor']['autopreview_enabled'] = array(
-      '#title' => t('Enable auto preview'),
-      '#type' => 'checkbox',
-      '#default_value' => $config->get('autopreview_enabled'),
-      '#attributes' => [
-        'id' => 'edit-autopreview-enabled',
-      ],
-    );
-    // Preview path.
-    $form['css_editor']['preview_path'] = array(
-      '#title' => t('Preview path:'),
-      '#type' => 'textfield',
-      '#size' => 60,
-      '#attributes' => [
-        'id' => 'edit-preview-path',
-      ],
-    );
-    // Preview box.
-    $preview_url = Url::fromRoute('<front>', array(), array('absolute' => TRUE, 'query' => array('theme' => $theme)))->toString();
-    $form['css_editor']['css_preview'] = array(
-      '#type' => 'inline_template',
-      '#template' => '<iframe src="{{ url }}" id="css-editor-preview">' . t('Frames are not supported.') . '</iframe>',
-      '#context' => array(
-        'url' => $preview_url,
-      ),
-    );
-    // Attach CSS and Javascript libraries.
-    $form['#attached']['library'][] = 'css_editor/codemirror';
-    $form['#attached']['library'][] = 'css_editor/css_editor';
-    $form['#attached']['drupalSettings']['CSSEditor']['frontPage'] = $preview_url;
-    array_unshift($form['#submit'], '_css_editor_theme_settings_form_submit');
-  }
+#[LegacyHook]
+function css_editor_form_system_theme_settings_alter(&$form, FormStateInterface $form_state, $form_id)
+{
+    \Drupal::service(CssEditorHooks::class)->formSystemThemeSettingsAlter($form, $form_state, $form_id);
 }
 
 /**
diff --git a/css_editor.services.yml b/css_editor.services.yml
index c2c2846..b042c53 100644
--- a/css_editor.services.yml
+++ b/css_editor.services.yml
@@ -11,3 +11,7 @@ services:
     class: Drupal\css_editor\Theme\CssEditorThemeNegotiator
     tags:
       - { name: theme_negotiator, priority: 100 }
+
+  Drupal\css_editor\Hook\CssEditorHooks:
+    class: Drupal\css_editor\Hook\CssEditorHooks
+    autowire: true
diff --git a/src/CssEditorService.php b/src/CssEditorService.php
index 99474e3..e9fb0d1 100644
--- a/src/CssEditorService.php
+++ b/src/CssEditorService.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\css_editor;
 
+use Drupal\Component\Utility\DeprecationHelper;
+use Drupal\Core\File\FileExists;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\File\FileSystemInterface;
 use Psr\Log\LoggerInterface;
@@ -83,7 +85,7 @@ class CssEditorService {
 
     // Save CSS data to file.
     try {
-      $this->fileSystem->saveData($css, $file, FileSystemInterface::EXISTS_REPLACE);
+      $this->fileSystem->saveData($css, $file, DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '10.3.0', fn() => FileExists::Replace, fn() => FileSystemInterface::EXISTS_REPLACE));
       $this->fileSystem->chmod($file);
 
       // Update config with file path.
diff --git a/src/Hook/CssEditorHooks.php b/src/Hook/CssEditorHooks.php
new file mode 100644
index 0000000..756a90b
--- /dev/null
+++ b/src/Hook/CssEditorHooks.php
@@ -0,0 +1,132 @@
+<?php
+
+namespace Drupal\css_editor\Hook;
+
+use Drupal\Core\File\FileSystemInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+/**
+ * Hook implementations for css_editor.
+ */
+class CssEditorHooks
+{
+    use StringTranslationTrait;
+    /**
+     * Implements hook_library_info_alter().
+     */
+    #[Hook('library_info_alter')]
+    public function libraryInfoAlter(&$libraries, $extension)
+    {
+        $theme = \Drupal::theme()->getActiveTheme()->getName();
+        if ($extension == $theme) {
+            if ($file = _css_editor_get_stylesheet($theme)) {
+                // Append custom style sheet to theme libraries.
+                $libraries['css_editor']['css']['theme'][$file]['weight'] = 9999;
+            }
+        }
+    }
+    /**
+     * Implements hook_page_attachments().
+     */
+    #[Hook('page_attachments')]
+    public function pageAttachments(array &$page)
+    {
+        $theme = \Drupal::theme()->getActiveTheme()->getName();
+        if (_css_editor_get_stylesheet($theme)) {
+            $page['#attached']['library'][] = $theme . '/css_editor';
+        }
+    }
+    /**
+     * Implements hook_cache_flush().
+     */
+    #[Hook('cache_flush')]
+    public function cacheFlush()
+    {
+        // Regenerate all CSS files when cache is cleared.
+        \Drupal::service('css_editor.css_generator')->regenerateAllCssFiles();
+    }
+    /**
+     * Implements hook_form_FORM_ID_alter() for `system_theme_settings`.
+     */
+    #[Hook('form_system_theme_settings_alter')]
+    public function formSystemThemeSettingsAlter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
+    {
+        $theme = _css_editor_get_edited_theme($form_state);
+        if ($theme) {
+            $config = \Drupal::config('css_editor.theme.' . $theme);
+            // Add CSS customization fieldset.
+            $form['css_editor'] = [
+                '#type' => 'details',
+                '#title' => $this->t('Custom CSS'),
+                '#open' => TRUE,
+                '#tree' => TRUE,
+            ];
+            // Switch to enable/disable customization.
+            $form['css_editor']['enabled'] = [
+                '#title' => $this->t('Enable or disable custom CSS:'),
+                '#type' => 'checkbox',
+                '#default_value' => $config->get('enabled'),
+            ];
+            // Editor box.
+            $form['css_editor']['css'] = [
+                '#type' => 'textarea',
+                '#prefix' => '<div id="css-editor-field">',
+                '#description' => $this->t('Type or paste custom CSS code for this theme.'),
+                '#default_value' => $config->get('css'),
+                '#attributes' => [
+                    'id' => 'css-editor-textarea',
+                ],
+                '#suffix' => '</div>',
+            ];
+            // Switch to enable/disable the plain text editor.
+            $form['css_editor']['plaintext_enabled'] = [
+                '#title' => $this->t('Use plain text editor'),
+                '#type' => 'checkbox',
+                '#default_value' => $config->get('plaintext_enabled'),
+                '#attributes' => [
+                    'id' => 'edit-plaintext-enabled',
+                ],
+            ];
+            // Switch to enable/disable autopreview.
+            $form['css_editor']['autopreview_enabled'] = [
+                '#title' => $this->t('Enable auto preview'),
+                '#type' => 'checkbox',
+                '#default_value' => $config->get('autopreview_enabled'),
+                '#attributes' => [
+                    'id' => 'edit-autopreview-enabled',
+                ],
+            ];
+            // Preview path.
+            $form['css_editor']['preview_path'] = [
+                '#title' => $this->t('Preview path:'),
+                '#type' => 'textfield',
+                '#size' => 60,
+                '#attributes' => [
+                    'id' => 'edit-preview-path',
+                ],
+            ];
+            // Preview box.
+            $preview_url = \Drupal\Core\Url::fromRoute('<front>', [
+            ], [
+                'absolute' => TRUE,
+                'query' => [
+                    'theme' => $theme,
+                ],
+            ])->toString();
+            $form['css_editor']['css_preview'] = [
+                '#type' => 'inline_template',
+                '#template' => '<iframe src="{{ url }}" id="css-editor-preview">' . $this->t('Frames are not supported.') . '</iframe>',
+                '#context' => [
+                    'url' => $preview_url,
+                ],
+            ];
+            // Attach CSS and Javascript libraries.
+            $form['#attached']['library'][] = 'css_editor/codemirror';
+            $form['#attached']['library'][] = 'css_editor/css_editor';
+            $form['#attached']['drupalSettings']['CSSEditor']['frontPage'] = $preview_url;
+            array_unshift($form['#submit'], '_css_editor_theme_settings_form_submit');
+        }
+    }
+}
