diff --git a/src/Hook/ViteReactGeneratorHooks.php b/src/Hook/ViteReactGeneratorHooks.php
new file mode 100644
index 0000000..e96112c
--- /dev/null
+++ b/src/Hook/ViteReactGeneratorHooks.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Drupal\vite_react_generator\Hook;
+
+use Drupal\Component\Utility\Html;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+
+/**
+ * Hook implementations for vite_react_generator.
+ */
+class ViteReactGeneratorHooks {
+
+  /**
+   * Implements hook_help().
+   */
+  #[Hook('help')]
+  public function help($route_name, RouteMatchInterface $route_match) {
+    if ($route_name == 'help.page.vite_react_generator') {
+      $text = file_get_contents(__DIR__ . '/README.md');
+      if (!\Drupal::moduleHandler()->moduleExists('markdown')) {
+        return '<pre>' . Html::escape($text) . '</pre>';
+      }
+      else {
+        // Use the Markdown filter to render the README.
+        $filter_manager = \Drupal::service('plugin.manager.filter');
+        $settings = \Drupal::configFactory()->get('markdown.settings')->getRawData();
+        $config = [
+          'settings' => $settings,
+        ];
+        $filter = $filter_manager->createInstance('markdown', $config);
+        return $filter->process($text, 'en');
+      }
+    }
+    return '';
+  }
+
+}
diff --git a/tests/src/Functional/_swc_testing/foo.info.yml b/tests/src/Functional/_swc_testing/foo.info.yml
index 77c2f15..29ee720 100644
--- a/tests/src/Functional/_swc_testing/foo.info.yml
+++ b/tests/src/Functional/_swc_testing/foo.info.yml
@@ -2,6 +2,6 @@ name: Foo
 type: module
 description: '@todo Add description.'
 package: '@todo Add package'
-core_version_requirement: '^10 || ^11'
+core_version_requirement: ^10.1 || ^11 || ^12
 'interface translation project': foo
 'interface translation server pattern': modules/foo/translations/foo.%language.po
diff --git a/tests/src/Unit/ComponentNameTest.php b/tests/src/Unit/ComponentNameTest.php
index c2aea28..25be9ef 100644
--- a/tests/src/Unit/ComponentNameTest.php
+++ b/tests/src/Unit/ComponentNameTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\vite_react_generator\Unit;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\DataProvider;
 use Drupal\vite_react_generator\Drush\Generators\Validator\ComponentName;
 use PHPUnit\Framework\TestCase;
 
@@ -10,6 +12,7 @@ use PHPUnit\Framework\TestCase;
  *
  * @group vite_react_generator
  */
+#[Group('vite_react_generator')]
 final class ComponentNameTest extends TestCase {
 
   /**
@@ -17,6 +20,7 @@ final class ComponentNameTest extends TestCase {
    *
    * @dataProvider dataProvider()
    */
+  #[DataProvider('dataProvider()')]
   public function test(mixed $component_name, ?\UnexpectedValueException $exception): void {
     if ($exception) {
       $this->expectExceptionObject($exception);
@@ -30,7 +34,7 @@ final class ComponentNameTest extends TestCase {
    * @returns array
    *   The dataset for the test case.
    */
-  public function dataProvider(): array {
+  public static function dataProvider(): array {
     $exception = new \UnexpectedValueException('The value is not correct component machine name.');
     return array_reduce([
       ['snake_case_here', NULL],
diff --git a/tests/src/Unit/RequiredComponentNameTest.php b/tests/src/Unit/RequiredComponentNameTest.php
index 7e40607..1b6a281 100644
--- a/tests/src/Unit/RequiredComponentNameTest.php
+++ b/tests/src/Unit/RequiredComponentNameTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\vite_react_generator\Unit;
 
+use PHPUnit\Framework\Attributes\Group;
+use PHPUnit\Framework\Attributes\DataProvider;
 use Drupal\vite_react_generator\Drush\Generators\Validator\RequiredComponentName;
 use PHPUnit\Framework\TestCase;
 
@@ -10,6 +12,7 @@ use PHPUnit\Framework\TestCase;
  *
  * @group vite_react_generator
  */
+#[Group('vite_react_generator')]
 final class RequiredComponentNameTest extends TestCase {
 
   /**
@@ -17,6 +20,7 @@ final class RequiredComponentNameTest extends TestCase {
    *
    * @dataProvider dataProvider()
    */
+  #[DataProvider('dataProvider()')]
   public function test(mixed $component_name, ?\UnexpectedValueException $exception): void {
     if ($exception) {
       $this->expectExceptionObject($exception);
@@ -30,7 +34,7 @@ final class RequiredComponentNameTest extends TestCase {
    * @returns array
    *   The dataset for the test case.
    */
-  public function dataProvider(): array {
+  public static function dataProvider(): array {
     $mn_exception = new \UnexpectedValueException('The value is not correct component machine name.');
     $rq_exception = new \UnexpectedValueException('The value is required.');
     return array_reduce([
diff --git a/vite_react_generator.info.yml b/vite_react_generator.info.yml
index 6fd6b29..9e500cf 100644
--- a/vite_react_generator.info.yml
+++ b/vite_react_generator.info.yml
@@ -2,4 +2,4 @@ name: 'Vite React App Generator'
 type: module
 description: 'Generates Vite + React apps.'
 package: Development
-core_version_requirement: ^10.3 || ^11
+core_version_requirement: ^10.3 || ^11 || ^12
diff --git a/vite_react_generator.module b/vite_react_generator.module
index 49cf180..db90597 100644
--- a/vite_react_generator.module
+++ b/vite_react_generator.module
@@ -5,26 +5,14 @@
  * Hook implementations for the Vite React App Generator module.
  */
 
-use Drupal\Component\Utility\Html;
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\vite_react_generator\Hook\ViteReactGeneratorHooks;
 use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
  * Implements hook_help().
  */
+#[LegacyHook]
 function vite_react_generator_help($route_name, RouteMatchInterface $route_match) {
-  if ($route_name == 'help.page.vite_react_generator') {
-    $text = file_get_contents(__DIR__ . '/README.md');
-    if (!\Drupal::moduleHandler()->moduleExists('markdown')) {
-      return '<pre>' . Html::escape($text) . '</pre>';
-    }
-    else {
-      // Use the Markdown filter to render the README.
-      $filter_manager = \Drupal::service('plugin.manager.filter');
-      $settings = \Drupal::configFactory()->get('markdown.settings')->getRawData();
-      $config = ['settings' => $settings];
-      $filter = $filter_manager->createInstance('markdown', $config);
-      return $filter->process($text, 'en');
-    }
-  }
-  return '';
+  return \Drupal::service(ViteReactGeneratorHooks::class)->help($route_name, $route_match);
 }
diff --git a/vite_react_generator.services.yml b/vite_react_generator.services.yml
new file mode 100644
index 0000000..06c68ae
--- /dev/null
+++ b/vite_react_generator.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\vite_react_generator\Hook\ViteReactGeneratorHooks:
+    class: Drupal\vite_react_generator\Hook\ViteReactGeneratorHooks
+    autowire: true
