diff --git a/.cspell-project-words.txt b/.cspell-project-words.txt
new file mode 100644
index 0000000000000000000000000000000000000000..14757431eff852c934eb01f6420200d40a177969
--- /dev/null
+++ b/.cspell-project-words.txt
@@ -0,0 +1,7 @@
+hotp
+totp
+Authy
+ciphertext
+chillerlan
+OTPHP
+spomky
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ad49485f5ab295b389624ca3fa4ec309f55c06f0..47c6b2d4d26b91d828e62b8e69e20fa9a8fb62d0 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -36,6 +36,9 @@ variables:
   # Generate a new phpstan baseline.
   GENERATE_PHPSTAN_BASELINE:
     value: "0"
+  # cSpell ignore files.
+  _CSPELL_IGNORE_PATHS:
+    value: 'docs/css/*'
 
 ################
 # Customize composer stage to not symlink the module as it interferes with
diff --git a/README.md b/README.md
index 0ca3df1abf4eb9fbf457c389cb6243f3e96e767b..2001a4e6ddb3134125373139a732ffdb87a60171 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ integrations with third-party suppliers like Authy, Duo and others.
 [Project Page](https://www.drupal.org/project/tfa)  
 [Issue Tracker](https://www.drupal.org/project/issues/tfa)  
 [Online Documentation](https://project.pages.drupalcode.org/tfa/)  
-<!-- This documentation is also avaliable in the docs/ folder -->
+<!-- This documentation is also available in the docs/ folder -->
 
 ## Requirements
 
@@ -40,7 +40,7 @@ to log in.
 
 ### Getting started
 
-Pleass see [Getting started](https://project.pages.drupalcode.org/tfa/getting-started/)
+See [Getting started](https://project.pages.drupalcode.org/tfa/getting-started/)
 for a guide on setting up TFA.
 
 ## Testing and development with TFA enabled
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 3310e5f1a536a07a37bec05611eaedb6764dcd35..160b068ab48aa798618614edcb885a78a45583fa 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -3,7 +3,7 @@
 This module requires a few dependencies to be setup before it can be configured.
 
 The following is intended as a "Quick Start" guide. You should review all
-options prior to deployin in produciton.
+options prior to deploying in production.
 
 Note: Any changes to the Encryption Method or Encrypt Key after initial
 configuration will place TFA in an undefined state. There is no encryption
@@ -13,15 +13,15 @@ encryption method or key is changed.
 ## Encryption method - [Real AES](https://www.drupal.org/project/real_aes)
 
 An encryption method module is required to be able to use the Key and Encrypt
-modules. Several encryption plugins are avalible, Real AES is not the only
+modules. Several encryption plugins are available, Real AES is not the only
 method available. For more options please see the
 [Encrypt Project Page](https://www.drupal.org/project/encrypt) or
-[Encrypt Ecosytem List](https://www.drupal.org/project/encrypt/ecosystem).
+[Encrypt Ecosystem List](https://www.drupal.org/project/encrypt/ecosystem).
 
 ## Install Key, Encrypt, and the Encryption method plugin
 
 Before proceeding to the next steps install Key, Encrypt, and your chosen
-Encrption plugin according to their instructions. With a composer install of
+Encryption plugin according to their instructions. With a composer install of
 TFA these modules should already be download to your contrib module directory
 and just need to be installed/enabled inside of Drupal.
 
@@ -77,7 +77,7 @@ Now you should be ready to configure the TFA module.
     * Encryption Profile: Select the Encryption Profile you created in the
       previous step.
     * Adjust other settings as desired.
-    * Consider slecting "Roles required to set up TFA" for some roles,
+    * Consider selecting "Roles required to set up TFA" for some roles,
       especially Administrator roles.
     * Save
 
diff --git a/docs/install-hardening.md b/docs/install-hardening.md
index 1c62ba015640842a3d1af4d4ed39e601462b35fb..c097e3c573f53de8d3b00b180197b322a502ef1f 100644
--- a/docs/install-hardening.md
+++ b/docs/install-hardening.md
@@ -1,11 +1,11 @@
 # Install hardening
 
-## Remove unnecesssary files
-Uneecssary files may be removed in order to reduce the amount of information
-avaliable to attackers regarding the version of TFA deployed.
+## Remove unnecessary files
+Unnecessary files may be removed in order to reduce the amount of information
+available to attackers regarding the version of TFA deployed.
 
 The following paths are safe to remove:
-
+<!-- cSpell:disable -->
 ```
 docs/**
 tests/**
@@ -17,6 +17,8 @@ mkdocs.yml
 phpstan*
 README.md
 ```
+<!-- cSpell:enable -->
+
 
 Using the
 [Drupal Vendor Hardening Composer Plugin](https://www.drupal.org/docs/develop/using-composer/using-drupals-vendor-hardening-composer-pluging)
diff --git a/drush.services.yml b/drush.services.yml
index 6882885ba2f94de2df561b8f926b54283654aff1..ae12401fbf5c5c60ef9ea9373eba1c2dbab1acb8 100644
--- a/drush.services.yml
+++ b/drush.services.yml
@@ -1,5 +1,5 @@
 services:
-  tfa.drush.token_managment:
+  tfa.drush.token_management:
     class: \Drupal\tfa\Commands\TfaTokenManagement
     arguments:
       - '@plugin.manager.mail'
@@ -10,6 +10,6 @@ services:
     class: \Drupal\tfa\Commands\TfaCommands
     arguments:
       - '@database'
-      - '@tfa.drush.token_managment'
+      - '@tfa.drush.token_management'
     tags:
       - { name: drush.command }
diff --git a/mkdocs.yml b/mkdocs.yml
index b0f9fb131e042326d9212cc0e74a257794e7b39c..7dccc04d87391ff33a2be9b3a68774a545c64f15 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,4 +1,5 @@
 site_name: TFA 2.x
+# cSpell:disable
 theme:
   name: material
   features:
diff --git a/src/Commands/TfaCommands.php b/src/Commands/TfaCommands.php
index 083ea515c737229b3340f3b81fcc890432fee0c4..ff7ff8eb59dbddee5e4e058c0c929c5a26014847 100644
--- a/src/Commands/TfaCommands.php
+++ b/src/Commands/TfaCommands.php
@@ -23,7 +23,7 @@ final class TfaCommands extends DrushCommands implements SanitizePluginInterface
   protected Connection $database;
 
   /**
-   * TokenManagment service.
+   * TokenManagement service.
    *
    * @var \Drupal\tfa\Commands\TfaTokenManagement
    */
diff --git a/src/Commands/TfaTokenManagement.php b/src/Commands/TfaTokenManagement.php
index 5097bfa2a6284ce1d1cddddc351e4860eecf3d52..0a29d736f84f61cc278f5c97ffdcf32c1e6e01f7 100644
--- a/src/Commands/TfaTokenManagement.php
+++ b/src/Commands/TfaTokenManagement.php
@@ -105,7 +105,7 @@ final class TfaTokenManagement {
       ]
     );
 
-    // E-mail account to inform user that it has been disabled.
+    // Email account to inform user that it has been disabled.
     $params = ['account' => $account];
     if (!empty($email)) {
       $this->mailManager->mail('tfa', 'tfa_disabled_configuration', $email, $account->getPreferredLangcode(), $params);
diff --git a/src/Form/EntryForm.php b/src/Form/EntryForm.php
index b28d38230faf6817e273cdb3a0bd08df8a2936a1..6e5da3cee281e245ae268f896f4875483283eed2 100644
--- a/src/Form/EntryForm.php
+++ b/src/Form/EntryForm.php
@@ -108,7 +108,7 @@ final class EntryForm extends FormBase {
    * @param \Drupal\Core\Lock\LockBackendInterface $lock
    *   The lock service.
    * @param \Drupal\Core\Cache\CacheBackendInterface $memoryCache
-   *   The tfa memorry cache service.
+   *   The tfa memory cache service.
    */
   public function __construct(TfaPluginManager $tfa_plugin_manager, UserFloodControlInterface $user_flood_control, DateFormatterInterface $date_formatter, UserDataInterface $user_data, UserStorageInterface $user_storage, LockBackendInterface $lock, protected CacheBackendInterface $memoryCache) {
     $this->tfaPluginManager = $tfa_plugin_manager;
diff --git a/src/Form/TfaDisableForm.php b/src/Form/TfaDisableForm.php
index fe04e4902ea00433d02815a9e2b398d77e0d07de..f39be14d9349be993c7348674f13846617df824a 100644
--- a/src/Form/TfaDisableForm.php
+++ b/src/Form/TfaDisableForm.php
@@ -178,7 +178,7 @@ final class TfaDisableForm extends FormBase {
       '@uid' => $account->id(),
     ]);
 
-    // E-mail account to inform user that it has been disabled.
+    // Email account to inform user that it has been disabled.
     if ($account->getEmail()) {
       $params = ['account' => $account];
       $this->mailManager->mail('tfa', 'tfa_disabled_configuration', $account->getEmail(), $account->getPreferredLangcode(), $params);
diff --git a/src/Plugin/EncryptionMethod/McryptAES128Encryption.php b/src/Plugin/EncryptionMethod/McryptAES128Encryption.php
index b66cd8c5549229e3bad8f18028f401a2554f9dcb..eb9b120087eb893e903677ac1b469bbbc5bb8bd8 100644
--- a/src/Plugin/EncryptionMethod/McryptAES128Encryption.php
+++ b/src/Plugin/EncryptionMethod/McryptAES128Encryption.php
@@ -22,6 +22,7 @@ use Drupal\encrypt\Plugin\EncryptionMethod\EncryptionMethodBase;
  * )
  *
  * phpcs:disable PHPCompatibility
+ * cSpell:ignore RIJNDAEL
  */
 class McryptAES128Encryption extends EncryptionMethodBase implements EncryptionMethodInterface {
   use StringTranslationTrait;
diff --git a/src/Plugin/Tfa/TfaHotp.php b/src/Plugin/Tfa/TfaHotp.php
index 5df67eebeffabf71091458f0cf17ae75801741f4..e8fa07ffe3cc1c8369e0d84d7ebe00a3769c3c0f 100644
--- a/src/Plugin/Tfa/TfaHotp.php
+++ b/src/Plugin/Tfa/TfaHotp.php
@@ -460,6 +460,7 @@ final class TfaHotp extends TfaBasePlugin implements TfaValidationInterface, Tfa
         '#tag' => 'style',
         '#value' => ".tfa-qr-code { width:200px }",
       ],
+      // cSpell:disable-next-line qrcode
       'qrcode-css',
     ];
 
@@ -501,7 +502,7 @@ final class TfaHotp extends TfaBasePlugin implements TfaValidationInterface, Tfa
   }
 
   /**
-   * Get a base64 qrcode image uri of seed.
+   * Get a base64 QR code image uri of seed.
    *
    * @return string
    *   QR-code uri.
diff --git a/src/Plugin/Tfa/TfaTotp.php b/src/Plugin/Tfa/TfaTotp.php
index 5baa192f537bda4681b6bab5c491baec0055b509..99aa1ee800acd49fda669eba688e2a1de04131da 100644
--- a/src/Plugin/Tfa/TfaTotp.php
+++ b/src/Plugin/Tfa/TfaTotp.php
@@ -472,6 +472,7 @@ final class TfaTotp extends TfaBasePlugin implements TfaValidationInterface, Tfa
         '#tag' => 'style',
         '#value' => ".tfa-qr-code { width:200px }",
       ],
+      // cSpell:disable-next-line qrcode
       'qrcode-css',
     ];
 
@@ -513,7 +514,7 @@ final class TfaTotp extends TfaBasePlugin implements TfaValidationInterface, Tfa
   }
 
   /**
-   * Get a base64 qrcode image uri of seed.
+   * Get a base64 QR code image uri of seed.
    *
    * @return string
    *   QR-code uri.
diff --git a/src/Plugin/TfaValidationInterface.php b/src/Plugin/TfaValidationInterface.php
index e9bdca49c1dcdf1421e67f5beb244d74e5534352..c9a3afef17e6bc2d9fc0b6d8f02091c8fec56a37 100644
--- a/src/Plugin/TfaValidationInterface.php
+++ b/src/Plugin/TfaValidationInterface.php
@@ -67,7 +67,7 @@ interface TfaValidationInterface {
    *
    * @return int<0, max>
    *   This may be the expected length of the token based on internal
-   *   knowledge or may be determined by analysing the submitted password.
+   *   knowledge or may be determined by analyzing the submitted password.
    *   A 0 may be returned if no token matching an expected format can be
    *   found or if another error occurs during the process.
    */
diff --git a/src/TfaRandomTrait.php b/src/TfaRandomTrait.php
index 420089f39e006ec0efd17fa8ddf634e7fcf06ec6..1585c0c4f482bb78ad81214edea26b4db9d250ab 100644
--- a/src/TfaRandomTrait.php
+++ b/src/TfaRandomTrait.php
@@ -8,6 +8,8 @@ namespace Drupal\tfa;
  * @package Drupal\tfa
  *
  * @api
+ *
+ * cSpell:ignore abcdefghijkmnopqrstuvwxyz ABCDEFGHJKLMNPQRSTUVWXYZ
  */
 trait TfaRandomTrait {
 
diff --git a/tests/src/Functional/TfaTestBase.php b/tests/src/Functional/TfaTestBase.php
index 259eebb30cf9c4dd50534cb83e2593337dae53a2..09bb93365657a87b70491c15dcaaf660302de607 100644
--- a/tests/src/Functional/TfaTestBase.php
+++ b/tests/src/Functional/TfaTestBase.php
@@ -70,6 +70,7 @@ abstract class TfaTestBase extends BrowserTestBase {
       'key_type' => 'encryption',
       'key_type_settings' => ['key_size' => '128'],
       'key_provider' => 'config',
+      // cSpell:disable-next-line mustbesixteenbit
       'key_provider_settings' => ['key_value' => 'mustbesixteenbit'],
     ]);
     $key->save();
diff --git a/tests/src/Unit/Drush/TfaTokenManagementTest.php b/tests/src/Unit/Drush/TfaTokenManagementTest.php
index 5ae861b6ce3136a0d2a328c92ca1851b59381f2c..43478cb83d3c23bc1d3ab1b45da3c4065dc9dcb5 100644
--- a/tests/src/Unit/Drush/TfaTokenManagementTest.php
+++ b/tests/src/Unit/Drush/TfaTokenManagementTest.php
@@ -107,7 +107,7 @@ final class TfaTokenManagementTest extends UnitTestCase {
   }
 
   /**
-   * Generator for the tesetResetUserTfaData().
+   * Generator for testResetUserTfaData().
    */
   public static function providerTestResetUserTfaData(): \Generator {
     yield 'Successful reset by username' => [
diff --git a/tests/src/Unit/EventSubscriber/TfaUserSetSubscriberTest.php b/tests/src/Unit/EventSubscriber/TfaUserSetSubscriberTest.php
index 72ac79b65233cf000ab762c01538cbe70e6bfad0..51065118e2a9e1ed96b8b5c0541628d8c405d417 100644
--- a/tests/src/Unit/EventSubscriber/TfaUserSetSubscriberTest.php
+++ b/tests/src/Unit/EventSubscriber/TfaUserSetSubscriberTest.php
@@ -160,7 +160,7 @@ class TfaUserSetSubscriberTest extends UnitTestCase {
   /**
    * Test that the event handler is subscribed.
    */
-  public function testSubscribedEventsHandeling(): void {
+  public function testSubscribedEventsHandling(): void {
     $events = TfaUserSetSubscriber::getSubscribedEvents();
     $this->assertArrayHasKey(AccountEvents::SET_USER, $events);
     $this->assertIsArray($events[AccountEvents::SET_USER]);
@@ -463,7 +463,7 @@ class TfaUserSetSubscriberTest extends UnitTestCase {
   }
 
   /**
-   * Tests the Exceptiosn event handler for TfaAccessDenied()
+   * Tests the Exception event handler for TfaAccessDenied()
    *
    * @dataProvider providerTestOnException
    */
diff --git a/tests/src/Unit/Plugin/Tfa/TfaHotpTest.php b/tests/src/Unit/Plugin/Tfa/TfaHotpTest.php
index 18f1d4954db03d1cf1cec8231f4e28205b7c7fe8..d347f6a40c4df0c28a6e11730462127accce44f8 100644
--- a/tests/src/Unit/Plugin/Tfa/TfaHotpTest.php
+++ b/tests/src/Unit/Plugin/Tfa/TfaHotpTest.php
@@ -85,6 +85,7 @@ final class TfaHotpTest extends UnitTestCase {
   /**
    * Seed to be used in tests.
    */
+  // cSpell:disable-next-line
   const SEED = 'ACCZUIQHH4QARV3IYLXQGCEI4NX6BVYRMJVDMMAAX3ILECU4WW6UKBDVDX7N5OQU2WWFRNN2XOH4RYEI3RZVGCB7RO7VHM3GT53GEDQ';
 
   /**
@@ -350,6 +351,7 @@ final class TfaHotpTest extends UnitTestCase {
           [
             ['tfa', 3, 'tfa_hotp_seed', ['seed' => base64_encode(self::SEED)]],
             ['tfa', 3, 'tfa_hotp_counter', (string) self::NEXT_COUNTER],
+            // cSpell:disable-next-line
             ['tfa', 3, 'tfa_accepted_code_2Mg5OyxhHxNGcz-tNhN_BpBsVg_yAGE_irXrQU0_H3A', (string) self::NEXT_COUNTER],
           ]
         );
@@ -362,6 +364,7 @@ final class TfaHotpTest extends UnitTestCase {
       'setup' => function (self $context) {
         $context->replaceUserDataMock(
           [
+            // cSpell:disable-next-line
             ['tfa', 3, 'tfa_hotp_seed', ['seed' => base64_encode('YPW44GO532UJLCPQ')]],
             ['tfa', 3, 'tfa_hotp_counter', (string) self::NEXT_COUNTER],
           ]
diff --git a/tests/src/Unit/Plugin/Tfa/TfaTotpTest.php b/tests/src/Unit/Plugin/Tfa/TfaTotpTest.php
index cb288f73d5b50f954dc348980d15ad009f0833ad..9a0a15b7e729472f6e8752a17f75f43248bf1c74 100644
--- a/tests/src/Unit/Plugin/Tfa/TfaTotpTest.php
+++ b/tests/src/Unit/Plugin/Tfa/TfaTotpTest.php
@@ -85,10 +85,10 @@ final class TfaTotpTest extends UnitTestCase {
   /**
    * Seed to be used in tests.
    */
+  // cSpell:disable-next-line
   const SEED = 'ACCZUIQHH4QARV3IYLXQGCEI4NX6BVYRMJVDMMAAX3ILECU4WW6UKBDVDX7N5OQU2WWFRNN2XOH4RYEI3RZVGCB7RO7VHM3GT53GEDQ';
-
   /**
-   * Time to simulate request occured.
+   * Time to simulate request occurred.
    */
   const SIMULATED_REQUEST_TIME = 1600000000;
 
@@ -337,7 +337,7 @@ final class TfaTotpTest extends UnitTestCase {
       'expected_time_window' => 53333330,
     ];
 
-    yield 'Current token is older than last timeslice.' => [
+    yield 'Current token is older than last time slice.' => [
       'expected_result' => FALSE,
       'submitted_code' => TOTP::createFromSecret(self::SEED)->at(self::SIMULATED_REQUEST_TIME),
       'setup' => function (self $context) {
@@ -350,7 +350,7 @@ final class TfaTotpTest extends UnitTestCase {
       },
     ];
 
-    yield 'Current token is same age as last timeslice.' => [
+    yield 'Current token is same age as last time slice.' => [
       'expected_result' => FALSE,
       'submitted_code' => TOTP::createFromSecret(self::SEED)->now(),
       'setup' => function (self $context) {
@@ -414,6 +414,7 @@ final class TfaTotpTest extends UnitTestCase {
             [
               'tfa',
               3,
+              // cSpell:disable-next-line
               'tfa_accepted_code_JPOGOpgcoSQNvVq--07anlcdCNGgSk5-amAnos3XW5g',
               (string) self::SIMULATED_REQUEST_TIME,
             ],
@@ -428,6 +429,7 @@ final class TfaTotpTest extends UnitTestCase {
       'setup' => function (self $context) {
         $context->replaceUserDataMock(
           [
+            // cSpell:disable-next-line
             ['tfa', 3, 'tfa_totp_seed', ['seed' => base64_encode('YPW44GO532UJLCPQ')]],
             ['tfa', 3, 'tfa_totp_time_window', (string) (floor(self::SIMULATED_REQUEST_TIME / 30) - 10)],
           ]
diff --git a/tests/src/Unit/TfaUserAuthTest.php b/tests/src/Unit/TfaUserAuthTest.php
index ed3e38401d6fefb7abc6646cb8f32dbf2f7c60a7..d9663dc0e40b3341a87fefac05d310517614c7db 100644
--- a/tests/src/Unit/TfaUserAuthTest.php
+++ b/tests/src/Unit/TfaUserAuthTest.php
@@ -27,6 +27,8 @@ use PHPUnit\Framework\MockObject\Rule\InvokedCount;
  * @covers  \Drupal\tfa\TfaUserAuth
  *
  * @group tfa
+ *
+ * cSpell:ignore abcxyz
  */
 class TfaUserAuthTest extends UnitTestCase {
 
@@ -537,7 +539,7 @@ class TfaUserAuthTest extends UnitTestCase {
    *
    * @dataProvider providerBypass
    */
-  public function testBypass(int|false $expected_result, InvokedCount $validate_reqeust_constrant, InvokedCount $set_force_logout_constraint, array $callback_match, string $expected_password, int|false $inner_result, \stdClass|null $bypass_result): void {
+  public function testBypass(int|false $expected_result, InvokedCount $validate_request_constraint, InvokedCount $set_force_logout_constraint, array $callback_match, string $expected_password, int|false $inner_result, \stdClass|null $bypass_result): void {
 
     $this->loginContextMock->method('isTfaDisabled')->willReturn(FALSE);
     $this->loginContextMock->method('isReady')->willReturn(TRUE);
@@ -545,7 +547,7 @@ class TfaUserAuthTest extends UnitTestCase {
     $this->innerUserAuthMock->method('authenticate')->with('tfa_user', $expected_password)->willReturn($inner_result);
     $this->loginContextMock->expects($this->never())->method('hasSkipped');
     $this->validationPluginMock->method('ready')->willReturn(TRUE);
-    $this->validationPluginMock->expects($validate_reqeust_constrant)->method('validateRequest')->with('123456')->willReturn(TRUE);
+    $this->validationPluginMock->expects($validate_request_constraint)->method('validateRequest')->with('123456')->willReturn(TRUE);
 
     $callback_list = [];
     $this->memoryCacheMock