diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..9ab59b180fb670006ac910a2bc4524a1376dcea0
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,15 @@
+
+# Ignore developer files when exporting
+.gitattributes         export-ignore
+.gitignore             export-ignore
+.gitlab-ci.yml         export-ignore
+.phive                 export-ignore
+captainhook.json       export-ignore
+phpcs.xml.dist         export-ignore
+phpstan-baseline.neon  export-ignore
+phpstan.dist.neon      export-ignore
+phpunit.dist.xml       export-ignore
+tests                  export-ignore
+
+# Explicitly set file type and line endings for PHP files, improves git diff output
+*.php     text eol=lf diff=php
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 5d49cc71d98b16e2ed3cc08be94e85f83584b1e5..a708841abb3c83ea2ba84c9f3a1fb8966eea8e46 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,11 @@ tools/
 phpstan.neon
 .phpunit.result.cache
 phpunit.xml
+
+tools/
+
+phpstan.neon
+
+.phpunit.result.cache
+
+phpunit.xml
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b8d20acb6c365ad8036a7b36d47dabd876d08efa..b5a64b401e554341447c74d7cf93a89ac95a3fdb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,3 +1,17 @@
 include:
-  - project: 'quiqqer/stabilization/semantic-release'
-    file: '/ci-templates/.gitlab-ci.yml'
+  - component: dev.quiqqer.com/quiqqer/stabilization/ci-cd-components/quiqqer-package-bundle/quiqqer-package-bundle@main
+
+# Remove the entire phpunit-php8.1 block, to allow PHPUnit to run on PHP 8.1 in your pipeline
+phpunit-php8.1:
+  rules:
+    - when: never
+
+# Remove the entire phpunit-php8.2 block, to allow PHPUnit to run on PHP 8.2 in your pipeline
+phpunit-php8.2:
+  rules:
+    - when: never
+
+# Remove the entire phpunit-php8.3 block, to allow PHPUnit to run on PHP 8.3 in your pipeline
+phpunit-php8.3:
+  rules:
+    - when: never
\ No newline at end of file
diff --git a/.phive/phars.xml b/.phive/phars.xml
index a1315a09b4adad780a9c5e52f74835c708c5c7d5..f67ea918e05290132fd03421244b4f0f7085ebdf 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,4 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <phive xmlns="https://phar.io/phive">
-  <phar name="phpstan" version="^1.10.67" installed="1.10.67" location="./tools/phpstan" copy="false"/>
+  <phar name="phpstan" version="1.*" installed="1.12.13" location="./tools/phpstan" copy="false"/>
+  <phar name="phpunit" version="^10.5.20" installed="10.5.20" location="./tools/phpunit" copy="true"/>
+  <phar name="phpcs" version="^3.10.1" installed="3.10.1" location="./tools/phpcs" copy="true"/>
+  <phar name="phpcbf" version="^3.10.1" installed="3.10.1" location="./tools/phpcbf" copy="true"/>
+  <phar name="captainhook" version="^5.23.3" installed="5.23.3" location="./tools/captainhook" copy="true"/>
 </phive>
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..4a69a59b440e5beec561eca1e341509bd5a18688
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,3 @@
+# Contributing
+
+This package follows the [QUIQQER contribution guidelines](https://dev.quiqqer.com/quiqqer/stabilization/documentation/-/wikis/home).
\ No newline at end of file
diff --git a/ajax/frontend/auth/existsUnverifiedActivation.php b/ajax/frontend/auth/existsUnverifiedActivation.php
index 9ed0c26c3cd859e4282dad36f456680c6c11a4a8..4aad06829642cd799d9b55ed861ae71a167a5c86 100644
--- a/ajax/frontend/auth/existsUnverifiedActivation.php
+++ b/ajax/frontend/auth/existsUnverifiedActivation.php
@@ -4,20 +4,22 @@
  * @return string - User e-mail address
  */
 
-use QUI\FrontendUsers\ActivationVerification;
-use QUI\Verification\Verifier;
+use QUI\Verification\VerificationRepository;
 
 QUI::$Ajax->registerFunction(
     'package_quiqqer_frontend-users_ajax_frontend_auth_existsUnverifiedActivation',
     function ($userId) {
         try {
             $User = QUI::getUsers()->get($userId);
-            Verifier::getVerificationByIdentifier($User->getUUID(), ActivationVerification::getType());
+            $verificationRepository = new VerificationRepository();
+            $verification = $verificationRepository->findByIdentifier(
+                'activate-' . $User->getUUID()
+            );
         } catch (Exception) {
             return false;
         }
 
-        return $User->getAttribute('email');
+        return $verification ? $User->getAttribute('email') : false;
     },
     ['userId']
 );
diff --git a/ajax/frontend/auth/resendActivationMail.php b/ajax/frontend/auth/resendActivationMail.php
index af8fbb4971ff780dcc8242a6cb07e4c8a7084234..c49e571a27133487e6dd07e0b812f7fd62686859 100644
--- a/ajax/frontend/auth/resendActivationMail.php
+++ b/ajax/frontend/auth/resendActivationMail.php
@@ -4,12 +4,11 @@
  * This file contains package_quiqqer_frontend-users_ajax_frontend_auth_resendActivationMail
  */
 
-use QUI\FrontendUsers\ActivationVerification;
 use QUI\FrontendUsers\Handler;
 use QUI\FrontendUsers\RegistrarInterface;
 use QUI\FrontendUsers\Registrars\Email\Registrar as EmailRegistrar;
 use QUI\Utils\Security\Orthos;
-use QUI\Verification\Verifier;
+use QUI\Verification\VerificationRepository;
 
 /**
  * Resend an activation mail
@@ -21,9 +20,16 @@
     function ($email) {
         try {
             $User = QUI::getUsers()->getUserByMail(Orthos::clear($email));
-            Verifier::getVerificationByIdentifier($User->getUUID(), ActivationVerification::getType());
-        } catch (Exception $Exception) {
+            $verificationRepository = new VerificationRepository();
+            $verification = $verificationRepository->findByIdentifier(
+                'activate-' . $User->getUUID()
+            );
+
             // if the verification does not exist -> do not resend mail
+            if (empty($verification)) {
+                return false;
+            }
+        } catch (Exception $Exception) {
             QUI\System\Log::writeException($Exception);
             return false;
         }
diff --git a/ajax/frontend/profile/address/getDelete.php b/ajax/frontend/profile/address/getDelete.php
new file mode 100644
index 0000000000000000000000000000000000000000..c5d1e9ea352c87e2e2535d7a891afeb8c3b7fac0
--- /dev/null
+++ b/ajax/frontend/profile/address/getDelete.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * This file contains package_quiqqer_invoice_ajax_frontend_address_getDelete
+ */
+
+/**
+ *
+ * @param int $addressId
+ * @return string
+ */
+QUI::$Ajax->registerFunction(
+    'package_quiqqer_frontend-users_ajax_frontend_profile_address_getDelete',
+    function ($addressId) {
+        $_REQUEST['delete'] = $addressId;
+        $Address = new QUI\FrontendUsers\Controls\Address\Address();
+
+        return QUI\ControlUtils::parse($Address);
+    },
+    ['addressId'],
+    ['Permission::checkUser']
+);
diff --git a/ajax/frontend/profile/save.php b/ajax/frontend/profile/save.php
index 010fab69bd8d4bb6058b4a0214e9d25577b4dfd0..2297123161e8387335037c92d9d2324d2f45850d 100644
--- a/ajax/frontend/profile/save.php
+++ b/ajax/frontend/profile/save.php
@@ -21,14 +21,18 @@ function ($category, $settings, $data) {
 
         // Check permission
         if (!Utils::hasPermissionToViewCategory($category, $settings)) {
-            throw new \QUI\FrontendUsers\Exception(
+            throw new \QUI\FrontendUsers\Exception([
                 'quiqqer/frontend-users',
                 'exception.ajax.frontend.profile.save.no_category_permission'
-            );
+            ]);
         }
 
         $Control = QUI\FrontendUsers\Utils::getProfileSettingControl($category, $settings);
-        $Control->setAttribute('User', QUI::getUserBySession());
+
+        if (method_exists($Control, 'setAttribute')) {
+            $Control->setAttribute('User', QUI::getUserBySession());
+        }
+
         $Control->onSave();
     },
     ['category', 'settings', 'data'],
diff --git a/ajax/settings/getAuthenticators.php b/ajax/settings/getAuthenticators.php
index 3ad5648a6cf4fa8abd581fbc3ada95bdab172c22..24d78c6d898ba2019db947d564e3309290e195a9 100644
--- a/ajax/settings/getAuthenticators.php
+++ b/ajax/settings/getAuthenticators.php
@@ -6,14 +6,11 @@
  * @return array
  */
 
-use QUI\FrontendUsers\AbstractRegistrar;
-
 QUI::$Ajax->registerFunction(
     'package_quiqqer_frontend-users_ajax_settings_getAuthenticators',
     function () {
         $authenticators = [];
 
-        /** @var AbstractRegistrar $Registrar */
         foreach (QUI\Users\Auth\Handler::getInstance()->getAvailableAuthenticators() as $class) {
             /** @var QUI\Users\AbstractAuthenticator $Authenticator */
             $Authenticator = new $class();
diff --git a/bin/controls/settings/Registrars.Entry.html b/bin/controls/settings/Registrars.Entry.html
index 3505e6294bd474b549297404e3f1443968c1d3a5..a51cac9431a4aec49191f4c8d647583d7057ee85 100644
--- a/bin/controls/settings/Registrars.Entry.html
+++ b/bin/controls/settings/Registrars.Entry.html
@@ -33,6 +33,7 @@
                             class="field-container-field quiqqer-frontendusers-settings-registrars-setting">
                         <option value="mail">{{activationModeOptionMail}}</option>
                         <option value="auto">{{activationModeOptionAuto}}</option>
+                        <option value="autoWithEmailConfirm">{{activationModeOptionAutoWithEmailConfirm}}</option>
                         <option value="manual">{{activationModeOptionManual}}</option>
                     </select>
                 </label>
diff --git a/bin/controls/settings/Registrars.js b/bin/controls/settings/Registrars.js
index c665f951c969d7bfdd1034e7044d9c1f76e1a850..0192065a3438e21b87837d9c2fb8a48cb25a4782 100644
--- a/bin/controls/settings/Registrars.js
+++ b/bin/controls/settings/Registrars.js
@@ -19,7 +19,7 @@ define('package/quiqqer/frontend-users/bin/controls/settings/Registrars', [
     'css!package/quiqqer/frontend-users/bin/controls/settings/Registrars.css'
 
 ], function (QUI, QUIControl, QUILoader, QUIFormUtils, QUILocale, QUIAjax,
-             Mustache, entryTemplate) {
+    Mustache, entryTemplate) {
     "use strict";
 
     var lg = 'quiqqer/frontend-users';
@@ -82,14 +82,15 @@ define('package/quiqqer/frontend-users/bin/controls/settings/Registrars', [
                         'class'         : 'quiqqer-frontendusers-settings-registrars-entry',
                         'data-registrar': Registrar.type,
                         html            : Mustache.render(entryTemplate, {
-                            title                     : Registrar.title,
-                            description               : Registrar.description,
-                            labelActivationMode       : QUILocale.get(lg, lgPrefix + 'labelActivationMode'),
-                            activationModeOptionMail  : QUILocale.get(lg, lgPrefix + 'activationModeOptionMail'),
-                            activationModeOptionAuto  : QUILocale.get(lg, lgPrefix + 'activationModeOptionAuto'),
-                            activationModeOptionManual: QUILocale.get(lg, lgPrefix + 'activationModeOptionManual'),
-                            labelActive               : QUILocale.get(lg, lgPrefix + 'labelActive'),
-                            labelDisplayPosition      : QUILocale.get(lg, lgPrefix + 'labelDisplayPosition')
+                            title                                   : Registrar.title,
+                            description                             : Registrar.description,
+                            labelActivationMode                     : QUILocale.get(lg, lgPrefix + 'labelActivationMode'),
+                            activationModeOptionMail                : QUILocale.get(lg, lgPrefix + 'activationModeOptionMail'),
+                            activationModeOptionAuto                : QUILocale.get(lg, lgPrefix + 'activationModeOptionAuto'),
+                            activationModeOptionAutoWithEmailConfirm: QUILocale.get(lg, lgPrefix + 'activationModeOptionAutoWithEmailConfirm'),
+                            activationModeOptionManual              : QUILocale.get(lg, lgPrefix + 'activationModeOptionManual'),
+                            labelActive                             : QUILocale.get(lg, lgPrefix + 'labelActive'),
+                            labelDisplayPosition                    : QUILocale.get(lg, lgPrefix + 'labelDisplayPosition')
                         })
                     }).inject(self.$Content);
 
diff --git a/bin/frontend/controls/Registration.js b/bin/frontend/controls/Registration.js
index 5969e3100f8fbde592f8d7ada2b3f18a4569a40f..07553c5f68b1cbe83f29c52ae6b4e51a04cf1a0f 100644
--- a/bin/frontend/controls/Registration.js
+++ b/bin/frontend/controls/Registration.js
@@ -110,6 +110,11 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/Registration', [
             );
 
             if (RedirectElm) {
+                if (RedirectElm.get('data-reload')) {
+                    window.location.reload();
+                    return;
+                }
+
                 var url     = RedirectElm.get('data-url');
                 var instant = RedirectElm.get('data-instant') === "1";
 
diff --git a/bin/frontend/controls/RegistrationSignUp.js b/bin/frontend/controls/RegistrationSignUp.js
index 984c4eeb4bf662c691d4a9657c4197e35e474b44..d3e98ffa841937a4ee565c62afea0185e4b7732d 100644
--- a/bin/frontend/controls/RegistrationSignUp.js
+++ b/bin/frontend/controls/RegistrationSignUp.js
@@ -332,6 +332,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/RegistrationSignUp'
         sendRegistration: function (registrar, registration_id, formData) {
             this.showLoader();
 
+            console.log(111);
             var self = this;
 
             return new Promise(function (resolve, reject) {
@@ -395,8 +396,15 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/RegistrationSignUp'
 
                                 var Redirect = Section.getElement('.quiqqer-frontendUsers-redirect');
 
-                                if (Redirect && Redirect.get('data-instant') && self.getAttribute('reloadOnSuccess')) {
-                                    window.location = Redirect.get('data-url');
+                                if (Redirect && self.getAttribute('reloadOnSuccess')) {
+                                    if (Redirect.get('data-reload')) {
+                                        window.location.reload();
+                                        return;
+                                    }
+
+                                    if (Redirect.get('data-instant')){
+                                        window.location = Redirect.get('data-url');
+                                    }
                                 }
 
                                 if (Section.getElement('.content-message-error')) {
@@ -442,8 +450,6 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/RegistrationSignUp'
          * @return {Promise}
          */
         showTerms: function (registrar, isSocial) {
-            console.log('show terms', this.getAttribute('termsAccepted'));
-
             if (this.getAttribute('termsAccepted')) {
                 return Promise.resolve();
             }
@@ -638,8 +644,15 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/RegistrationSignUp'
 
                                 var Redirect = Section.getElement('.quiqqer-frontendUsers-redirect');
 
-                                if (Redirect && Redirect.get('data-instant')) {
-                                    window.location = Redirect.get('data-url');
+                                if (Redirect && self.getAttribute('reloadOnSuccess')) {
+                                    if (Redirect.get('data-reload')) {
+                                        window.location.reload();
+                                        return;
+                                    }
+
+                                    if (Redirect.get('data-instant')){
+                                        window.location = Redirect.get('data-url');
+                                    }
                                 }
 
                                 var ErrorBox = Section.getElement('.content-message-error');
@@ -1331,7 +1344,10 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/RegistrationSignUp'
                     duration: 250,
                     callback: function () {
                         Captcha.setStyle('display', 'none');
-                        Password.setStyle('display', 'none');
+
+                        if (Password) {
+                            Password.setStyle('display', 'none');
+                        }
 
                         Mail.setStyle('opacity', 0);
                         Mail.setStyle('display', 'inline');
@@ -1378,8 +1394,8 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/RegistrationSignUp'
 
                 childNodes.setStyle('display', 'none');
 
-                return self.hideTerms().then(function () {
-                    return self.showLoader();
+                return self.showLoader().then(() => {
+                    return self.hideTerms();
                 }).then(function () {
                     var Form     = self.getElm().getElement('form[name="quiqqer-fu-registrationSignUp-email"]'),
                         FormData = QUIFormUtils.getFormData(Form);
diff --git a/bin/frontend/controls/address/Manager.js b/bin/frontend/controls/address/Manager.js
index d27bd72a6c401b6da6f40fce7fac210e71e72bc9..15477e4bf24906ffc7fa8cbe90f99a3bd297a16f 100644
--- a/bin/frontend/controls/address/Manager.js
+++ b/bin/frontend/controls/address/Manager.js
@@ -6,10 +6,11 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
     'qui/QUI',
     'qui/controls/Control',
     'qui/controls/loader/Loader',
+    'qui/controls/windows/Confirm',
     'Locale',
     'Ajax'
 
-], function(QUI, QUIControl, QUILoader, QUILocale, QUIAjax) {
+], function(QUI, QUIControl, QUILoader, QUIConfirm, QUILocale, QUIAjax) {
     'use strict';
 
     const lg = 'quiqqer/frontend-users';
@@ -24,8 +25,6 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
             '$editClick',
             '$deleteClick',
             '$addClick',
-            '$openContainer',
-            '$closeContainer',
             '$clickCreateSubmit',
             '$clickEditSave'
         ],
@@ -56,14 +55,6 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
             this.$imported = true;
             this.getElm().set('data-quiid', this.getId());
 
-            const entries = this.getElm().getElements(
-                '.quiqqer-frontend-users-address-list-entry'
-            );
-
-            entries.setStyles({
-                'position': 'relative'
-            });
-
             this.getElm().getElements('[name="create"]').addEvent('click', this.$addClick);
             this.getElm().getElements('[name="delete"]').addEvent('click', this.$deleteClick);
             this.getElm().getElements('[name="edit"]').addEvent('click', this.$editClick);
@@ -170,30 +161,51 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
 
             const self = this;
 
-            // open delete dialog
-            this.$openContainer(this.getElm()).then(function(Container) {
-                return self.getCreateTemplate().then(function(result) {
-                    const Content = Container.getElement(
-                        '.quiqqer-frontend-users-address-container-content'
-                    );
+            self.getCreateTemplate().then(function(result) {
+                const Form = new Element('form', {
+                    'class': 'quiqqer-frontendUsers-controls-profile-control default-content',
+                    html: result,
+                    'data-name': 'address-container'
+                });
 
-                    new Element('form', {
-                        'class': 'quiqqer-frontend-users-address-container-create',
-                        html: result,
-                        events: {
-                            submit: function(event) {
-                                event.stop();
-                            }
-                        }
-                    }).inject(Content);
+                QUI.parse(Form).then(function() {
+                    self.$removeUnusedNodes(Form);
 
-                    Content.getElement('header').inject(
-                        Container.getElement('.quiqqer-frontend-users-address-container-header')
-                    );
+                    new QUIConfirm({
+                        'class' : 'qui-window-popup--frontendUsers-profile qui-window-popup--frontendUsers-profile-address-add',
+                        maxHeight: 800,
+                        maxWidth: 700,
+                        autoclose: false,
+                        backgroundClosable: false,
 
-                    Content.getElement('[type="submit"]').addEvent('click', self.$clickCreateSubmit);
+                        title: QUILocale.get(lg, 'dialog.frontend-users.title'),
+                        icon: 'fa fa-address-card-o',
 
-                    self.resize();
+                        ok_button: {
+                            text: QUILocale.get(lg, 'dialog.frontend-users.create.address.btn')
+                        },
+                        cancel_button: {
+                            text: QUILocale.get(lg, 'dialog.frontend-users.btn.cancel')
+                        },
+
+                        events: {
+                            onOpen: function(Popup) {
+                                const Content = Popup.getContent();
+                                Content.innerHTML = '';
+                                Form.inject(Content);
+                            },
+                            onSubmit: function(Popup) {
+                                Popup.Loader.show();
+
+                                self.$clickCreateSubmit(Popup).then(function() {
+                                    Popup.close();
+                                    self.refresh();
+                                }).catch(() => {
+                                    Popup.Loader.hide();
+                                });
+                            }
+                        }
+                    }).open();
                 });
             });
         },
@@ -201,47 +213,41 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
         /**
          * click event - address creation
          *
-         * @param {DOMEvent} event
+         * @param {QUIConfirm} Popup
          */
-        $clickCreateSubmit: function(event) {
-            event.stop();
-
-            const Target = event.target,
-                Container = Target.getParent('.quiqqer-frontend-users-address-container'),
-                Form = Container.getElement('form');
-
-            this.Loader.show();
+        $clickCreateSubmit: function(Popup) {
+            const Content = Popup.getContent(),
+                Form = Content.getElement('form');
 
-            require(['qui/utils/Form'], (FormUtils) => {
-                const formData = FormUtils.getFormData(Form);
-                const requiredFields = Form.getElements('[required]');
-
-                for (let i = 0, len = requiredFields.length; i < len; i++) {
-                    if ('reportValidity' in requiredFields[i]) {
-                        requiredFields[i].reportValidity();
-
-                        if ('checkValidity' in requiredFields[i]) {
-                            if (requiredFields[i].checkValidity() === false) {
-                                this.Loader.hide();
-                                return;
+            return new Promise(function(resolve, reject) {
+                require(['qui/utils/Form'], (FormUtils) => {
+                    const formData = FormUtils.getFormData(Form);
+                    const requiredFields = Form.getElements('[required]');
+
+                    for (let i = 0, len = requiredFields.length; i < len; i++) {
+                        if ('reportValidity' in requiredFields[i]) {
+                            requiredFields[i].reportValidity();
+
+                            if ('checkValidity' in requiredFields[i]) {
+                                if (requiredFields[i].checkValidity() === false) {
+                                    reject();
+                                    return;
+                                }
                             }
                         }
                     }
-                }
 
-                QUIAjax.post('package_quiqqer_frontend-users_ajax_frontend_profile_address_create', () => {
-                    this.$closeContainer(Container);
-                    this.refresh();
-                }, {
-                    'package': 'quiqqer/frontend-users',
-                    data: JSON.encode(formData),
-                    onError: (err) => {
-                        QUI.getMessageHandler().then(function(MH) {
-                            MH.addError(err.getMessage());
-                        });
+                    QUIAjax.post('package_quiqqer_frontend-users_ajax_frontend_profile_address_create', resolve, {
+                        'package': 'quiqqer/frontend-users',
+                        data: JSON.encode(formData),
+                        onError: (err) => {
+                            QUI.getMessageHandler().then(function(MH) {
+                                MH.addError(err.getMessage());
+                            });
 
-                        this.Loader.hide();
-                    }
+                            reject();
+                        }
+                    });
                 });
             });
         },
@@ -271,72 +277,82 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
         $deleteClick: function(event) {
             event.stop();
 
-            const self = this;
-            let Target = event.event.target;
+            let Target = event.target;
 
-            if (!Target.hasClass('quiqqer-frontend-users-address-list-entry')) {
-                Target = Target.getParent('.quiqqer-frontend-users-address-list-entry');
+            if (Target.nodeName !== 'BUTTON') {
+                Target = Target.getParent('button');
             }
 
-            const Address = Target;
+            const addressId = Target.getParent('[data-name="address"]').querySelector('[name="address"]').value;
+            const self = this;
 
-            // open delete dialog
-            this.$openContainer(Target).then(function(Container) {
-                Container.addClass(
-                    'quiqqer-frontend-users-address-container-delete'
-                );
+            self.getDeleteTemplate(addressId).then(function(result) {
 
-                const Content = Container.getElement('.quiqqer-frontend-users-address-container-content');
+                const Form = new Element('form', {
+                    'class': 'quiqqer-frontendUsers-controls-profile-control default-content',
+                    html: result,
+                    'data-name': 'address-container'
+                });
 
-                new Element('div', {
-                    'class': 'quiqqer-frontend-users-address-container-delete-message',
-                    html: QUILocale.get(lg, 'dialog.frontend-users.delete.address')
-                }).inject(Content);
+                QUI.parse(Form).then(function() {
+                    self.$removeUnusedNodes(Form);
 
-                new Element('button', {
-                    'class': 'quiqqer-frontend-users-address-container-delete-button',
-                    html: QUILocale.get('quiqqer/system', 'delete'),
-                    events: {
-                        click: function(event) {
-                            let Target = event.target;
+                    new QUIConfirm({
+                        'class' : 'qui-window-popup--frontendUsers-profile qui-window-popup--frontendUsers-profile-address-delete',
+                        maxHeight: 450,
+                        maxWidth: 500,
+                        autoclose: false,
+                        backgroundClosable: false,
 
-                            if (Target.nodeName !== 'BUTTON') {
-                                Target = Target.getParent('button');
-                            }
+                        title: QUILocale.get(lg, 'dialog.frontend-users.address.delete.title'),
+                        icon: 'fa fa-address-card-o',
 
-                            Target.disabled = true;
-                            Target.setStyle('width', Target.getSize().x);
-                            Target.set('html', '<span class="fa fa-spinner fa-spin"></span>');
-
-                            self.Loader.show();
-
-                            self.deleteAddress(
-                                Target.getParent('.quiqqer-frontend-users-address-list-entry').getElement(
-                                    '[name="address"]').value
-                            ).then(function() {
-                                return self.$closeContainer(Container);
-                            }).then(function() {
-                                Address.setStyles({
-                                    overflow: 'hidden',
-                                    height: Address.getSize().y
-                                });
+                        ok_button: {
+                            text: QUILocale.get(lg, 'dialog.frontend-users.address.delete.btn')
+                        },
+                        cancel_button: {
+                            text: QUILocale.get(lg, 'dialog.frontend-users.btn.cancel')
+                        },
 
-                                moofx(Address).animate({
-                                    height: 0,
-                                    opacity: 0
-                                }, {
-                                    duration: 250,
-                                    callback: function() {
-                                        self.refresh();
-                                    }
+                        events: {
+                            onOpen: function(Popup) {
+                                const Content = Popup.getContent();
+                                Content.innerHTML = '';
+                                Form.inject(Content);
+
+                                const ConfirmBtn = Popup.getElm().querySelector('[name="submit"]');
+
+                                ConfirmBtn.classList.remove('btn-success');
+                                ConfirmBtn.classList.add('btn-danger');
+                            },
+                            onSubmit: function(Popup) {
+                                Popup.Loader.show();
+
+                                self.deleteAddress(addressId).then(function() {
+                                    Popup.close();
+                                    self.refresh();
+                                }).catch(() => {
+                                    Popup.Loader.hide();
                                 });
-                            }).catch(function() {
-                                self.$closeContainer(Container);
-                                self.Loader.hide();
-                            });
+                            }
                         }
-                    }
-                }).inject(Content);
+                    }).open();
+                });
+            });
+        },
+
+        /**
+         * Return the address create template
+         *
+         * @return {Promise}
+         */
+        getDeleteTemplate: function(addressId) {
+            return new Promise(function(resolve, reject) {
+                QUIAjax.get('package_quiqqer_frontend-users_ajax_frontend_profile_address_getDelete', resolve, {
+                    'package': 'quiqqer/frontend-users',
+                    onError: reject,
+                    addressId: addressId
+                });
             });
         },
 
@@ -366,39 +382,60 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
         $editClick: function(event) {
             event.stop();
 
-            const self = this;
             let Target = event.target;
 
             if (Target.nodeName !== 'BUTTON') {
                 Target = Target.getParent('button');
             }
 
-            const addressId = Target.getParent('.quiqqer-frontend-users-address-list-entry').getElement(
-                '[name="address"]').value;
+            const addressId = Target.getParent('[data-name="address"]').querySelector('[name="address"]').value;
+            const self = this;
 
-            this.$openContainer(this.getElm()).then(function(Container) {
-                return self.getEditTemplate(addressId).then(function(result) {
-                    const Content = Container.getElement(
-                        '.quiqqer-frontend-users-address-container-content'
-                    );
+            self.getEditTemplate(addressId).then(function(result) {
+                const Form = new Element('form', {
+                    'class': 'quiqqer-frontendUsers-controls-profile-control default-content',
+                    html: result,
+                    'data-name': 'address-container'
+                });
 
-                    new Element('form', {
-                        'class': 'quiqqer-frontend-users-address-container-edit',
-                        html: result,
-                        events: {
-                            submit: function(event) {
-                                event.stop();
-                            }
-                        }
-                    }).inject(Content);
+                QUI.parse(Form).then(function() {
+                    self.$removeUnusedNodes(Form);
 
-                    Content.getElement('header').inject(
-                        Container.getElement('.quiqqer-frontend-users-address-container-header')
-                    );
+                    new QUIConfirm({
+                        'class' : 'qui-window-popup--frontendUsers-profile qui-window-popup--frontendUsers-profile-address-edit',
+                        maxHeight: 800,
+                        maxWidth: 700,
+                        autoclose: false,
+                        backgroundClosable: false,
 
-                    Content.getElement('[name="editSave"]').addEvent('click', self.$clickEditSave);
+                        title: QUILocale.get(lg, 'dialog.frontend-users.edit.title'),
+                        icon: 'fa fa-address-card-o',
 
-                    self.resize();
+                        ok_button: {
+                            text: QUILocale.get(lg, 'dialog.frontend-users.edit.address.btn')
+                        },
+                        cancel_button: {
+                            text: QUILocale.get(lg, 'dialog.frontend-users.btn.cancel')
+                        },
+
+                        events: {
+                            onOpen: function(Popup) {
+                                const Content = Popup.getContent();
+                                Content.innerHTML = '';
+                                Form.inject(Content);
+                            },
+                            onSubmit: function(Popup) {
+                                Popup.Loader.show();
+
+                                self.$clickEditSave(Popup).then(function() {
+                                    Popup.close();
+                                    self.refresh();
+                                }).catch(() => {
+                                    Popup.Loader.hide();
+                                });
+                            }
+                        }
+                    }).open();
                 });
             });
         },
@@ -406,48 +443,34 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
         /**
          * event : click -> save the address edit
          *
-         * @param {DOMEvent} event
+         * {QUIConfirm} Popup
          */
-        $clickEditSave: function(event) {
-            event.stop();
+        $clickEditSave: function(Popup) {
+            const self = this,
+                Content = Popup.getContent(),
+                Form = Content.getElement('form');
 
-            const Target = event.target,
-                Container = Target.getParent('.quiqqer-frontend-users-address-container'),
-                Form = Container.getElement('form');
-
-            this.Loader.show();
+            return new Promise(function(resolve, reject) {
+                require(['qui/utils/Form'], (FormUtils) => {
+                    const formData = FormUtils.getFormData(Form);
 
-            require(['qui/utils/Form'], (FormUtils) => {
-                const formData = FormUtils.getFormData(Form);
-                const requiredFields = Form.getElements('[required]');
+                    if (self.$hasValidityIssues(Form)) {
+                        reject();
+                        return;
+                    }
 
-                for (let i = 0, len = requiredFields.length; i < len; i++) {
-                    if ('reportValidity' in requiredFields[i]) {
-                        requiredFields[i].reportValidity();
+                    QUIAjax.post('package_quiqqer_frontend-users_ajax_frontend_profile_address_edit', resolve, {
+                        'package': 'quiqqer/frontend-users',
+                        data: JSON.encode(formData),
+                        addressId: formData.addressId,
+                        onError: (err) => {
+                            QUI.getMessageHandler().then((MH) => {
+                                MH.addError(err.getMessage());
+                            });
 
-                        if ('checkValidity' in requiredFields[i]) {
-                            if (requiredFields[i].checkValidity() === false) {
-                                this.Loader.hide();
-                                return;
-                            }
+                            reject();
                         }
-                    }
-                }
-
-                QUIAjax.post('package_quiqqer_frontend-users_ajax_frontend_profile_address_edit', () => {
-                    this.$closeContainer(Container);
-                    this.refresh();
-                }, {
-                    'package': 'quiqqer/frontend-users',
-                    data: JSON.encode(formData),
-                    addressId: formData.addressId,
-                    onError: (err) => {
-                        QUI.getMessageHandler().then((MH) => {
-                            MH.addError(err.getMessage());
-                        });
-
-                        this.Loader.hide();
-                    }
+                    });
                 });
             });
         },
@@ -469,74 +492,30 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/address/Manager', [
 
         //endregion
 
-        /**
-         * Open a div container with effect
-         *
-         * @return {Promise}
-         */
-        $openContainer: function(Parent) {
-            const self = this;
-
-            const Container = new Element('div', {
-                'class': 'quiqqer-frontend-users-address-container',
-                html: '<div class="quiqqer-frontend-users-address-container-header"></div>' +
-                    '<div class="quiqqer-frontend-users-address-container-content"></div>',
-                tabIndex: -1
-            }).inject(Parent);
-
-            new Element('span', {
-                'class': 'fa fa-close quiqqer-frontend-users-address-container-close',
-                events: {
-                    click: function() {
-                        self.$closeContainer(Container);
-                    }
-                }
-            }).inject(Container, 'top');
-
-            return new Promise(function(resolve) {
-                moofx(Container).animate({
-                    left: 0,
-                    opacity: 1
-                }, {
-                    duration: 250,
-                    callback: function() {
-                        // no scroll animation because after address edit is open
-                        // there may be an animation depend on selected option in "businessType" select
-                        self.getElm().scrollIntoView()
-                        resolve(Container);
-                    }
-                });
-            });
+        $removeUnusedNodes: function(Node) {
+            if (Node.querySelector('button')) {
+                Node.querySelector('button').destroy();
+            }
         },
 
-        /**
-         * Open a div container with effect
-         *
-         * @param {HTMLDivElement} Container
-         * @return {Promise}
-         */
-        $closeContainer: function(Container) {
-            const self = this;
+        $hasValidityIssues: function(Form) {
+            const requiredFields = Form.getElements('[required]');
+            let i = 0,
+                len = requiredFields.length;
 
-            return new Promise(function(resolve) {
-                moofx(Container).animate({
-                    left: -50,
-                    opacity: 0
-                }, {
-                    duration: 250,
-                    callback: function() {
-                        Container.destroy();
-                        self.getElm().setStyle('height', null);
+            for (i; i < len; i++) {
+                if ('reportValidity' in requiredFields[i]) {
+                    requiredFields[i].reportValidity();
 
-                        if (self.$Profile) {
-                            self.$Profile.getElm().setStyle('overflow', null);
+                    if ('checkValidity' in requiredFields[i]) {
+                        if (requiredFields[i].checkValidity() === false) {
+                            return true;
                         }
-
-                        self.resize();
-                        resolve();
                     }
-                });
-            });
+                }
+            }
+
+            return false;
         }
     });
 });
diff --git a/bin/frontend/controls/login/Login.js b/bin/frontend/controls/login/Login.js
index f5c85caa122a33bd95cb82c6d93ea372468d10f8..0b98ad3824aad38501219b312e255f4f4ee22b91 100644
--- a/bin/frontend/controls/login/Login.js
+++ b/bin/frontend/controls/login/Login.js
@@ -108,10 +108,11 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
                 this.Loader.show();
             }
 
-            var Elm = this.getElm();
+            const Elm = this.getElm(),
+                HeaderElm = Elm.querySelector('[data-name="header"]');
 
-            if (this.getAttribute('header') === false) {
-                Elm.getElement('h2').destroy();
+            if (this.getAttribute('header') === false && HeaderElm) {
+                HeaderElm.destroy();
             }
 
             this.$parseQuiControls();
@@ -128,22 +129,24 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
             }
 
             QUIAjax.get('package_quiqqer_frontend-users_ajax_frontend_login_getControl', function(result) {
-                var Ghost = new Element('div', {
+                const Ghost = new Element('div', {
                     html: result
                 });
 
-                if (self.getAttribute('header') === false) {
-                    Ghost.getElement('h2').destroy();
+                const HeaderElm = Ghost.querySelector('[data-name="header"]');
+
+                if (self.getAttribute('header') === false && HeaderElm) {
+                    HeaderElm.destroy();
                 }
 
                 self.getElm().set(
                     'html',
-                    Ghost.getElement('.quiqqer-fu-login').get('html')
+                    Ghost.querySelector('.quiqqer-fu-login').get('html')
                 );
 
                 self.Loader.inject(self.$Elm);
 
-                Ghost.getElements('style').inject(self.getElm());
+                Ghost.querySelector('style').inject(self.getElm());
 
                 self.$parseQuiControls();
             }, {
@@ -161,7 +164,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
             var self = this;
 
             QUI.parse(this.getElm()).then(function() {
-                var Login = self.getElm().getElement('.quiqqer-fu-login-container');
+                var Login = self.getElm().querySelector('[data-name="login-container"]');
 
                 // already logged in
                 if (!Login) {
@@ -174,6 +177,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
 
                 Login.setStyle('opacity', 0);
                 Login.setStyle('display', null);
+                Login.setStyle('positino', 'relative');
 
                 self.getElm().getElements('form[name="quiqqer-fu-login-email"]').addEvent('submit', function(event) {
                     event.stop();
@@ -185,15 +189,17 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
                 var emailAddress = self.getAttribute('emailAddress');
 
                 if (emailAddress) {
-                    self.getElm().getElement('form[name="quiqqer-fu-login-email"]').getElement('input[name="username"]').value = emailAddress;
+                    self.getElm().querySelector('form[name="quiqqer-fu-login-email"]').querySelector(
+                        'input[name="username"]').value = emailAddress;
 
-                    self.getElm().getElement('form[name="quiqqer-fu-login-email"]').getElement('input[name="password"]').focus();
+                    self.getElm().querySelector('form[name="quiqqer-fu-login-email"]').querySelector(
+                        'input[name="password"]').focus();
                 }
 
-                self.getElm().getElements('.quiqqer-fu-login-social-entry').addEvent('click', self.$auth);
+                self.getElm().getElements('[data-name="social-login-form"]').addEvent('click', self.$auth);
 
                 self.getElm().getElements(
-                    '.quiqqer-fu-login-forget-password-link a'
+                    '[data-name="forgot-password-link"] a'
                 ).addEvent('click', function(event) {
                     event.stop();
                     self.openForgottenPassword();
@@ -213,9 +219,8 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
                     self.sendForgottenPassword();
                 });
 
-
                 // submit events
-                var container = self.getElm().getElements('.quiqqer-fu-login-social-entry-control');
+                var container = self.getElm().getElements('[data-name="social-login-controlContainer"]');
                 var i, len, Control, ControlDom;
 
                 for (i = 0, len = container.length; i < len; i++) {
@@ -225,7 +230,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
                     //Control.addEvent('');
                 }
 
-                self.getElm().getElements('form.quiqqer-fu-login-social-entry').addEvents({
+                self.getElm().getElements('[data-name="social-login-form"]').addEvents({
                     submit: self.$authBySocial
                 });
 
@@ -258,7 +263,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
                 }
 
                 if (submitauth) {
-                    var Form = self.getElm().getElement('form[data-authenticator-hash="' +
+                    var Form = self.getElm().querySelector('form[data-authenticator-hash="' +
                         self.getAttribute('submitauth') + '"]');
 
                     if (Form) {
@@ -273,7 +278,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
          */
         authByEmail: function() {
             var self = this,
-                Form = this.getElm().getElement('form[name="quiqqer-fu-login-email"]');
+                Form = this.getElm().querySelector('form[name="quiqqer-fu-login-email"]');
 
             if (this.getAttribute('showLoader')) {
                 this.Loader.show();
@@ -402,8 +407,8 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
          * @param Form
          */
         $showSocialLoader: function(Form) {
-            var Icon = Form.getElement('.quiqqer-fu-login-social-entry-icon');
-            var Loader = Form.getElement('.quiqqer-fu-login-social-entry-loader');
+            var Icon = Form.querySelector('[data-name="social-login-entry-icon"]');
+            var Loader = Form.querySelector('[data-name="social-login-entry-loader"]');
 
             Loader.setStyle('opacity', 0);
             Loader.setStyle('display', 'inline-block');
@@ -430,8 +435,8 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
          * @param Form
          */
         $hideSocialLoader: function(Form) {
-            var Icon = Form.getElement('.quiqqer-fu-login-social-entry-icon');
-            var Loader = Form.getElement('.quiqqer-fu-login-social-entry-loader');
+            var Icon = Form.querySelector('[data-name="social-login-entry-icon"]');
+            var Loader = Form.querySelector('[data-name="social-login-entry-loader"]');
 
             Icon.setStyle('opacity', 0);
             Icon.setStyle('display', 'inline-block');
@@ -462,11 +467,11 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
 
             var Target = event.target;
 
-            if (!Target.hasClass('quiqqer-fu-login-social-entry')) {
-                Target = Target.getParent('.quiqqer-fu-login-social-entry');
+            if (Target.getAttribute('data-name') !== 'social-login-form') {
+                Target = Target.getAttribute('[data-name="social-login-form"]');
             }
 
-            var Container = Target.getElement('.quiqqer-fu-login-social-entry-control');
+            var Container = Target.getElement('[data-name="social-login-controlContainer"]');
             var ControlDom = Container.getFirst();
             var Control = QUI.Controls.getById(ControlDom.get('data-quiid'));
 
@@ -512,16 +517,36 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
          * opens the password forgotten sheet
          */
         openForgottenPassword: function() {
-            var Reset = this.getElm().getElement('.quiqqer-fu-login-forget-password-reset');
+            var Reset = this.getElm().querySelector('[data-name="password-reset"]');
 
             if (!Reset) {
                 return;
             }
 
+            // set these styles to make the animation work correctly when using _basic files
+            Reset.style.position = 'absolute';
+            Reset.style.left = 0;
+            Reset.style.top = 0;
+            Reset.style.width = '100%';
+            Reset.style.zIndex = 1;
+            Reset.style.opacity = 0;
+
+            const Login = this.getElm().querySelector('[data-name="login-container"]');
+            Login.style.height = Login.offsetHeight + 'px';
+
+            const LoginInner = this.getElm().querySelector('[data-name="login-container-inner"]');
+
+            // set these styles to make the animation work correctly when using _basic files
             Reset.setStyle('opacity', 0);
             Reset.setStyle('left', -50);
             Reset.setStyle('display', 'block');
 
+            if (LoginInner) {
+                moofx(LoginInner).animate({
+                    opacity: 0
+                });
+            }
+
             moofx(Reset).animate({
                 left: 0,
                 opacity: 1
@@ -530,6 +555,12 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
 
                 }
             });
+
+            if (LoginInner) {
+                moofx(Login).animate({
+                    height: Reset.offsetHeight
+                });
+            }
         },
 
         /**
@@ -538,9 +569,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
          * @param {Object} error
          */
         $onUserLoginError: function(Control, error) {
-            var ActivationInfoBox = this.$Elm.getElement(
-                '.quiqqer-fu-login-activation-info'
-            );
+            var ActivationInfoBox = this.$Elm.querySelector('[data-name="activation-info"]');
 
             ActivationInfoBox.set('html', '');
 
@@ -574,14 +603,14 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
                     var email = this.getAttribute('emailAddress');
 
                     if (!email) {
-                        var Form = this.getElm().getElement('form[name="quiqqer-fu-login-email"]');
+                        var Form = this.getElm().querySelector('form[name="quiqqer-fu-login-email"]');
 
                         if (!Form) {
                             showResendError();
                             return;
                         }
 
-                        email = Form.getElement('input[name="username"]').value.trim();
+                        email = Form.querySelector('input[name="username"]').value.trim();
                     }
 
                     new ResendActivationLinkBtn({
@@ -608,12 +637,23 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
          * close the password reset
          */
         closeForgottenPassword: function() {
-            var Reset = this.getElm().getElement('.quiqqer-fu-login-forget-password-reset');
+            var Reset = this.getElm().querySelector('[data-name="password-reset"]');
 
             if (!Reset) {
                 return;
             }
 
+            const Login = this.getElm().querySelector('[data-name="login-container"]');
+            Login.style.height = Login.offsetHeight + 'px';
+
+            const LoginInner = this.getElm().querySelector('[data-name="login-container-inner"]');
+
+            if (LoginInner) {
+                moofx(LoginInner).animate({
+                    opacity: 1
+                });
+            }
+
             moofx(Reset).animate({
                 left: -50,
                 opacity: 0
@@ -622,6 +662,16 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
                     Reset.setStyle('display', 'none');
                 }
             });
+
+            if (LoginInner) {
+                moofx(Login).animate({
+                    height: LoginInner.offsetHeight
+                }, {
+                    callback: function() {
+                        Login.style.height = null;
+                    }
+                });
+            }
         },
 
         /**
@@ -630,9 +680,10 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/login/Login', [
         sendForgottenPassword: function() {
             var self = this,
                 Elm = this.getElm(),
-                SubmitBtn = Elm.getElement('.quiqqer-fu-login-forget-password-reset [type="submit"]'),
-                EmailInput = Elm.getElement('.quiqqer-fu-login-forget-password-reset [name="email"]'),
-                Section = Elm.getElement('.quiqqer-fu-login-forget-password-reset section');
+                PasswordReset = Elm.querySelector('[data-name="password-reset"]'),
+                SubmitBtn = PasswordReset.querySelector('[type="submit"]'),
+                EmailInput = PasswordReset.querySelector('[name="email"]'),
+                Section = PasswordReset.querySelector('[data-name="password-reset-inner"]');
 
             if (EmailInput.value === '') {
                 return Promise.resolve();
diff --git a/bin/frontend/controls/profile/ChangePassword.js b/bin/frontend/controls/profile/ChangePassword.js
index f9116bec198baf11dffe7fcc24e707f8de52b9f8..9c66963175771d7c58047804d2cf42b8853de794 100644
--- a/bin/frontend/controls/profile/ChangePassword.js
+++ b/bin/frontend/controls/profile/ChangePassword.js
@@ -12,15 +12,15 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassw
 
     'Locale'
 
-], function (QUIControl, QUIControlUtils, QUIFormUtils, QUILocale) {
-    "use strict";
+], function(QUIControl, QUIControlUtils, QUIFormUtils, QUILocale) {
+    'use strict';
 
     var lg = 'quiqqer/frontend-users';
 
     return new Class({
 
         Extends: QUIControl,
-        Type   : 'package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassword',
+        Type: 'package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassword',
 
         Binds: [
             '$onInject',
@@ -30,12 +30,12 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassw
             '$hideSuccess'
         ],
 
-        initialize: function (options) {
+        initialize: function(options) {
             this.parent(options);
 
-            this.$ErrorContainer   = null;
+            this.$ErrorContainer = null;
             this.$SuccessContainer = null;
-            this.$ProfileControl   = null;
+            this.$ProfileControl = null;
 
             this.addEvents({
                 onImport: this.$onImport
@@ -45,9 +45,9 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassw
         /**
          * event: on import
          */
-        $onImport: function () {
-            var self             = this;
-            var Elm              = this.getElm();
+        $onImport: function() {
+            var self = this;
+            var Elm = this.getElm();
             var PasswordOldInput = Elm.getElement('input[name="passwordOld"]');
 
             if (PasswordOldInput) {
@@ -60,30 +60,30 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassw
                 return;
             }
 
-            this.$ErrorContainer   = Elm.getElement('.quiqqer-frontendUsers-changepassword-error');
-            this.$SuccessContainer = Elm.getElement('.quiqqer-frontendUsers-changepassword-success');
+            this.$ErrorContainer = Elm.querySelector('[data-name="msg-error"]');
+            this.$SuccessContainer = Elm.querySelector('[data-name="msg-success"]');
 
             QUIControlUtils.getControlByElement(
                 Elm.getParent('.quiqqer-frontendUsers-controls-profile')
-            ).then(function (ProfileControl) {
+            ).then(function(ProfileControl) {
                 self.$ProfileControl = ProfileControl;
 
                 self.$ProfileControl.addEvents({
-                    onSave     : function () {
+                    onSave: function() {
                         QUIFormUtils.setDataToForm({
-                            'passwordOld'       : '',
-                            'passwordNew'       : '',
+                            'passwordOld': '',
+                            'passwordNew': '',
                             'passwordNewConfirm': ''
                         }, Form);
                     },
-                    onSaveEnd  : function () {
+                    onSaveEnd: function() {
                         self.$showSuccess();
                     },
-                    onSaveError: function (Control, error) {
+                    onSaveError: function(Control, error) {
                         self.$showError(error.getMessage());
                     }
                 });
-            }, function () {
+            }, function() {
                 // nothing
             });
         },
@@ -93,7 +93,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassw
          *
          * @param {String} msg
          */
-        $showError: function (msg) {
+        $showError: function(msg) {
             this.$hideSuccess();
 
             this.$ErrorContainer.set('html', msg);
@@ -105,7 +105,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassw
         /**
          * Show error msg
          */
-        $hideError: function () {
+        $hideError: function() {
             this.$ErrorContainer.setStyle('display', 'none');
             this.$ProfileControl.resize();
         },
@@ -113,7 +113,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassw
         /**
          * Show success msg
          */
-        $showSuccess: function () {
+        $showSuccess: function() {
             this.$hideError();
 
             this.$SuccessContainer.set(
@@ -128,7 +128,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassw
         /**
          * Hide success msg
          */
-        $hideSuccess: function () {
+        $hideSuccess: function() {
             this.$SuccessContainer.setStyle('display', 'none');
             this.$ProfileControl.resize();
         }
diff --git a/bin/frontend/controls/profile/DeleteAccount.js b/bin/frontend/controls/profile/DeleteAccount.js
index 2cfbe4567e35e4d3415ac917027c8eab09efc56b..88bd693c54b636d80644c020dda4b11231fae8bf 100644
--- a/bin/frontend/controls/profile/DeleteAccount.js
+++ b/bin/frontend/controls/profile/DeleteAccount.js
@@ -11,15 +11,15 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/DeleteAccou
     'Locale',
     'Ajax'
 
-], function (QUIControl, QUIConfirm, QUILocale, QUIAjax) {
-    "use strict";
+], function(QUIControl, QUIConfirm, QUILocale, QUIAjax) {
+    'use strict';
 
     var lg = 'quiqqer/frontend-users';
 
     return new Class({
 
         Extends: QUIControl,
-        Type   : 'package/quiqqer/frontend-users/bin/frontend/controls/profile/DeleteAccount',
+        Type: 'package/quiqqer/frontend-users/bin/frontend/controls/profile/DeleteAccount',
 
         Binds: [
             '$onImport',
@@ -27,11 +27,11 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/DeleteAccou
         ],
 
         options: {
-            username     : '',
+            username: '',
             deletestarted: 0
         },
 
-        initialize: function (options) {
+        initialize: function(options) {
             this.parent(options);
 
             this.addEvents({
@@ -42,24 +42,24 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/DeleteAccou
         /**
          * event: on import
          */
-        $onImport: function () {
+        $onImport: function() {
             var Elm = this.getElm();
 
-            var SubmitBtn = Elm.getElement('button.quiqqer-frontendUsers-saveButton'),
+            var SubmitBtn = Elm.querySelector('[type="submit"]'),
                 confirmed = false;
 
             if (!SubmitBtn) {
                 return;
             }
 
-            var self     = this;
+            var self = this;
             var username = this.getAttribute('username');
 
             if (!username) {
                 username = '';
             }
 
-            SubmitBtn.addEvent('click', function (event) {
+            SubmitBtn.addEvent('click', function(event) {
                 if (confirmed || self.getAttribute('deletestarted')) {
                     return;
                 }
@@ -68,50 +68,51 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/DeleteAccou
 
                 new QUIConfirm({
                     maxHeight: 350,
+                    maxWidth: 600,
                     autoclose: true,
 
                     information: QUILocale.get(lg, 'controls.profile.DeleteAccount.confirm.information', {
                         username: username
                     }),
-                    title      : QUILocale.get(lg, 'controls.profile.DeleteAccount.confirm.title'),
-                    texticon   : 'fa fa-trash',
-                    text       : QUILocale.get(lg, 'controls.profile.DeleteAccount.confirm.text'),
-                    icon       : 'fa fa-trash',
+                    title: QUILocale.get(lg, 'controls.profile.DeleteAccount.confirm.title'),
+                    texticon: 'fa fa-trash',
+                    text: QUILocale.get(lg, 'controls.profile.DeleteAccount.confirm.text'),
+                    icon: 'fa fa-trash',
 
                     cancel_button: {
-                        text     : QUILocale.get('quiqqer/system', 'cancel'),
+                        text: QUILocale.get('quiqqer/system', 'cancel'),
                         textimage: 'fa fa-remove'
                     },
 
                     ok_button: {
-                        text     : QUILocale.get(lg, 'controls.profile.DeleteAccount.confirm.btn'),
+                        text: QUILocale.get(lg, 'controls.profile.DeleteAccount.confirm.btn'),
                         textimage: 'fa fa-trash'
                     },
 
                     events: {
-                        onOpen  : function (Popup) {
+                        onOpen: function(Popup) {
                             var SubmitBtn = Popup.getButton('submit');
 
                             SubmitBtn.disable();
 
                             Popup.Loader.show();
 
-                            self.$checkDeleteAccount().then(function () {
+                            self.$checkDeleteAccount().then(function() {
                                 SubmitBtn.enable();
                                 Popup.Loader.hide();
-                            }, function (Error) {
+                            }, function(Error) {
                                 Popup.setAttribute(
                                     'information',
                                     QUILocale.get(lg, 'controls.profile.DeleteAccount.confirm.information_error', {
                                         username: username,
-                                        error   : Error.getMessage()
+                                        error: Error.getMessage()
                                     })
                                 );
 
                                 Popup.Loader.hide();
                             });
                         },
-                        onSubmit: function (Popup) {
+                        onSubmit: function(Popup) {
                             confirmed = true;
                             Popup.close();
                             SubmitBtn.click();
@@ -126,11 +127,11 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/DeleteAccou
          *
          * @return {Promise}
          */
-        $checkDeleteAccount: function () {
-            return new Promise(function (resolve, reject) {
+        $checkDeleteAccount: function() {
+            return new Promise(function(resolve, reject) {
                 QUIAjax.get('package_quiqqer_frontend-users_ajax_frontend_profile_checkDeleteAccount', resolve, {
                     'package': 'quiqqer/frontend-users',
-                    onError  : reject,
+                    onError: reject,
                     showError: false
                 });
             });
diff --git a/bin/frontend/controls/profile/Profile.js b/bin/frontend/controls/profile/Profile.js
index 3d7dce91110704f7231c008569c72c9f3c4f2da0..b27eb67f8d1601d62283a83610de7c2a48beabea 100644
--- a/bin/frontend/controls/profile/Profile.js
+++ b/bin/frontend/controls/profile/Profile.js
@@ -83,7 +83,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
         resize: function () {
             var self      = this,
                 Elm       = this.getElm(),
-                Animation = Elm.getElement('.quiqqer-frontendUsers-controls-profile-categoryContentAnimation');
+                Animation = Elm.querySelector('[data-name="content-animated"]');
 
             return new Promise(function (resolve) {
                 self.$parseContent().then(() => {
@@ -128,7 +128,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
             this.$bindCategoriesEvents();
 
             this.openSetting().then(function () {
-                var Form     = Elm.getElement('.quiqqer-frontendUsers-controls-profile-categoryContent');
+                var Form     = Elm.querySelector('[data-name="form"]');
                 var category = Form.get('data-category');
                 var settings = Form.get('data-setting');
 
@@ -155,7 +155,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
             this.$parseContent().then(function () {
                 self.$addFormEvents();
 
-                var Form = Elm.getElement('.quiqqer-frontendUsers-controls-profile-categoryContent');
+                var Form = Elm.querySelector('[data-name="form"]');
 
                 if (!Form) {
                     return;
@@ -205,6 +205,10 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
             var pathName = window.location.pathname,
                 url      = QUIQQER_SITE.url + '/' + this.$category + '/' + this.$settings;
 
+            if (url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1) {
+                pathName = window.location.href;
+            }
+
             if (!this.$settings || !this.$category) {
                 return;
             }
@@ -255,9 +259,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
             category = category || false;
             settings = settings || false;
 
-            var Animation = Elm.getElement(
-                '.quiqqer-frontendUsers-controls-profile-categoryContentAnimation'
-            );
+            var Animation = Elm.querySelector('[data-name="content-animated"]');
 
             var Animate = new Promise(function (resolve) {
                 if (!Animation) {
@@ -280,12 +282,11 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
                 return new Promise(function (resolve, reject) {
                     QUIAjax.get('package_quiqqer_frontend-users_ajax_frontend_profile_getControl', function (result) {
                         var height = self.$Elm.getSize().y;
-                        var Form   = self.$Elm.getElement(
-                            '.quiqqer-frontendUsers-controls-profile-categoryContent'
-                        );
+                        var Form   = self.$Elm.querySelector('[data-name="form"]');
 
                         if (!result) {
-                            result = '<div class="quiqqer-frontendUsers-controls-profile-categoryContentAnimation">' +
+                            result = '<div class="quiqqer-frontendUsers-controls-profile-categoryContentAnimation" ' +
+                                'data-name="content-animated">' +
                                 QUILocale.get(lg, 'controls.profile.Profile.setting_error') +
                                 '</div>';
                         }
@@ -296,7 +297,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
 
                         // build the form
                         if (!Form) {
-                            var Control = Ghost.getElement(
+                            var Control = Ghost.querySelector(
                                 '[data-qui="package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile"]'
                             );
 
@@ -305,26 +306,14 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
                             }
 
                             self.$Elm.set('html', Control.get('html'));
-
-                            Animation = Elm.getElement(
-                                '.quiqqer-frontendUsers-controls-profile-categoryContentAnimation'
-                            );
-
-                            // Form = self.$Elm.getElement(
-                            //     '.quiqqer-frontendUsers-controls-profile-categoryContent'
-                            // );
-
+                            Animation = Elm.querySelector('[data-name="content-animated"]');
                             self.$bindCategoriesEvents();
                         }
 
                         var styles  = Ghost.getElements('style');
                         var scripts = Ghost.getElements('script');
 
-                        var Content = Ghost.getElement(
-                            '.quiqqer-frontendUsers-controls-profile-categoryContentAnimation'
-                        );
-
-                        //Form.setStyle('height', height);
+                        var Content = Ghost.querySelector('[data-name="content-animated"]');
 
                         if (!Content) {
                             return;
@@ -378,56 +367,45 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
          * init category events
          */
         $bindCategoriesEvents: function () {
-            var i, len, Header;
-            var self       = this;
-            var Elm        = this.getElm();
-            var categories = Elm.getElements('.quiqqer-fupc-category');
+            let i, len, Header;
+            const self       = this;
+            const Elm        = this.getElm();
+            const categories = Elm.querySelectorAll('[data-name="nav-category"]');
 
             var toggle = function () {
                 var Category = this;
 
-                if (!this.hasClass('quiqqer-fupc-category')) {
-                    Category = this.getParent('.quiqqer-fupc-category');
+                if (this.getAttribute('data-name') !== 'nav-category') {
+                    Category = this.getParent('[data-name="nav-category"]');
                 }
 
-                var Opener = Category.getElement('.quiqqer-fupc-category-header-opener');
-
-                Opener.removeClass('fa-arrow-circle-o-right');
-                Opener.removeClass('fa-arrow-circle-o-down');
-
-                if (Category.hasClass('quiqqer-fupc-category--open')) {
-                    Category.removeClass('quiqqer-fupc-category--open');
-                    Opener.addClass('fa-arrow-circle-o-right');
+                if (Category.getAttribute('data-open') === "1") {
+                    Category.setAttribute('data-open', 0);
                     return;
                 }
 
-                Category.addClass('quiqqer-fupc-category--open');
-                Opener.addClass('fa-arrow-circle-o-down');
+                Category.setAttribute('data-open', 1);
             };
 
             for (i = 0, len = categories.length; i < len; i++) {
-                Header = categories[i].getElement('.quiqqer-fupc-category-header');
-
-                new Element('span', {
-                    'class': 'fa fa-arrow-circle-o-down quiqqer-fupc-category-header-opener'
-                }).inject(Header);
+                Header = categories[i].querySelector('[data-name="header"]');
 
                 Header.addEvent('click', toggle);
             }
 
             // category settings click
-            var items = Elm.getElements('.quiqqer-fupc-category-items-item');
+            const items = Elm.getElements('[data-name="nav-category-item"]');
 
             items.addEvent('click', function (event) {
                 event.stop();
 
-                var Target = event.target;
+                let Target = event.target;
 
-                if (!Target.hasClass('quiqqer-fupc-category-items-item')) {
-                    Target = Target.getParent('.quiqqer-fupc-category-items-item');
+                if (Target.getAttribute('data-name') !== 'nav-category-item') {
+                    Target = Target.getParent('[data-name="nav-category-item"]');
                 }
 
-                var category = Target.getParent('.quiqqer-fupc-category').get('data-category'),
+                const category = Target.getParent('[data-name="nav-category"]').get('data-category'),
                     setting  = Target.get('data-setting');
 
                 self.$setMenuItemActive(category, setting);
@@ -437,10 +415,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
 
 
             // mobile
-            var MobileCategories = Elm.getElement(
-                '.quiqqer-frontendUsers-controls-profile-categories-mobile select'
-            );
-
+            const MobileCategories = Elm.getElement('[name="profile-categories-mobile"]');
             if (MobileCategories) {
                 if (self.$category && self.$settings) {
                     MobileCategories.value = self.$category + ':' + self.$settings;
@@ -468,7 +443,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
          * @return {Promise}
          */
         save: function () {
-            var self = this;
+            const self = this;
 
             this.fireEvent('saveBegin', [this]);
 
@@ -523,7 +498,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
         },
 
         /**
-         * Set an menu item active
+         * Set a menu item active
          *
          * @param {String} category
          * @param {String} settings
@@ -537,10 +512,11 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile', [
                 return;
             }
 
-            this.$Elm.getElements('.quiqqer-fupc-category-items-item--active')
-                .removeClass('quiqqer-fupc-category-items-item--active');
+            this.$Elm.querySelectorAll('[data-active]').forEach((ActiveItem) => {
+                ActiveItem.removeAttribute('data-active');
+            });
 
-            Item.addClass('quiqqer-fupc-category-items-item--active');
+            Item.setAttribute('data-active', 1);
         }
     });
 });
diff --git a/bin/frontend/controls/profile/UserAvatar.js b/bin/frontend/controls/profile/UserAvatar.js
index 60ad4c4724a02fe5779c3c31dd312ab3312df53b..25b3641ff6bb6d30672f305083d619a159f35de4 100644
--- a/bin/frontend/controls/profile/UserAvatar.js
+++ b/bin/frontend/controls/profile/UserAvatar.js
@@ -62,7 +62,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/UserAvatar'
                     );
 
                     if (Node) {
-                        Node.getElement('.quiqqer-fupc-category-items-item--active').click();
+                        Node.getElement('[data-active="1"]').click();
                     }
                 });
 
diff --git a/bin/frontend/controls/profile/UserData.css b/bin/frontend/controls/profile/UserData.css
index 80f8cb352f8fa3ebe49fbb020f5a7e00ca137eef..33bb70e69a6a5ab80665c7a00807c7a5813b9ea7 100644
--- a/bin/frontend/controls/profile/UserData.css
+++ b/bin/frontend/controls/profile/UserData.css
@@ -1,9 +1,3 @@
-.quiqqer-frontendUsers-userdata-email__hidden {
+[data-hidden] {
     display: none;
-}
-
-.quiqqer-frontendUsers-userdata-email-new-hint {
-    clear: both;
-    width: 100%;
-    float: left;
 }
\ No newline at end of file
diff --git a/bin/frontend/controls/profile/UserData.js b/bin/frontend/controls/profile/UserData.js
index c1a3b218228631ec6d93274081e47327571fde1c..c853829a8e5901a5375166b771903376667f053e 100644
--- a/bin/frontend/controls/profile/UserData.js
+++ b/bin/frontend/controls/profile/UserData.js
@@ -17,15 +17,15 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData',
 
     'css!package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData.css'
 
-], function (QUI, QUIControl, QUIControlUtils, QUIFunctionUtils, QUILocale, Registration) {
-    "use strict";
+], function(QUI, QUIControl, QUIControlUtils, QUIFunctionUtils, QUILocale, Registration) {
+    'use strict';
 
     var lg = 'quiqqer/frontend-users';
 
     return new Class({
 
         Extends: QUIControl,
-        Type   : 'package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData',
+        Type: 'package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData',
 
         Binds: [
             '$onInject',
@@ -33,7 +33,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData',
             '$clearEmailErrorMsg'
         ],
 
-        initialize: function (options) {
+        initialize: function(options) {
             this.parent(options);
 
             this.$EmailErrorMsgElm = null;
@@ -46,37 +46,41 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData',
         /**
          * event: on import
          */
-        $onImport: function () {
-            var self           = this;
-            var Elm            = this.getElm();
-            var ChangeEmailElm = Elm.getElement('.quiqqer-frontendUsers-userdata-email-edit');
-            var EmailNewElm    = Elm.getElement('.quiqqer-frontendUsers-userdata-email-new');
-            var EmailNewInput  = Elm.getElement('input[name="emailNew"]');
-            var ProfileNode    = Elm.getParent('.quiqqer-frontendUsers-controls-profile');
+        $onImport: function() {
+            const self = this;
+            const Elm = this.getElm();
+            const ChangeEmailElm = Elm.querySelector('[data-name="email-edit"]');
+            const EmailNewElm = Elm.querySelector('[data-name="email-new"]');
+            const EmailNewInput = Elm.querySelector('input[name="emailNew"]');
+            let ProfileNode = Elm.querySelector(
+                '[data-qui="package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile"]'
+            );
 
             if (ProfileNode) {
-                QUIControlUtils.getControlByElement(ProfileNode).then(function (ProfileControl) {
+                QUIControlUtils.getControlByElement(ProfileNode).then(function(ProfileControl) {
                     ProfileControl.addEvents({
-                        onSave     : function () {
-                            EmailNewElm.addClass('quiqqer-frontendUsers-userdata-email__hidden');
+                        onSave: function() {
+                            EmailNewElm.addAttribute('data-hidden');
+                            // EmailNewElm.addClass('quiqqer-frontendUsers-userdata-email__hidden');
                             EmailNewInput.value = '';
                         },
-                        onSaveError: function () {
+                        onSaveError: function() {
                             EmailNewInput.value = '';
                             EmailNewInput.focus();
                         }
                     });
-                }, function () {
+                }, function() {
                     // do nothing
                 });
             }
 
-            ChangeEmailElm.addEvent('click', function () {
-                EmailNewElm.removeClass('quiqqer-frontendUsers-userdata-email__hidden');
+            ChangeEmailElm.addEvent('click', function() {
+                // EmailNewElm.removeClass('quiqqer-frontendUsers-userdata-email__hidden');
+                EmailNewElm.removeAttribute('data-hidden');
                 EmailNewInput.focus();
 
                 // resize profile
-                var ProfileNode = self.getElm().getParent(
+                ProfileNode = self.getElm().getParent(
                     '[data-qui="package/quiqqer/frontend-users/bin/frontend/controls/profile/Profile"]'
                 );
 
@@ -84,22 +88,22 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData',
                     return;
                 }
 
-                var Profile = QUI.Controls.getById(ProfileNode.get('data-quiid'));
+                const Profile = QUI.Controls.getById(ProfileNode.get('data-quiid'));
 
                 if (Profile) {
                     Profile.resize();
                 }
             });
 
-            var CheckMail = function (event) {
-                var email = event.target.value.trim();
+            const CheckMail = function(event) {
+                const email = event.target.value.trim();
 
                 Promise.all([
                     Registration.emailSyntaxValidation(email),
                     Registration.emailValidation(email)
-                ]).then(function (result) {
+                ]).then(function(result) {
                     var emailSyntaxValid = result[0];
-                    var emailValid       = result[1];
+                    var emailValid = result[1];
 
                     if (emailSyntaxValid && emailValid) {
                         self.$clearEmailErrorMsg();
@@ -131,7 +135,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData',
          *
          * @param {String} msg
          */
-        $showEmailErrorMsg: function (msg) {
+        $showEmailErrorMsg: function(msg) {
             if (!this.$EmailErrorMsgElm) {
                 this.$EmailErrorMsgElm = new Element('div', {
                     'class': 'content-message-error'
@@ -144,7 +148,7 @@ define('package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData',
         /**
          * Hide error msg for e-mail change
          */
-        $clearEmailErrorMsg: function () {
+        $clearEmailErrorMsg: function() {
             if (this.$EmailErrorMsgElm) {
                 this.$EmailErrorMsgElm.destroy();
                 this.$EmailErrorMsgElm = null;
diff --git a/captainhook.json b/captainhook.json
new file mode 100644
index 0000000000000000000000000000000000000000..3702e1a358868bedd5ff4c7eae40bb1abb589267
--- /dev/null
+++ b/captainhook.json
@@ -0,0 +1,13 @@
+{
+    "pre-commit": {
+        "enabled": true,
+        "actions": [
+            {
+                "action": "\\CaptainHook\\App\\Hook\\PHP\\Action\\Linting"
+            },
+            {
+                "action": "composer test"
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/composer.json b/composer.json
index ec87d3b880d471a9fedfae04201e016d11d2371f..f758f19c49256e0eca1f34bc8e235f2ebe58c78c 100644
--- a/composer.json
+++ b/composer.json
@@ -1,44 +1,86 @@
 {
-  "name": "quiqqer/frontend-users",
-  "type": "quiqqer-module",
-  "description": "The Frontend Users module extends QUIQQER with a profile extension and a registration for users.",
-  "license": "GPL-3.0+",
-  "authors": [
-    {
-      "name": "Henning Leutz",
-      "email": "support@pcsg.de",
-      "homepage": "https://www.pcsg.de",
-      "role": "Developer"
+    "name": "quiqqer/frontend-users",
+    "type": "quiqqer-module",
+    "description": "The Frontend Users module extends QUIQQER with a profile extension and a registration for users.",
+    "license": "GPL-3.0+",
+    "authors": [
+        {
+            "name": "Henning Leutz",
+            "email": "support@pcsg.de",
+            "homepage": "https://www.pcsg.de",
+            "role": "Developer"
+        },
+        {
+            "name": "Patrick Müller",
+            "email": "support@pcsg.de",
+            "homepage": "https://www.pcsg.de",
+            "role": "Developer"
+        },
+        {
+            "name": "Jan Wennrich",
+            "email": "support@pcsg.de",
+            "homepage": "https://www.pcsg.de",
+            "role": "Developer"
+        }
+    ],
+    "support": {
+        "email": "support@pcsg.de"
     },
-    {
-      "name": "Patrick M\u00fcller",
-      "email": "support@pcsg.de",
-      "homepage": "https://www.pcsg.de",
-      "role": "Developer"
+    "require": {
+        "quiqqer/core": "^2",
+        "quiqqer/countries": "^2",
+        "quiqqer/verification": "^3",
+        "quiqqer/tooltips": "^2",
+        "quiqqer/data-layer": "^2"
     },
-    {
-      "name": "Jan Wennrich",
-      "email": "support@pcsg.de",
-      "homepage": "https://www.pcsg.de",
-      "role": "Developer"
-    }
-  ],
-  "support": {
-    "email": "support@pcsg.de"
-  },
-  "require": {
-    "quiqqer/core": "^2",
-    "quiqqer/countries": "^2",
-    "quiqqer/verification": "^2",
-    "quiqqer/tooltips": "^2",
-    "quiqqer/data-layer": "^2"
-  },
-  "suggest": {
-    "quiqqer/rest": "User registration via REST API"
-  },
-  "autoload": {
-    "psr-4": {
-      "QUI\\FrontendUsers\\": "src/QUI/FrontendUsers"
+    "suggest": {
+        "quiqqer/rest": "User registration via REST API"
+    },
+    "autoload": {
+        "psr-4": {
+            "QUI\\FrontendUsers\\": "src/QUI/FrontendUsers"
+        }
+    },
+    "scripts": {
+        "test": [
+            "@dev:lint",
+            "@dev:phpunit"
+        ],
+        "dev:phpunit": "./tools/phpunit",
+        "dev:lint": [
+            "@dev:lint:phpstan",
+            "@dev:lint:style"
+        ],
+        "dev:lint:phpstan": "./tools/phpstan",
+        "dev:lint:style": "./tools/phpcs",
+        "dev:lint:style:fix": "./tools/phpcbf",
+        "dev:init": [
+            "@dev:init:check-requirements",
+            "@dev:init:tools",
+            "@dev:init:git-hooks"
+        ],
+        "dev:init:check-requirements": [
+            "which composer > /dev/null || (echo 'Error: composer has to be globally installed'; exit 1)",
+            "which phive > /dev/null || (echo 'Error: PHIVE has to be globally installed'; exit 1)"
+        ],
+        "dev:init:tools": "phive install --temporary",
+        "dev:init:git-hooks": "./tools/captainhook install --only-enabled --force"
+    },
+    "scripts-aliases": {
+        "test": [
+            "dev:test"
+        ]
+    },
+    "scripts-descriptions": {
+        "test": "Runs linting, static analysis, and unit tests.",
+        "dev:phpunit": "Run PHPUnit test suites",
+        "dev:lint": "Run PHPStan and code style check",
+        "dev:lint:phpstan": "Run PHPStan",
+        "dev:lint:style": "Run code style check (PHP_CodeSniffer)",
+        "dev:lint:style:fix": "Try to fix code style errors automatically",
+        "dev:init": "Initialize the developer tooling (tools and git hooks)",
+        "dev:init:check-requirements": "Check if the necessary requirements are met",
+        "dev:init:tools": "Install all developer tools (requires PHIVE)",
+        "dev:init:git-hooks": "Install all git hooks (may require tools to be installed)"
     }
-  }
-}
+}
\ No newline at end of file
diff --git a/locale.xml b/locale.xml
index dbb2033b9db7b0ae907d17a830cbb0fffe67d0e5..7fe2690fde37151846673484a34aba51921c633d 100644
--- a/locale.xml
+++ b/locale.xml
@@ -460,6 +460,14 @@
             <en>
                 <![CDATA[Automatic redirect to the specified page after the user has been successfully activated. The automatic forwarding takes place after <b>10 seconds</b>. <b>Note:</b> Does not apply if users are required to be activated <b>manually</b> after a registration.]]></en>
         </locale>
+        <locale name="settings.reloadOnSuccess.title">
+            <de><![CDATA[Seite neu laden nach Registrierung]]></de>
+            <en><![CDATA[Reload page after registration]]></en>
+        </locale>
+        <locale name="settings.reloadOnSuccess.description">
+            <de><![CDATA[Nach einer erfolgreichen Registrierung soll die Seite neu geladen werden. Diese Einstellung überschreibt die Einstellung "Automatische Weiterleitung nach Aktivierung".]]></de>
+            <en><![CDATA[After successful registration the page should be reloaded. This setting overwrites the setting "Auto redirect on activation".]]></en>
+        </locale>
         <locale name="settings.redirectOnLogin.title">
             <de><![CDATA[Automatische Weiterleitung nach Login]]></de>
             <en><![CDATA[Auto redirect on log in]]></en>
@@ -822,11 +830,24 @@
             <en><![CDATA[Gravatar]]></en>
         </locale>
 
-        <locale name="dialog.frontend-users.delete.address">
+        <locale name="dialog.frontend-users.btn.cancel">
+            <de><![CDATA[Abbrechen]]></de>
+            <en><![CDATA[Cancel]]></en>
+        </locale>
+
+        <locale name="dialog.frontend-users.address.delete.title">
+            <de><![CDATA[Adresse löschen]]></de>
+            <en><![CDATA[Delete address]]></en>
+        </locale>
+        <locale name="dialog.frontend-users.address.delete.message">
             <de><![CDATA[Möchten Sie die Adresse wirklichen löschen?]]></de>
             <en><![CDATA[Do you really want to delete the address?]]></en>
         </locale>
-        <locale name="dialog.frontend-users.title">
+        <locale name="dialog.frontend-users.address.delete.btn">
+            <de><![CDATA[Adresse löschen]]></de>
+            <en><![CDATA[Delete address]]></en>
+        </locale>
+        <locale name="dialog.frontend-users.edit.title">
             <de><![CDATA[Neue Adresse anlegen]]></de>
             <en><![CDATA[Create new address]]></en>
         </locale>
@@ -1642,6 +1663,32 @@ The e-mail address for your user account on [host] has been changed to the addre
 </p>]]></en>
         </locale>
 
+        <!-- E-Mail-Address confirm mail -->
+        <locale name="mail.confirm_email_address.subject">
+            <de><![CDATA[Bestätigung Ihrer E-Mail-Adresse]]></de>
+            <en><![CDATA[Confirm your email address]]></en>
+        </locale>
+        <locale name="mail.confirm_email_address.body" html="true">
+            <de><![CDATA[<h1>Hallo [username]!</h1>
+<p>
+Bitte bestätigen Sie Ihre E-Mail-Adresse für Ihr Benutzerkonto auf [host]. Für die Bestätigung öffnen Sie bitte folgenden Link:
+<br><br>
+<a href="[confirmLink]">[confirmLink]</a>
+</p>
+<p>
+<b>Hinweis:</b> Sollten Sie diese E-Mail nicht veranlasst haben, können Sie sie einfach ignorieren.
+</p>]]></de>
+            <en><![CDATA[<h1>Hello [username]!</h1>
+<p>
+Please confirm your e-mail address for your user account on [host]. To confirm your e-mail address, please click on the following link:
+<br>
+<a href="[confirmLink]">[confirmLink]</a>
+</p>
+<p>
+<b>Note:</b> If you have not initiated this email, please ignore this it.
+</p>]]></en>
+        </locale>
+
         <!-- User delete confirm mail -->
         <locale name="mail.delete_user_confirm.subject">
             <de><![CDATA[Löschung Ihres Benutzerkontos]]></de>
@@ -1771,36 +1818,36 @@ The deletion of your user account on [host] was requested on [date]. Please conf
         <locale name="control.sign.up.terms_of_use_and_privacy_policy.label" html="true">
             <de><![CDATA[
             Durch das Erstellen eines Benutzerkontos versichere ich die
-            <a href="[termsOfUseUrl]">[termsOfUseSiteTitle]</a> und
-            <a href="[privacyPolicyUrl]">[privacyPolicySiteTitle]</a>
+            <a href="[termsOfUseUrl]" data-id="[termsOfUseSiteId]">[termsOfUseSiteTitle]</a> und
+            <a href="[privacyPolicyUrl]" data-id="[privacyPolicySiteId]">[privacyPolicySiteTitle]</a>
             gelesen zu haben und erkläre mich mit diesen einverstanden.
             ]]></de>
             <en><![CDATA[
             By creating a user account, I confirm that I have read and agree to the
-            <a href="[termsOfUseUrl]">[termsOfUseSiteTitle]</a> and
-            <a href="[privacyPolicyUrl]">[privacyPolicySiteTitle]</a>.
+            <a href="[termsOfUseUrl]" data-id="[termsOfUseSiteId]">[termsOfUseSiteTitle]</a> and
+            <a href="[privacyPolicyUrl]" data-id="[privacyPolicySiteId]">[privacyPolicySiteTitle]</a>.
             ]]></en>
         </locale>
         <locale name="control.sign.up.terms_of_use.label" html="true">
             <de><![CDATA[
             Durch das Erstellen eines Benutzerkontos versichere ich die
-            <a href="[termsOfUseUrl]">[termsOfUseSiteTitle]</a> gelesen zu haben
+            <a href="[termsOfUseUrl]" data-id="[termsOfUseSiteId]">[termsOfUseSiteTitle]</a> gelesen zu haben
             und erkläre mich mit diesen einverstanden.
             ]]></de>
             <en><![CDATA[
             By creating a user account, I confirm that I have read and agree to the
-            <a href="[termsOfUseUrl]">[termsOfUseSiteTitle]</a>.
+            <a href="[termsOfUseUrl]" data-id="[termsOfUseSiteId]">[termsOfUseSiteTitle]</a>.
             ]]></en>
         </locale>
         <locale name="control.sign.up.privacy_policy.label" html="true">
             <de><![CDATA[
             Durch das Erstellen eines Benutzerkontos versichere ich die
-            <a href="[privacyPolicyUrl]">[privacyPolicySiteTitle]</a>
+            <a href="[privacyPolicyUrl]" data-id="[privacyPolicySiteId]">[privacyPolicySiteTitle]</a>
             gelesen zu haben und erkläre mich mit diesen einverstanden.
             ]]></de>
             <en><![CDATA[
             By creating a user account, I confirm that I have read and agree to the
-            <a href="[privacyPolicyUrl]">[privacyPolicySiteTitle]</a>.
+            <a href="[privacyPolicyUrl]" data-id="[privacyPolicySiteId]">[privacyPolicySiteTitle]</a>.
             ]]></en>
         </locale>
         <locale name="control.sign.up.type.login.in.button">
@@ -1975,6 +2022,58 @@ The deletion of your user account on [host] was requested on [date]. Please conf
             ]]></en>
         </locale>
 
+        <locale name="mail.text.confirmEmail.title">
+            <de><![CDATA[Frontend Users: Bestätigung der E-Mail-Adresse]]></de>
+            <en><![CDATA[Frontend Users: Confirmation of e-mail address]]></en>
+        </locale>
+        <locale name="mail.text.confirmEmail.description">
+            <de><![CDATA[
+            E-Mail zur Bestägigung einer E-Mail-Adresse.
+            ]]></de>
+            <en><![CDATA[
+            Email for confirmation of an email address.
+            ]]></en>
+        </locale>
+        <locale name="order.confirmEmail.subject.description">
+            <de><![CDATA[
+            <p>Betreff der Bestätigungs--E-Mail. Verfügbare Variablen:</p>
+            <ul>
+                <li><b>[host]:</b> Host des Projektes (System)</li>
+            </ul>
+            ]]></de>
+            <en><![CDATA[
+            <p>Subject of the confirmation e-mail. Available variables:</p>
+            <ul>
+                <li><b>[host]:</b> Host of the project (system)</li>
+            </ul>
+            ]]></en>
+        </locale>
+        <locale name="order.confirmEmail.body.description">
+            <de><![CDATA[
+            <p>Inhalt der Bestätigungs-E-Mail. Verfügbare Variablen:</p>
+            <ul>
+                <li><b>[host]:</b> Host des Projektes (System)</li>
+                <li><b>[userId]:</b> Benutzer ID</li>
+                <li><b>[email]:</b> E-Mail des Benutzers</li>
+                <li><b>[confirmLink]:</b> Bestätigungs-Link (muss enthalten sein!)</li>
+                <li><b>[username]:</b> Benutzername</li>
+                <li><b>[userFirstName]:</b> Vorname des Benutzers (falls vorhanden)</li>
+                <li><b>[userLastName]:</b> Nachname des Benutzers (falls vorhanden)</li>
+            </ul>
+            ]]></de>
+            <en><![CDATA[
+            <p>Content of the confirmation e-mail. Available variables:</p>
+            <ul>
+                <li><b>[host]:</b> Host of the project (system)</li>
+                <li><b>[userId]:</b> User id of the user</li>
+                <li><b>[email]:</b> E mail of the user</li>
+                <li><b>[confirmLink]:</b> Confirmation link (must be included!)</li>
+                <li><b>[username]:</b> Username</li>
+                <li><b>[userFirstName]:</b> First name of the user (if available)</li>
+                <li><b>[userLastName]:</b> Last name of the user (if available)</li>
+            </ul>
+            ]]></en>
+        </locale>
 
         <locale name="mail.text.changeEmail.title">
             <de><![CDATA[Frontend Users: E-Mail ändern]]></de>
@@ -2135,6 +2234,10 @@ The deletion of your user account on [host] was requested on [date]. Please conf
             <de><![CDATA[Automatische Aktivierung]]></de>
             <en><![CDATA[Auto activation]]></en>
         </locale>
+        <locale name="controls.settings.registrars.template.activationModeOptionAutoWithEmailConfirm">
+            <de><![CDATA[Automatische Aktivierung (Link zur Bestätigung der E-Mail-Adresse wird trotzdem versandt)]]></de>
+            <en><![CDATA[Auto activation (link to confirm email address will be sent regardless)]]></en>
+        </locale>
         <locale name="controls.settings.registrars.template.activationModeOptionManual">
             <de><![CDATA[Manuelle Aktivierung (über Benutzer-Verwaltung)]]></de>
             <en><![CDATA[Manual activation (via User Management)]]></en>
diff --git a/phpstan.dist.neon b/phpstan.dist.neon
index aa10a371ae2d7b11f3021e6489cdb3fb8cc1edd7..ef886a95df9495ee50e39ea453be2b1086293062 100644
--- a/phpstan.dist.neon
+++ b/phpstan.dist.neon
@@ -2,11 +2,16 @@ includes:
 	- phpstan-baseline.neon
 
 parameters:
-    level: 1
+    level: 5
     paths:
         - src
         - ajax
         - types
+    excludePaths:
+        # Ignore files that use classes from optional packages
+        - src/QUI/FrontendUsers/ErpProvider.php
+        - src/QUI/FrontendUsers/Rest/Provider.php
+        - src/QUI/FrontendUsers/GdprDataProvider.php
     bootstrapFiles:
         - tests/phpstan-bootstrap.php
     treatPhpDocTypesAsCertain: false
diff --git a/phpunit.dist.xml b/phpunit.dist.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f6c7becf0c12757beb871a9333e2d81e02aa7cae
--- /dev/null
+++ b/phpunit.dist.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="tests/phpunit-bootstrap.php">
+    <testsuites>
+        <testsuite name="Tests">
+            <directory>tests/</directory>
+        </testsuite>
+    </testsuites>
+</phpunit>
diff --git a/settings.xml b/settings.xml
index 5ccfa7c5a639c1b4933a1f7715f225dc12030f37..9b2941aecadda3f28758b013d3d101309ab6ee49 100644
--- a/settings.xml
+++ b/settings.xml
@@ -120,6 +120,10 @@
                 <conf name="autoRedirectOnSuccess">
                     <type><![CDATA[string]]></type>
                 </conf>
+                <conf name="reloadOnSuccess">
+                    <type><![CDATA[bool]]></type>
+                    <defaultvalue>0</defaultvalue>
+                </conf>
                 <conf name="addressFields">
                     <type><![CDATA[string]]></type>
                 </conf>
@@ -582,6 +586,16 @@
                             </description>
                         </input>
 
+                        <input conf="registration.reloadOnSuccess" type="checkbox">
+                            <text>
+                                <locale group="quiqqer/frontend-users" var="settings.reloadOnSuccess.title"/>
+                            </text>
+                            <description>
+                                <locale group="quiqqer/frontend-users"
+                                        var="settings.reloadOnSuccess.description"/>
+                            </description>
+                        </input>
+
                         <input conf="registration.useCaptcha" type="checkbox">
                             <text>
                                 <locale group="quiqqer/frontend-users" var="settings.useCaptcha.title"/>
diff --git a/src/QUI/FrontendUsers/AbstractFrontendUsersLinkVerificationHandler.php b/src/QUI/FrontendUsers/AbstractFrontendUsersLinkVerificationHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..bcd91ea09c496de2645f4f6599e409b8aba891fb
--- /dev/null
+++ b/src/QUI/FrontendUsers/AbstractFrontendUsersLinkVerificationHandler.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace QUI\FrontendUsers;
+
+use QUI;
+use QUI\Projects\Project;
+use QUI\Verification\AbstractLinkVerificationHandler;
+use QUI\Verification\Entity\LinkVerification;
+
+/**
+ * Base class for all link verification handlers of quiqqer/frontend-users.
+ */
+abstract class AbstractFrontendUsersLinkVerificationHandler extends AbstractLinkVerificationHandler
+{
+    /**
+     * Get the Project this ActivationVerification is intended for
+     *
+     * @param LinkVerification $verification
+     * @return Project|null
+     * @throws QUI\Exception
+     */
+    protected function getProject(LinkVerification $verification): ?Project
+    {
+        $project = $verification->getCustomDataEntry('project');
+        $projectLang = $verification->getCustomDataEntry('projectLang');
+
+        if (empty($project) || empty($projectLang)) {
+            return null;
+        }
+
+        return QUI::getProjectManager()->getProject($project, $projectLang);
+    }
+}
diff --git a/src/QUI/FrontendUsers/AbstractRegistrar.php b/src/QUI/FrontendUsers/AbstractRegistrar.php
index 4739df041943db81bcea7d3942784688ebff5765..98dcf6f53722e8c6a8bcfcff38d716a08315a226 100644
--- a/src/QUI/FrontendUsers/AbstractRegistrar.php
+++ b/src/QUI/FrontendUsers/AbstractRegistrar.php
@@ -36,7 +36,7 @@ abstract public function validate(): array;
     abstract public function getInvalidFields(): array;
 
     /**
-     * @return mixed
+     * @return string
      */
     abstract public function getUsername(): string;
 
@@ -56,7 +56,7 @@ abstract public function onRegistered(QUI\Interfaces\Users\User $User): void;
      * @param QUI\Locale|null $Locale (optional) - If omitted use QUI::getLocale()
      * @return string
      */
-    abstract public function getTitle(QUI\Locale $Locale = null): string;
+    abstract public function getTitle(null | QUI\Locale $Locale = null): string;
 
     /**
      * Get description
@@ -64,7 +64,7 @@ abstract public function getTitle(QUI\Locale $Locale = null): string;
      * @param QUI\Locale|null $Locale (optional) - If omitted use QUI::getLocale()
      * @return string
      */
-    abstract public function getDescription(QUI\Locale $Locale = null): string;
+    abstract public function getDescription(null | QUI\Locale $Locale = null): string;
 
     /**
      * Return an icon for the registrar
diff --git a/src/QUI/FrontendUsers/ActivationVerification.php b/src/QUI/FrontendUsers/ActivationLinkVerification.php
similarity index 53%
rename from src/QUI/FrontendUsers/ActivationVerification.php
rename to src/QUI/FrontendUsers/ActivationLinkVerification.php
index c613d0a99f653f4d455bf96d8b99082caa82395e..e382a979eedff31d4a75f4c8c264532616ca181a 100644
--- a/src/QUI/FrontendUsers/ActivationVerification.php
+++ b/src/QUI/FrontendUsers/ActivationLinkVerification.php
@@ -4,7 +4,11 @@
 
 use QUI;
 use QUI\Exception;
-use QUI\Verification\AbstractVerification;
+use QUI\ExceptionStack;
+use QUI\Projects\Project;
+use QUI\Verification\Entity\LinkVerification;
+use QUI\Verification\Enum\VerificationErrorReason;
+use QUI\Verification\Entity\AbstractVerification;
 
 /**
  * Class ActivationVerification
@@ -13,16 +17,17 @@
  *
  * @package QUI\FrontendUsers
  */
-class ActivationVerification extends AbstractVerification
+class ActivationLinkVerification extends AbstractFrontendUsersLinkVerificationHandler
 {
     /**
      * Get the duration of a Verification (minutes)
      *
-     * @return int|false - duration in minutes;
+     * @param AbstractVerification $verification
+     * @return int|null - duration in minutes;
      * if this method returns false use the module setting default value
      * @throws Exception
      */
-    public function getValidDuration(): bool|int
+    public function getValidDuration(AbstractVerification $verification): ?int
     {
         $settings = Handler::getInstance()->getMailSettings();
         return (int)$settings['verificationValidityDuration'];
@@ -31,17 +36,18 @@ public function getValidDuration(): bool|int
     /**
      * Execute this method on successful verification
      *
+     * @param LinkVerification $verification
      * @return void
+     * @throws \Exception
      */
-    public function onSuccess(): void
+    public function onSuccess(LinkVerification $verification): void
     {
-        $userId = $this->getIdentifier();
-
         try {
-            $User = QUI::getUsers()->get($userId);
-            $User->activate(false, QUI::getUsers()->getSystemUser());
+            $userUuid = $verification->getCustomDataEntry('uuid');
+            $User = QUI::getUsers()->get($userUuid);
+            $User->activate('', QUI::getUsers()->getSystemUser());
 
-            Utils::setUserEmailVerified($User);
+            Utils::setDefaultUserEmailVerified($User);
 
             QUI::getEvents()->fireEvent(
                 'quiqqerFrontendUsersUserActivate',
@@ -50,21 +56,20 @@ public function onSuccess(): void
                     Handler::getInstance()->getRegistrar($User->getAttribute(Handler::USER_ATTR_REGISTRAR))
                 ]
             );
-        } catch (QUI\Users\Exception $Exception) {
-            QUI\System\Log::addWarning(
-                'quiqqer/frontend-users -> ActivationVerification :: ' . $Exception->getMessage()
-            );
         } catch (\Exception $Exception) {
             QUI\System\Log::writeException($Exception);
+            throw $Exception;
         }
     }
 
     /**
      * Execute this method on unsuccessful verification
      *
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
      * @return void
      */
-    public function onError(): void
+    public function onError(LinkVerification $verification, VerificationErrorReason $reason): void
     {
         // nothing
     }
@@ -72,10 +77,11 @@ public function onError(): void
     /**
      * This message is displayed to the user on successful verification
      *
+     * @param LinkVerification $verification
      * @return string
      * @throws Exception
      */
-    public function getSuccessMessage(): string
+    public function getSuccessMessage(LinkVerification $verification): string
     {
         $registrationSetting = Handler::getInstance()->getRegistrationSettings();
 
@@ -91,10 +97,11 @@ public function getSuccessMessage(): string
     /**
      * This message is displayed to the user on unsuccessful verification
      *
-     * @param string $reason - The reason for the error (see \QUI\Verification\Verifier::REASON_)
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
      * @return string
      */
-    public function getErrorMessage(string $reason): string
+    public function getErrorMessage(LinkVerification $verification, VerificationErrorReason $reason): string
     {
         return '';
     }
@@ -102,23 +109,26 @@ public function getErrorMessage(string $reason): string
     /**
      * Automatically redirect the user to this URL on successful verification
      *
-     * @return string|false - If this method returns false, no redirection takes place
+     * @param LinkVerification $verification
+     * @return string|null - If this method returns false, no redirection takes place
      * @throws Exception
      */
-    public function getOnSuccessRedirectUrl(): bool|string
+    public function getOnSuccessRedirectUrl(LinkVerification $verification): ?string
     {
+        $project = $this->getProject($verification);
+
+        if (!$project) {
+            return null;
+        }
+
         $RegistrarHandler = Handler::getInstance();
-        $RegistrationSite = $RegistrarHandler->getRegistrationSignUpSite(
-            $this->getProject()
-        );
+        $RegistrationSite = $RegistrarHandler->getRegistrationSignUpSite($project);
 
         if (empty($RegistrationSite)) {
-            $RegistrationSite = $RegistrarHandler->getRegistrationSite(
-                $this->getProject()
-            );
+            $RegistrationSite = $RegistrarHandler->getRegistrationSite($project);
 
             if (empty($RegistrationSite)) {
-                return false;
+                return null;
             }
         }
 
@@ -126,30 +136,35 @@ public function getOnSuccessRedirectUrl(): bool|string
             'success'
         ], [
             'success' => 'activation',
-            'registrar' => $this->getRegistrarHash()
+            'registrar' => $this->getRegistrarHash($verification)
         ]);
     }
 
     /**
      * Automatically redirect the user to this URL on unsuccessful verification
      *
-     * @return string|false - If this method returns false, no redirection takes place
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
+     * @return string|null - If this method returns false, no redirection takes place
      * @throws Exception
+     * @throws ExceptionStack
      */
-    public function getOnErrorRedirectUrl(): bool|string
+    public function getOnErrorRedirectUrl(LinkVerification $verification, VerificationErrorReason $reason): ?string
     {
         $RegistrarHandler = Handler::getInstance();
-        $RegistrationSite = $RegistrarHandler->getRegistrationSignUpSite(
-            $this->getProject()
-        );
+        $project = $this->getProject($verification);
+
+        if (!$project) {
+            return null;
+        }
+
+        $RegistrationSite = $RegistrarHandler->getRegistrationSignUpSite($project);
 
         if (empty($RegistrationSite)) {
-            $RegistrationSite = $RegistrarHandler->getRegistrationSite(
-                $this->getProject()
-            );
+            $RegistrationSite = $RegistrarHandler->getRegistrationSite($project);
 
             if (empty($RegistrationSite)) {
-                return false;
+                return null;
             }
         }
 
@@ -157,35 +172,24 @@ public function getOnErrorRedirectUrl(): bool|string
             'error'
         ], [
             'error' => 'activation',
-            'registrar' => $this->getRegistrarHash()
+            'registrar' => $this->getRegistrarHash($verification)
         ]);
     }
 
-    /**
-     * Get the Project this ActivationVerification is intended for
-     *
-     * @return QUI\Projects\Project
-     * @throws Exception
-     */
-    protected function getProject(): QUI\Projects\Project
-    {
-        $additionalData = $this->getAdditionalData();
-        return QUI::getProjectManager()->getProject($additionalData['project'], $additionalData['projectLang']);
-    }
-
     /**
      * Get hash of registrar used for this Verification
      *
+     * @param LinkVerification $verification
      * @return string
      */
-    protected function getRegistrarHash(): string
+    protected function getRegistrarHash(LinkVerification $verification): string
     {
-        $data = $this->getAdditionalData();
+        $registrar = $verification->getCustomDataEntry('registrar');
 
-        if (empty($data['registrar'])) {
+        if (empty($registrar)) {
             return '';
         }
 
-        return $data['registrar'];
+        return $registrar;
     }
 }
diff --git a/src/QUI/FrontendUsers/Console/AnonymiseUsers.php b/src/QUI/FrontendUsers/Console/AnonymiseUsers.php
index 223c6f08ce8eda3107dfd8abf16ae3e3d8506071..7a680cef405877fd5f13155c7a50e3ee3fd5d001 100644
--- a/src/QUI/FrontendUsers/Console/AnonymiseUsers.php
+++ b/src/QUI/FrontendUsers/Console/AnonymiseUsers.php
@@ -59,13 +59,13 @@ public function execute(): void
         // EMAIL
 
         $this->writeLn(
-            "Use the following host handle for email-addresses [@foo.bar]: "
+            "Use the following host handle for email-addresses [@foobar.local]: "
         );
 
         $emailHandle = $this->readInput();
 
         if (empty($emailHandle)) {
-            $emailHandle = '@foo.bar';
+            $emailHandle = '@foobar.local';
         }
 
         // SUMMARY
diff --git a/src/QUI/FrontendUsers/Console/SendUserMails.php b/src/QUI/FrontendUsers/Console/SendUserMails.php
index 7fa403b912ba4a9022f16902496a7e2f0cd5c52c..f0027b3a4949ed5a7f5c1c543b7fde3cdeb2e10e 100644
--- a/src/QUI/FrontendUsers/Console/SendUserMails.php
+++ b/src/QUI/FrontendUsers/Console/SendUserMails.php
@@ -398,7 +398,7 @@ protected function setLimits(array $limits): void
      *
      * @return array|false - Limit config or false if limits not yet configured
      */
-    protected function getLimits(): bool|array
+    protected function getLimits(): bool | array
     {
         try {
             $limitsFile = QUI::getPackage('quiqqer/frontend-users')->getVarDir() . 'send_user_mails_limits';
@@ -585,7 +585,7 @@ protected function isMailAllowed(): bool
      * @param string|null $testMailAddress (optional) - If set, a single test mail will be sent to this address
      * @return void
      */
-    protected function sendMails(string $testMailAddress = null): void
+    protected function sendMails(null | string $testMailAddress = null): void
     {
         $Users = QUI::getUsers();
         $SystemUser = $Users->getSystemUser();
@@ -630,7 +630,7 @@ protected function sendMails(string $testMailAddress = null): void
                     );
 
                     sleep(60);
-                } while (!$mailAllowed);
+                } while (!$mailAllowed); // @phpstan-ignore-line
             }
 
             if (!empty($recipient['firstname']) && !empty($recipient['lastname'])) {
diff --git a/src/QUI/FrontendUsers/Controls/Address/Address.Create.html b/src/QUI/FrontendUsers/Controls/Address/Address.Create.html
index b267ff9b8069ce3670198dce4f681303c47dc3fd..42059bd8c9b6593843bd84833c57ab999fb10d7a 100644
--- a/src/QUI/FrontendUsers/Controls/Address/Address.Create.html
+++ b/src/QUI/FrontendUsers/Controls/Address/Address.Create.html
@@ -1,7 +1,5 @@
 <section class="quiqqer-frontend-users-address-create">
-    <header>
-        <h1>{locale group="quiqqer/frontend-users" var="dialog.frontend-users.title"}</h1>
-    </header>
+    <h2>{locale group="quiqqer/frontend-users" var="dialog.frontend-users.title"}</h2>
 
     {template_event name="quiqqer::frontend-users::user-address-create-begin" User=$User}
 
@@ -55,12 +53,14 @@
             {locale group="quiqqer/frontend-users" var="street_no"}
             {if $settings.street_no.required}*{/if}
         </span>
-        <input type="text" name="street" value="" autocomplete="shipping street-address" {if $settings.street_no.required}required{/if}
-               placeholder="{locale group='quiqqer/frontend-users' var='street'}"
-        />
-        <input type="text" name="street_number" value=""
-               placeholder="{locale group='quiqqer/frontend-users' var='house_no'}"
-        />
+        <div class="address-street--2-col">
+            <input type="text" name="street" value="" autocomplete="shipping street-address" {if $settings.street_no.required}required{/if}
+                   placeholder="{locale group='quiqqer/frontend-users' var='street'}"
+            />
+            <input type="text" name="street_number" value=""
+                   placeholder="{locale group='quiqqer/frontend-users' var='house_no'}"
+            />
+        </div>
     </label>
     {/if}
 
@@ -95,7 +95,7 @@
     {/if}
 
     {if $settings.country.show}
-    <label class="quiqqer-frontendUsers-userdata-create-address-country">
+    <label class="quiqqer-frontendUsers-userdata-address-country">
         <span>
             {locale group="quiqqer/frontend-users" var="country"}
             {if $settings.country.required}*{/if}
@@ -142,7 +142,7 @@
 
     {template_event name="quiqqer::frontend-users::user-address-create-end" User=$User}
 
-    <button type="submit" name="createSave" value="1" class="quiqqer-frontend-users-address-edit-button">
+    <button type="submit" name="createSave" value="1" class="btn btn-primary quiqqer-frontend-users-address-edit-button">
         {locale group="quiqqer/frontend-users" var="dialog.frontend-users.create.address.btn"}
     </button>
 
diff --git a/src/QUI/FrontendUsers/Controls/Address/Address.Delete.html b/src/QUI/FrontendUsers/Controls/Address/Address.Delete.html
index 7b249d5a6b3adce8d3d14a718993f25072af86d1..5d6515f5d615515993e0da91c12e047653642679 100644
--- a/src/QUI/FrontendUsers/Controls/Address/Address.Delete.html
+++ b/src/QUI/FrontendUsers/Controls/Address/Address.Delete.html
@@ -1,17 +1,15 @@
 <section class="quiqqer-frontend-users-address-delete">
-    <header>
-        <h1>{locale group="quiqqer/frontend-users" var="ordering.step.title.Address.delete"}</h1>
-    </header>
+    <h2>{locale group="quiqqer/frontend-users" var="dialog.frontend-users.address.delete.title"}</h2>
 
     <div class="quiqqer-frontend-users-address-delete-container">
-        {locale group="quiqqer/order" var="ordering.step.title.Address.delete.message"}
+        {locale group="quiqqer/frontend-users" var="dialog.frontend-users.address.delete.message"}
 
         {$Address->render()}
 
         <button type="submit" name="step" value="{$this->getName()}"
                 class="quiqqer-frontend-users-address-delete-container-deleteBtn"
         >
-            {locale group="quiqqer/order" var="ordering.step.title.Address.delete.btn"}
+            {locale group="quiqqer/frontend-users" var="dialog.frontend-users.address.delete.btn"}
         </button>
 
         <input type="hidden" name="addressId" value="{$Address->getUUID()}"/>
diff --git a/src/QUI/FrontendUsers/Controls/Address/Address.Edit.html b/src/QUI/FrontendUsers/Controls/Address/Address.Edit.html
index b0515acadcd3d28d669f256f37caa32bc49bcd27..defe48efabd22619367de1832027b033e90863f8 100644
--- a/src/QUI/FrontendUsers/Controls/Address/Address.Edit.html
+++ b/src/QUI/FrontendUsers/Controls/Address/Address.Edit.html
@@ -1,7 +1,5 @@
 <section class="quiqqer-frontend-users-address-edit">
-    <header>
-        <h1>{locale group="quiqqer/frontend-users" var="dialog.frontend-users.edit.title"}</h1>
-    </header>
+    <h2>{locale group="quiqqer/frontend-users" var="dialog.frontend-users.edit.title"}</h2>
 
     {template_event name="quiqqer::frontend-users::user-address-edit-begin" User=$User Address=$Address}
 
@@ -104,7 +102,7 @@
     {/if}
 
     {if $settings.country.show}
-    <label>
+    <label class="quiqqer-frontendUsers-userdata-address-country">
         <span>
             {locale group="quiqqer/system" var="country"}
             {if $settings.country.required}*{/if}
diff --git a/src/QUI/FrontendUsers/Controls/Address/Address.css b/src/QUI/FrontendUsers/Controls/Address/Address.css
index 5b07c91e67249b41fee74eaca76f1b8c93814d5c..bc1768911d3f194e789f75cb7272dcfa11c6bdce 100644
--- a/src/QUI/FrontendUsers/Controls/Address/Address.css
+++ b/src/QUI/FrontendUsers/Controls/Address/Address.css
@@ -1,19 +1,24 @@
+/* popup */
+.qui-window-popup--frontendUsers-profile {
+    --_qui-frontend-users-profile__popup__bg-color: var(--qui-frontend-users-profile__popup__bg-color, #f5f5f5);
+    --_qui-frontend-users-profile__popup__radius: var(--qui-frontend-users-profile__popup__radius, 0.5rem);
+    --_qui-frontend-users-profile__popup__conten-maxWidth: var(--qui-frontend-users-profile__popup__conten-maxWidth, 30rem);
+}
+
+/***********/
+/* General */
+/***********/
 .quiqqer-frontendUsers-manager,
 .quiqqer-frontend-users-address {
-    float: left;
     position: relative;
     width: 100%;
 }
 
 .quiqqer-frontend-users-address-description {
-    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
-    float: left;
-    padding-bottom: 10px;
-    width: 100%;
+    margin-bottom: 1.5rem;
 }
 
 .quiqqer-frontend-users-address-description-text {
-    float: left;
     width: 100%;
 }
 
@@ -23,7 +28,7 @@
 
 @media screen and (min-width: 768px) {
     .quiqqer-frontend-users-address-description-button {
-        float: right;
+        margin-left: auto;
     }
 }
 
@@ -33,97 +38,26 @@
     }
 }
 
-/** container
- ================================================== */
-
-.quiqqer-frontend-users-address-container {
-    background: #fff;
-    border: 1px solid #dedede;
-    height: 100%;
-    left: -50px;
-    outline: none;
-    opacity: 0;
-    position: absolute;
-    top: 0;
-    width: 100%;
-}
-
-.quiqqer-frontend-users-address-container-close {
-    cursor: pointer;
-    font-size: 20px;
-    line-height: 40px;
-    position: absolute;
-    right: 0;
-    text-align: center;
-    top: 0;
-    width: 40px;
-}
-
-.quiqqer-frontend-users-address-container-header {
-    float: left;
-    padding: 20px 40px 0 20px;
-    width: 100%;
-}
-
-.quiqqer-frontend-users-address-container-header header {
-    font-size: 22px;
-    padding: 0;
-}
-
-.quiqqer-frontend-users-address-container-header header h1 {
-    font-size: 22px;
-}
-
-.quiqqer-frontend-users-address-container-content {
-    float: left;
-    height: calc(100% - 40px);
-    margin-top: 40px;
-    overflow: auto;
-    width: 100%;
-}
-
 /** Address listing
  ================================================== */
-address {
-    font-style: normal;
-}
-
-address .adr:not(:last-child) {
-    margin-bottom: 0.75rem;
-}
-
-address .fa {
-    width: 1.5rem;
-}
-
 .quiqqer-frontend-users-address-list {
-    display: flex;
-    flex-wrap: wrap;
-    float: left;
-    padding-bottom: 20px;
-    width: 100%;
+    display: grid;
+    gap: 1rem;
 }
 
 .quiqqer-frontend-users-address-list-entry {
+    --_padding: 0.5rem 1rem;
+    --_radius: var(--radius, var(--_qui-frontend-users-profile__radius));
+    --_border: 1px solid #ddd;
+    --_bg: var(--bg, var(--_qui-frontend-users-profile__bg-color));
+
+    min-width: 0;
+    border-radius: var(--_radius);
     display: flex;
     flex-direction: column;
-    margin-top: 10px;
     overflow: hidden;
-    width: calc(50% - 5px);
-}
-
-@media screen and (hover: hover) {
-    .quiqqer-frontend-users-address-list-entry:hover {
-        background: rgba(0, 0, 0, 0.1);
-    }
-}
-
-.quiqqer-frontend-users-address-list-entry:nth-child(odd) {
-    margin-right: 5px;
-}
-
-.quiqqer-frontend-users-address-list-entry:nth-child(even) {
-    margin-left: 5px;
+    font-size: 0.875rem;
+    border: var(--_border);
 }
 
 .quiqqer-frontend-users-address-list-entry [type="radio"] {
@@ -131,152 +65,69 @@ address .fa {
     margin: 7px;
 }
 
-.quiqqer-frontend-users-address-list-entry header {
-    background: rgba(0, 0, 0, 0.1);
-    padding: 10px;
-    width: 100%;
+.quiqqer-frontend-users-address-list-entry :where(header) {
+    padding: var(--_padding);
+    border-bottom: var(--_border);
+    font-weight: bold;
+    background: var(--_bg);
 }
 
-.quiqqer-frontend-users-address-list-entry header label {
+.quiqqer-frontend-users-address-list-entry :where(header label) {
     margin: 0;
     padding: 0;
 }
 
 .quiqqer-frontend-users-address-list-entry address {
     flex-grow: 1;
-    margin-bottom: 10px;
-    padding: 10px;
-}
-
-.quiqqer-frontend-users-address-list-entry-buttons {
-    padding: 0 10px 10px 0;
-    text-align: right;
-}
-
-/** address edit && create
- ================================================== */
-
-.quiqqer-frontend-users-address-create,
-.quiqqer-frontend-users-address-edit {
-    max-width: 600px;
-    width: 100%;
-}
-
-.quiqqer-frontend-users-address-create header,
-.quiqqer-frontend-users-address-edit header {
-    margin-bottom: 20px;
-    padding: 0;
-}
-
-.quiqqer-frontend-users-address-create label,
-.quiqqer-frontend-users-address-edit label {
-    clear: both;
-    display: inline-block;
-    width: 100%;
-}
-
-@media screen and (min-width: 768px) {
-    .quiqqer-frontend-users-address-create label span,
-    .quiqqer-frontend-users-address-edit label span {
-        float: left;
-        width: 50%
-    }
-
-    .quiqqer-frontend-users-address-create input,
-    .quiqqer-frontend-users-address-create select,
-    .quiqqer-frontend-users-address-create .qui-select,
-    .quiqqer-frontend-users-address-edit input,
-    .quiqqer-frontend-users-address-edit select,
-    .quiqqer-frontend-users-address-edit .qui-select {
-        float: left;
-        width: 50%
-    }
-}
-
-@media screen and (max-width: 767px) {
-    .quiqqer-frontend-users-address-edit select {
-        width: 100%;
-    }
-
-    .quiqqer-frontend-users-address-create select,
-    .quiqqer-frontend-users-address-create .qui-select,
-    .quiqqer-frontend-users-address-edit .qui-select {
-        float: none;
-        width: 100%;
-    }
+    padding: var(--_padding);
+    font-style: normal;
+    font-size: 0.875rem;
+    line-height: 1.5;
 }
 
-.quiqqer-frontend-users-address-create [name="street"],
-.quiqqer-frontend-users-address-edit [name="street"] {
-    margin-bottom: 0.5rem;
+.quiqqer-frontend-users-address-list-entry address .adr:not(:last-child) {
+    margin-bottom: 0.5em;
 }
 
-@media screen and (min-width: 768px) {
-    .quiqqer-frontend-users-address-create [name="street"],
-    .quiqqer-frontend-users-address-edit [name="street"] {
-        width: 30%;
-    }
-
-    .quiqqer-frontend-users-address-create [name="street_number"],
-    .quiqqer-frontend-users-address-edit [name="street_number"] {
-        margin-left: 10px;
-        width: calc(20% - 10px);
-    }
-
-    .quiqqer-frontend-users-address-create [name="street"],
-    .quiqqer-frontend-users-address-edit [name="street"],
-    .quiqqer-frontend-users-address-create [name="street_number"],
-    .quiqqer-frontend-users-address-edit [name="street_number"] {
-        float: left;
-    }
-
-    .quiqqer-frontend-users-address-edit-create,
-    .quiqqer-frontend-users-address-edit-button {
-        margin-left: 50%;
-        width: 50%;
-    }
+.quiqqer-frontend-users-address-list-entry address .fa {
+    width: 1.5rem;
 }
 
-@media screen and (max-width: 767px) {
-    .quiqqer-frontend-users-address-edit-create,
-    .quiqqer-frontend-users-address-edit-button {
-        width: 100%;
-    }
+.quiqqer-frontend-users-address-list-entry-buttons {
+    text-align: right;
+    border-top: var(--_border);
+    padding: 0.5rem 1rem;
+    display: flex;
+    justify-content: flex-end;
+    gap: 0.5rem;
+    flex-wrap: wrap;
 }
 
-.quiqqer-frontend-users-address-container-edit,
-.quiqqer-frontend-users-address-container-create {
-    float: left;
-    padding: 0 20px 20px;
-    width: 100%;
+/*****************/
+/* Address popup */
+/*****************/
+.qui-window-popup--frontendUsers-profile .quiqqer-frontend-users-address-create,
+.qui-window-popup--frontendUsers-profile .quiqqer-frontend-users-address-edit {
+    max-width: var(--_qui-frontend-users-profile__popup__conten-maxWidth);
+    margin-inline: auto;
 }
-
-/** Rechnungsadresse löschen
- ================================================== */
-
-.quiqqer-frontend-users-address-delete {
+/************************/
+/* Address delete popup */
+/************************/
+.qui-window-popup--frontendUsers-profile-address-delete .quiqqer-frontend-users-address-delete {
     margin: 0 auto;
     max-width: 600px;
     width: 100%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
 }
 
-.quiqqer-frontend-users-address-delete-container-deleteBtn {
-    padding: 10px !important;
-    font-size: 14px !important;
-}
-
-.quiqqer-frontend-users-address-delete-container address {
-    margin: 20px auto;
-}
-
-/** Rechnungsadresse löschen - js
- ================================================== */
-
-.quiqqer-frontend-users-address-container-delete {
-    text-align: center;
+.quiqqer-frontend-users-address-delete-container :where(address) {
+    margin-top: 2rem;
+    background: var(--_qui-frontend-users-profile__popup__bg-color);
+    border-radius: var(--_qui-frontend-users-profile__popup__radius);
+    padding: 1rem;
+    font-style: normal;
 }
 
-.quiqqer-frontend-users-address-container-delete-message {
-    margin-bottom: 20px;
-    padding: 0 10px;
-}
diff --git a/src/QUI/FrontendUsers/Controls/Address/Address.html b/src/QUI/FrontendUsers/Controls/Address/Address.html
index 88d5b61060e4b50a2d4f13f817d1e6e21c9dae4a..ce6e80261eeba7608c38c71f9d3e259410f06d97 100644
--- a/src/QUI/FrontendUsers/Controls/Address/Address.html
+++ b/src/QUI/FrontendUsers/Controls/Address/Address.html
@@ -1,16 +1,14 @@
 {template_event name="quiqqer::frontend-users::user-address-top" User=$User}
 
 <section class="quiqqer-frontend-users-address quiqqer-frontendUsers-userdata-section">
-    <header>
-        <h2>{locale group="quiqqer/frontend-users" var="profile.address.category.title"}</h2>
-    </header>
+    <h2>{locale group="quiqqer/frontend-users" var="profile.address.category.title"}</h2>
 
     <div class="quiqqer-frontend-users-address-description">
         <div class="quiqqer-frontend-users-address-description-text">
             {locale group="quiqqer/frontend-users" var="control.address.title.Address.description"}
         </div>
 
-        <button name="create" class="quiqqer-frontend-users-address-description-button">
+        <button name="create" class="btn btn-secondary quiqqer-frontend-users-address-description-button">
             <span class="fa fa-plus"></span>
             <span>{locale group="quiqqer/frontend-users" var="control.address.title.Address.addButton"}</span>
         </button>
@@ -22,41 +20,39 @@
         {if $User->getId()}
         {* Logged in user *}
 
-        {foreach $addresses as $Address}
-        <div class="quiqqer-frontend-users-address-list-entry">
-            <header>
-                <label>
-                    <span class="fa fa-address-card-o"></span>
-                    {if $Address->getUUID() == $User->getAttribute('address')}
-                    {locale group="quiqqer/frontend-users" var="control.address.header.defaultAddress.title"}
-                    {else}
-                    {locale group="quiqqer/frontend-users" var="control.address.header.title"}
-                    {/if}
-                    <input type="hidden"
-                           name="address"
-                           value="{$Address->getUUID()}"
-                    >
-                </label>
-            </header>
-
-            {$Address->render()}
-
-            <div class="quiqqer-frontend-users-address-list-entry-buttons">
-                <button type="submit" name="edit" value="{$Address->getUUID()}">
-                    <span class="fa fa-edit"></span>
-                    <span>
-                        {locale group="quiqqer/frontend-users" var="control.address.title.Address.editButton"}
-                    </span>
-                </button>
-                <button type="submit" name="delete" value="{$Address->getUUID()}" class="btn btn-danger">
-                    <span class="fa fa-trash"></span>
-                    <span>
-                        {locale group="quiqqer/frontend-users" var="control.address.title.Address.deleteButton"}
-                    </span>
-                </button>
-            </div>
-        </div>
-        {/foreach}
+            {foreach $addresses as $Address}
+                <div class="quiqqer-frontend-users-address-list-entry" data-name="address">
+                    <header>
+                        <span class="fa fa-address-card-o"></span>
+                        {if $Address->getUUID() == $User->getAttribute('address')}
+                        {locale group="quiqqer/frontend-users" var="control.address.header.defaultAddress.title"}
+                        {else}
+                        {locale group="quiqqer/frontend-users" var="control.address.header.title"}
+                        {/if}
+                        <input type="hidden"
+                               name="address"
+                               value="{$Address->getUUID()}"
+                        >
+                    </header>
+
+                    {$Address->render()}
+
+                    <div class="quiqqer-frontend-users-address-list-entry-buttons">
+                        <button type="submit" name="edit" value="{$Address->getUUID()}">
+                            <span class="fa fa-edit"></span>
+                            <span>
+                                {locale group="quiqqer/frontend-users" var="control.address.title.Address.editButton"}
+                            </span>
+                        </button>
+                        <button type="submit" name="delete" value="{$Address->getUUID()}" class="btn btn-danger">
+                            <span class="fa fa-trash"></span>
+                            <span>
+                                {locale group="quiqqer/frontend-users" var="control.address.title.Address.deleteButton"}
+                            </span>
+                        </button>
+                    </div>
+                </div>
+            {/foreach}
         {/if}
     </div>
 
diff --git a/src/QUI/FrontendUsers/Controls/Address/Address.php b/src/QUI/FrontendUsers/Controls/Address/Address.php
index cf7b2f3f15e4384e313b1af7191e36add12cf2d2..0919d56c2cf85b63621e2be487cd99f8b8b68703 100644
--- a/src/QUI/FrontendUsers/Controls/Address/Address.php
+++ b/src/QUI/FrontendUsers/Controls/Address/Address.php
@@ -38,7 +38,7 @@ public function __construct(array $attributes = [])
      * @param null|QUI\Locale $Locale
      * @return string
      */
-    public function getName(QUI\Locale $Locale = null): string
+    public function getName(null | QUI\Locale $Locale = null): string
     {
         return 'Address';
     }
@@ -463,10 +463,15 @@ protected function delete(): void
      * Validate if the order has an invoice address
      *
      * @param QUI\Users\Address $Address
-     * @throws QUI\ERP\Order\Exception
+     * @throws QUI\Exception
      */
     public function validate(QUI\Users\Address $Address): void
     {
+        if (!class_exists('QUI\ERP\Order\Exception')) {
+            QUI\System\Log::addError('Class "QUI\ERP\Order\Exception" not found.');
+            throw new QUI\Exception('An error occurred.');
+        }
+
         $exception = [
             'quiqqer/order',
             'exception.missing.address.field'
diff --git a/src/QUI/FrontendUsers/Controls/Login.css b/src/QUI/FrontendUsers/Controls/Login.css
index fe63fee9084fb1750bd06117d13d0ef469c8f95e..8ccf509c6b63f1b7e078952c776b119b599c65b1 100644
--- a/src/QUI/FrontendUsers/Controls/Login.css
+++ b/src/QUI/FrontendUsers/Controls/Login.css
@@ -22,6 +22,10 @@
     width: 100%;
 }
 
+.quiqqer-fu-login-container__inner {
+    display: flow-root;
+}
+
 .quiqqer-fu-login-social-entry {
     border: 1px solid #ddd;
     border-radius: 100%;
@@ -135,8 +139,6 @@
 }
 
 .quiqqer-fu-login-forget-password-reset {
-    background: #fff;
-    height: 100%;
     opacity: 0;
     position: absolute;
     top: 0;
@@ -175,13 +177,6 @@
     width: 100%;
 }
 
-.quiqqer-fu-login-forget-password-reset [name="cancel"] {
-    bottom: 0;
-    padding: 0.5rem 2rem;
-    position: absolute;
-    right: 0;
-}
-
 .quiqqer-fu-login-activation-info {
     margin: 20px 0 20px 0;
 }
diff --git a/src/QUI/FrontendUsers/Controls/Login.html b/src/QUI/FrontendUsers/Controls/Login.html
index 34a2319e85b81565df4534b026c107c7b50d2874..47f37a1fe45ac7af1d88e61c9d65611663c248b7 100644
--- a/src/QUI/FrontendUsers/Controls/Login.html
+++ b/src/QUI/FrontendUsers/Controls/Login.html
@@ -14,89 +14,92 @@
 </div>
 {else}
 
-<section class="quiqqer-fu-login-container" style="display: none">
-    {if $this->getAttribute('header')}
-        <h2>{locale group="quiqqer/frontend-users" var="control.login.title"}</h2>
-    {/if}
-
-    <div class="quiqqer-fu-login-social">
-        {foreach $authenticators as $entry}
-        <form action=""
-              method="POST"
-              class="quiqqer-fu-login-social-entry"
-              data-authenticator="{$entry.class}"
-              data-authenticator-hash="{$entry.class|md5}"
-        >
-            <span class="quiqqer-fu-login-social-entry-icon">
-                {if $entry.icon}
-                <span class="{$entry.Login->getAttribute('icon')}"></span>
-                {elseif $entry.image}
-                <img src="{$entry.Login->getAttribute('icon')}" alt="" />
-                {/if}
-            </span>
-            <span class="quiqqer-fu-login-social-entry-loader">
-                <span class="fa fa-spin fa-spinner fas fa-circle-notch"></span>
-            </span>
-            <div class="quiqqer-fu-login-social-entry-control">
-                {$entry.Login->create()}
-            </div>
-        </form>
-        {/foreach}
-    </div>
+<section class="quiqqer-fu-login-container" style="display: none" data-name="login-container">
+    <div class="quiqqer-fu-login-container__inner" data-name="login-container-inner">
+        {if $this->getAttribute('header')}
+            <h2 data-name="header">{locale group="quiqqer/frontend-users" var="control.login.title"}</h2>
+        {/if}
 
-    {if $this->getAttribute('mail')}
-        {if count($authenticators)}
-        <div class="quiqqer-fu-login-between-text">
-            {locale group="quiqqer/frontend-users" var="control.login.message.between"}
+        <div class="quiqqer-fu-login-social">
+            {foreach $authenticators as $entry}
+            <form action=""
+                  method="POST"
+                  class="quiqqer-fu-login-social-entry"
+                  data-name="social-login-form"
+                  data-authenticator="{$entry.class}"
+                  data-authenticator-hash="{$entry.class|md5}"
+            >
+                <span class="quiqqer-fu-login-social-entry-icon" data-name="social-login-entry-icon">
+                    {if $entry.icon}
+                    <span class="{$entry.Login->getAttribute('icon')}"></span>
+                    {elseif $entry.image}
+                    <img src="{$entry.Login->getAttribute('icon')}" alt="" />
+                    {/if}
+                </span>
+                <span class="quiqqer-fu-login-social-entry-loader" data-name="social-login-entry-loader">
+                    <span class="fa fa-spin fa-spinner fas fa-circle-notch"></span>
+                </span>
+                <div class="quiqqer-fu-login-social-entry-control" data-name="social-login-controlContainer">
+                    {$entry.Login->create()}
+                </div>
+            </form>
+            {/foreach}
         </div>
+
+        {if $this->getAttribute('mail')}
+            {if count($authenticators)}
+            <div class="quiqqer-fu-login-between-text">
+                {locale group="quiqqer/frontend-users" var="control.login.message.between"}
+            </div>
+            {/if}
         {/if}
-    {/if}
 
-    <div class="quiqqer-fu-login-activation-info"></div>
+        <div class="quiqqer-fu-login-activation-info" data-name="activation-info"></div>
 
-    {if $this->getAttribute('mail')}
-        <form name="quiqqer-fu-login-email" class="quiqqer-fu-login-email">
-            <section class="quiqqer-fu-login-email-mailSection">
-                <label>
-                    <span class="label">
-                        {locale group="quiqqer/frontend-users" var="control.registration.sign.up.email.title"}
-                    </span>
-                    <span class="field">
-                    <span class="icon fa fa-envelope"></span>
-                        <input type="text" name="username" required autocomplete="email"/>
-                    </span>
-                </label>
+        {if $this->getAttribute('mail')}
+            <form name="quiqqer-fu-login-email" class="quiqqer-fu-login-email">
+                <section class="quiqqer-fu-login-email-mailSection">
+                    <label>
+                        <span class="label">
+                            {locale group="quiqqer/frontend-users" var="control.registration.sign.up.email.title"}
+                        </span>
+                        <span class="field">
+                        <span class="icon fa fa-envelope"></span>
+                            <input type="text" name="username" required autocomplete="email"/>
+                        </span>
+                    </label>
 
-                <label>
-                    <span class="label">
-                        {locale group="quiqqer/frontend-users" var="control.registration.sign.up.password.title"}
-                    </span>
-                    <span class="field">
-                    <span class="icon fa fa-key"></span>
-                        <input type="password" name="password" required autocomplete="off"/>
-                    </span>
-                </label>
+                    <label>
+                        <span class="label">
+                            {locale group="quiqqer/frontend-users" var="control.registration.sign.up.password.title"}
+                        </span>
+                        <span class="field">
+                        <span class="icon fa fa-key"></span>
+                            <input type="password" name="password" required autocomplete="off"/>
+                        </span>
+                    </label>
 
-                <div class="quiqqer-fu-login-email-buttons">
-                    <button type="submit" name="mail-login">
-                        {locale group="quiqqer/frontend-users" var="control.login.button"}
-                    </button>
-                </div>
-            </section>
-        </form>
-    {/if}
+                    <div class="quiqqer-fu-login-email-buttons">
+                        <button type="submit" name="mail-login">
+                            {locale group="quiqqer/frontend-users" var="control.login.button"}
+                        </button>
+                    </div>
+                </section>
+            </form>
+        {/if}
 
-    {if $showPasswordReset}
-    <div class="quiqqer-fu-login-forget-password-link">
-        <a href="#">
-            {locale group="quiqqer/frontend-users" var="control.login.forgotten.password"}
-        </a>
+        {if $showPasswordReset}
+        <div class="quiqqer-fu-login-forget-password-link" data-name="forgot-password-link">
+            <a href="#">
+                {locale group="quiqqer/frontend-users" var="control.login.forgotten.password"}
+            </a>
+        </div>
+        {/if}
     </div>
-    {/if}
 
     {if $showPasswordReset}
-    <div class="quiqqer-fu-login-forget-password-reset" style="display: none;">
-        <section>
+    <div class="quiqqer-fu-login-forget-password-reset" style="display: none;" data-name="password-reset">
+        <section data-name="password-reset-inner">
             <h2>{locale group="quiqqer/frontend-users" var="quiqqer.auth.login.password.title"}</h2>
 
             <p>
diff --git a/src/QUI/FrontendUsers/Controls/Login.php b/src/QUI/FrontendUsers/Controls/Login.php
index 43ed7482cb7ab91c3c225ca88c6f57cee73d6965..18ad1861d8dafd5f5d023c2d70803fe93deb1bad 100644
--- a/src/QUI/FrontendUsers/Controls/Login.php
+++ b/src/QUI/FrontendUsers/Controls/Login.php
@@ -39,7 +39,10 @@ public function __construct(array $attributes = [])
 
         $this->setAttributes($attributes);
 
-        $this->addCSSFile(dirname(__FILE__) . '/Login.css');
+        if (!defined('QUIQQER_CONTROL_TEMPLATE_USE_BASIC') || QUIQQER_CONTROL_TEMPLATE_USE_BASIC !== true) {
+            $this->addCSSFile(dirname(__FILE__) . '/Login.css');
+        }
+
         $this->addCSSClass('quiqqer-fu-login');
 
         $this->setJavaScriptControl(
@@ -120,7 +123,7 @@ public function getBody(): string
             'showPasswordReset' => $showPasswordReset
         ]);
 
-        return $Engine->fetch(dirname(__FILE__) . '/Login.html');
+        return $Engine->fetch($this->getTemplateFile());
     }
 
     /**
@@ -148,7 +151,6 @@ protected function getAuthenticators(): array
             }
 
             $authenticators = array_filter($authenticators, function ($authenticator) use ($allowed) {
-                /** @var QUI\Users\AuthenticatorInterface $Authenticator */
                 return in_array($authenticator, $allowed);
             });
         } catch (Exception $Exception) {
@@ -160,7 +162,6 @@ protected function getAuthenticators(): array
         }
 
         return array_filter($authenticators, function ($authenticator) use ($filterRegistrars) {
-            /** @var QUI\Users\AuthenticatorInterface $Authenticator */
             return in_array($authenticator, $filterRegistrars);
         });
     }
diff --git a/src/QUI/FrontendUsers/Controls/Login_basic.html b/src/QUI/FrontendUsers/Controls/Login_basic.html
new file mode 100644
index 0000000000000000000000000000000000000000..47f37a1fe45ac7af1d88e61c9d65611663c248b7
--- /dev/null
+++ b/src/QUI/FrontendUsers/Controls/Login_basic.html
@@ -0,0 +1,128 @@
+<noscript class="quiqqer-fu-login-noscript">
+    <div class="message-error">
+        {locale group="quiqqer/frontend-users" var="registrars.email.javascript_required"}
+    </div>
+</noscript>
+
+{if $SessionUser->getId() && $SessionUser->getId() >= 100}
+<div class="quiqqer-fu-login-logged-in message-information">
+    {locale
+    group="quiqqer/frontend-users"
+    var="message.already.loged.in"
+    username=$SessionUser->getName()
+    }
+</div>
+{else}
+
+<section class="quiqqer-fu-login-container" style="display: none" data-name="login-container">
+    <div class="quiqqer-fu-login-container__inner" data-name="login-container-inner">
+        {if $this->getAttribute('header')}
+            <h2 data-name="header">{locale group="quiqqer/frontend-users" var="control.login.title"}</h2>
+        {/if}
+
+        <div class="quiqqer-fu-login-social">
+            {foreach $authenticators as $entry}
+            <form action=""
+                  method="POST"
+                  class="quiqqer-fu-login-social-entry"
+                  data-name="social-login-form"
+                  data-authenticator="{$entry.class}"
+                  data-authenticator-hash="{$entry.class|md5}"
+            >
+                <span class="quiqqer-fu-login-social-entry-icon" data-name="social-login-entry-icon">
+                    {if $entry.icon}
+                    <span class="{$entry.Login->getAttribute('icon')}"></span>
+                    {elseif $entry.image}
+                    <img src="{$entry.Login->getAttribute('icon')}" alt="" />
+                    {/if}
+                </span>
+                <span class="quiqqer-fu-login-social-entry-loader" data-name="social-login-entry-loader">
+                    <span class="fa fa-spin fa-spinner fas fa-circle-notch"></span>
+                </span>
+                <div class="quiqqer-fu-login-social-entry-control" data-name="social-login-controlContainer">
+                    {$entry.Login->create()}
+                </div>
+            </form>
+            {/foreach}
+        </div>
+
+        {if $this->getAttribute('mail')}
+            {if count($authenticators)}
+            <div class="quiqqer-fu-login-between-text">
+                {locale group="quiqqer/frontend-users" var="control.login.message.between"}
+            </div>
+            {/if}
+        {/if}
+
+        <div class="quiqqer-fu-login-activation-info" data-name="activation-info"></div>
+
+        {if $this->getAttribute('mail')}
+            <form name="quiqqer-fu-login-email" class="quiqqer-fu-login-email">
+                <section class="quiqqer-fu-login-email-mailSection">
+                    <label>
+                        <span class="label">
+                            {locale group="quiqqer/frontend-users" var="control.registration.sign.up.email.title"}
+                        </span>
+                        <span class="field">
+                        <span class="icon fa fa-envelope"></span>
+                            <input type="text" name="username" required autocomplete="email"/>
+                        </span>
+                    </label>
+
+                    <label>
+                        <span class="label">
+                            {locale group="quiqqer/frontend-users" var="control.registration.sign.up.password.title"}
+                        </span>
+                        <span class="field">
+                        <span class="icon fa fa-key"></span>
+                            <input type="password" name="password" required autocomplete="off"/>
+                        </span>
+                    </label>
+
+                    <div class="quiqqer-fu-login-email-buttons">
+                        <button type="submit" name="mail-login">
+                            {locale group="quiqqer/frontend-users" var="control.login.button"}
+                        </button>
+                    </div>
+                </section>
+            </form>
+        {/if}
+
+        {if $showPasswordReset}
+        <div class="quiqqer-fu-login-forget-password-link" data-name="forgot-password-link">
+            <a href="#">
+                {locale group="quiqqer/frontend-users" var="control.login.forgotten.password"}
+            </a>
+        </div>
+        {/if}
+    </div>
+
+    {if $showPasswordReset}
+    <div class="quiqqer-fu-login-forget-password-reset" style="display: none;" data-name="password-reset">
+        <section data-name="password-reset-inner">
+            <h2>{locale group="quiqqer/frontend-users" var="quiqqer.auth.login.password.title"}</h2>
+
+            <p>
+                {locale group="quiqqer/system" var="quiqqer.auth.login.password.message"}
+            </p>
+
+            <label>
+            <span>
+                {locale group="quiqqer/system" var="quiqqer.auth.login.label.email"}
+            </span>
+                <input type="email" value="" name="email"/>
+            </label>
+
+            <button type="submit" class="login qui-button btn-green reset-password">
+                <span>{locale group='quiqqer/core' value='controls.users.auth.quiqqerlogin.btn.password_reset'}</span>
+            </button>
+
+            <button name="cancel" type="reset">
+                {locale group='quiqqer/core' value='cancel'}
+            </button>
+        </section>
+    </div>
+    {/if}
+</section>
+
+{/if}
diff --git a/src/QUI/FrontendUsers/Controls/Profile.css b/src/QUI/FrontendUsers/Controls/Profile.css
index 9d7fb0c18b11a7e7b38419363eb824def34b7294..a0ac2e4e39d0be9e57543b360756f602e0c5e98a 100644
--- a/src/QUI/FrontendUsers/Controls/Profile.css
+++ b/src/QUI/FrontendUsers/Controls/Profile.css
@@ -1,168 +1,220 @@
 .quiqqer-frontendUsers-controls-profile {
-    float: left;
-    width: 100%;
+    --_qui-frontend-users-profile__bg-color: var(--qui-frontend-users-profile__bg-color, #f5f5f5);
+    --_qui-frontend-users-profile__radius: var(--qui-frontend-users-profile__radius, 0.5rem);
+    --_qui-frontend-users-profile__content-maxWidth: var(--qui-frontend-users-profile__content-maxWidth, 600px);
+    --_qui-frontend-users-profile__sidebar-width: var(--qui-frontend-users-profile__sidebar-width, 300px);
+    --_qui-frontend-users-profile__sidebar-nav-item-outline--hover: var(--qui-frontend-users-profile__sidebar-nav-item-outline--hover, 2px solid currentColor);
+    --_qui-frontend-users-profile__sidebar-nav-item-bg-color--hover: var(--qui-frontend-users-profile__sidebar-nav-item-bg-color--hover, #f5f5f5);
+
+    display: flex;
+    gap: clamp(2rem, 10vw - 4rem, 4rem);
 }
 
-/** categories / tabs
- ==================================== */
+.quiqqer-frontendUsers-controls-profile__sidebar {
+    min-width: 0;
+    width: var(--_qui-frontend-users-profile__sidebar-width);
+    flex-shrink: 0;
+}
 
-.quiqqer-frontendUsers-controls-profile-categories {
-    float: left;
-    padding-right: 10px;
-    width: 30%;
+.quiqqer-frontendUsers-controls-profile__content {
+    min-width: 0;
+    flex-grow: 1;
 }
 
-.quiqqer-fupc-category {
-    float: left;
-    width: 100%;
+@media screen and (max-width: 767px) {
+    .quiqqer-frontendUsers-controls-profile {
+        flex-direction: column;
+        gap: 2rem;
+    }
+
+    .quiqqer-frontendUsers-controls-profile__sidebar,
+    .quiqqer-frontendUsers-controls-profile__content {
+        width: 100%
+    }
 }
 
-.quiqqer-fupc-category-header {
-    padding: 5px;
-    position: relative;
-    width: 100%;
+/* general */
+address {
+    font-style: normal;
+}
+
+address :where(.adr:not(:last-child)) {
+    margin-bottom: 0.5rem;
+}
+
+/*********************/
+/* categories / tabs */
+/*********************/
+.quiqqer-fupc-category:not(:last-child) {
+    margin-bottom: 1rem;
 }
 
-.quiqqer-fupc-category-header-opener {
+.quiqqer-fupc-category-header {
+    padding-block: 0.5em;
     cursor: pointer;
-    line-height: 30px;
-    position: absolute;
-    right: 0;
+    font-weight: bold;
+    display: flex;
+    align-items: baseline;
+}
+
+.quiqqer-fupc-category-header__text {
+    flex-grow: 1;
+}
+
+.quiqqer-fupc-category-header__icon {
     text-align: center;
     width: 30px;
 }
 
-.quiqqer-fupc-category--open .quiqqer-fupc-category-header {
-    border-bottom: 1px solid #bebebe;
-    margin-bottom: 5px;
+:where([data-open="1"]) .quiqqer-fupc-category-header__icon {
+    transform: rotate(90deg);
 }
 
 .quiqqer-fupc-category-items-item {
-    clear: both;
     display: none;
-    width: 100%;
-}
-
-.quiqqer-fupc-category-items-item--active {
-    background: rgba(0, 0, 0, 0.2);
+    text-decoration: none;
+    font-weight: normal;
+    padding: 0.25em 0.5em;
+    border-radius: var(--_qui-frontend-users-profile__radius);
+    outline-offset: -2px;
+    color: inherit;
+    align-items: baseline;
 }
 
-.quiqqer-fupc-category--open .quiqqer-fupc-category-items-item {
-    display: block;
+.quiqqer-fupc-category-items-item:where([data-active]) {
+    background-color: var(--_qui-frontend-users-profile__sidebar-nav-item-bg-color--hover);
 }
 
-.quiqqer-fupc-category-items-item:hover {
-    background: rgba(0, 0, 0, 0.2);
+:where([data-open="1"]) .quiqqer-fupc-category-items-item {
+    display: flex;
 }
 
 .quiqqer-fupc-category-items-item-icon {
-    float: left;
     line-height: 30px;
-    text-align: center;
-    width: 50px;
+    margin-right: 0.5em;
+    flex-shrink: 0;
+}
+
+:where(.quiqqer-fupc-category-items-item):hover {
+    outline: var(--_qui-frontend-users-profile__sidebar-nav-item-outline--hover);
+    color: inherit;
 }
 
 .quiqqer-fupc-category-items-item-text {
-    float: left;
-    width: calc(100% - 50px);
+    flex-grow: 1;
 }
 
 .quiqqer-frontendUsers-saveButton {
     cursor: pointer;
 }
 
-/** category content
- ==================================== */
-/*.quiqqer-frontendUsers-controls-profile-control > header:first-of-type > h2 {*/
-/*    margin-bottom: 2rem;*/
-/*}*/
+/* mobile */
+.quiqqer-frontendUsers-controls-profile-categories-mobile {
+    display: none;
+}
+
+@media screen and (max-width: 767px) {
+    .quiqqer-frontendUsers-controls-profile-categories-mobile {
+        display: block;
+    }
+
+    .quiqqer-frontendUsers-controls-profile-categories-mobile-label {
+        width: 100%;
+    }
+}
+
+/********************/
+/* category content */
+/********************/
+/* content */
+.quiqqer-frontendUsers-profile-section:not(:last-child) {
+    margin-bottom: 2rem;
+}
 
 .quiqqer-frontendUsers-controls-profile-categoryContent {
-    float: left;
-    padding-left: 10px;
     position: relative;
-    width: 70%;
+    max-width: var(--_qui-frontend-users-profile__content-maxWidth);
+    margin-inline: auto;
 }
 
 .quiqqer-frontendUsers-controls-profile-categoryContentAnimation {
-    float: left;
     position: relative;
     width: 100%;
 }
 
-.quiqqer-frontendUsers-controls-profile-control label {
-    clear: both;
-    float: left;
+/* form basic styling */
+.quiqqer-frontendUsers-controls-profile-control :where(h2) {
+    margin-top: 0;
+}
+
+.quiqqer-frontendUsers-controls-profile-control :where(label) {
     margin-bottom: 1rem;
     width: 100%;
+    display: block;
 }
 
-@media screen and (min-width: 768px) {
-    .quiqqer-frontendUsers-label {
-        float: left;
-        width: 30%;
-    }
+/* todo fix in qui, no float: left  */
+.quiqqer-frontendUsers-userdata-address-country,
+.quiqqer-frontendUsers-userdata-language,
+.quiqqer-frontendUsers-userdata-invoiceaddress {
+    display: flow-root;
 }
 
-/** user
- ==================================== */
+.quiqqer-frontendUsers-controls-profile-control :where(label > span:first-child) {
+    font-size: 0.875em;
+    margin-bottom: 0.5em;
+    opacity: 0.75;
+}
+
+.quiqqer-frontendUsers-controls-profile-control :where(input:not([type="checkbox"], [type="radio"]), select, textarea) {
+    width: 100%;
+}
 
-.package-intranet-profile-birthday {
-    float: left;
-    width: 66%;
+/* form basic styling: user data */
+.quiqqer-frontendUsers-controls-profile-control :where(.address-street--2-col) {
+    display: grid;
+    grid-template-columns: 5fr minmax(5rem, 1fr);
+    gap: 1rem;
 }
 
-.package-intranet-profile-birthday [name="birth_day"],
-.package-intranet-profile-birthday [name="birth_year"] {
-    float: left;
-    width: calc(20% - 10px);
+.quiqqer-frontendUsers-controls-profile-control select[name="country"] {
+    display: none;
 }
 
-.package-intranet-profile-birthday [name="birth_month"] {
-    float: left;
-    margin: 0 10px;
-    width: 60%;
+.quiqqer-frontendUsers-controls-profile-control .qui-select {
+    width: 100%;
 }
 
-/** responsive
- ==================================== */
+.quiqqer-frontendUsers-controls-profile-control :where(.qui-select .drop-icon) {
+    height: 36px;
+}
 
+/**************/
+/* responsive */
+/**************/
 .quiqqer-frontendUsers-controls-profile-categories-mobile {
     display: none;
 }
 
-
 @media (max-width: 767px) {
-    .quiqqer-frontendUsers-userdata-label {
-        display: block;
+    .quiqqer-frontendUsers-controls-profile-control input:not([type="checkbox"], [type="radio"]),
+    .quiqqer-frontendUsers-userdata-address-country-select,
+    .quiqqer-frontendUsers-controls-profile-categories-mobile select,
+    .package-intranet-profile-birthday,
+    .quiqqer-frontendUsers-userdata-email,
+    .quiqqer-frontendUsers-userdata-field {
         width: 100%;
-        margin-bottom: 0.25rem;
     }
 
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="firstname"],*/
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="lastname"],*/
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="street_no"],*/
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="zip"],*/
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="city"],*/
-    .quiqqer-frontendUsers-controls-profile-control input,
     .quiqqer-frontendUsers-userdata-address-country-select,
     .package-intranet-profile-birthday,
     .quiqqer-frontendUsers-userdata-email,
     .quiqqer-frontendUsers-userdata-field {
         display: block;
-        width: 100%;
     }
 
-
     .quiqqer-frontendUsers-controls-profile-categories-mobile {
-        clear: both;
-        display: inline;
-        float: left;
-        width: 100%;
-    }
-
-    .quiqqer-frontendUsers-controls-profile-categories-mobile select {
-        clear: both;
+        display: block;
         width: 100%;
     }
 
@@ -171,8 +223,7 @@
     }
 
     .quiqqer-frontendUsers-controls-profile-categoryContent {
-        padding: 0;
-        width: 100%;
+        max-width: 100%;
     }
 
     .quiqqer-frontendUsers-saveButton {
diff --git a/src/QUI/FrontendUsers/Controls/Profile.html b/src/QUI/FrontendUsers/Controls/Profile.html
index 33524ce733ec8c5e21854d279c9f23cae3096079..4fad8c34c074c99d64315c67faf8e5cdb70af388 100644
--- a/src/QUI/FrontendUsers/Controls/Profile.html
+++ b/src/QUI/FrontendUsers/Controls/Profile.html
@@ -1,70 +1,81 @@
 {if !$Category}
-<p>
-    {locale group="quiqqer/frontend-users" var="profile.no_categories_available"}
-</p>
+    <div class="quiqqer-frontendUsers-controls-profile__noCategoriesInfo">
+        <p>
+            {locale group="quiqqer/frontend-users" var="profile.no_categories_available"}
+        </p>
+    </div>
 {else}
+    <div class="quiqqer-frontendUsers-controls-profile__sidebar">
+        {if $this->getAttribute('menu')}
+            <div class="quiqqer-frontendUsers-controls-profile-categories">
+                {foreach $categories as $category}
+                <div class="quiqqer-fupc-category"
+                     data-category="{$category.name}"
+                     data-name="nav-category"
+                     data-open="1"
+                >
+                    <div class="quiqqer-fupc-category-header" data-name="header">
+                        <span class="quiqqer-fupc-category-header__text">{$category.title}</span>
+                        <span class="fa-solid fa-angle-right quiqqer-fupc-category-header__icon" data-name="opener"></span>
+                    </div>
+                    <div class="quiqqer-fu-profile-categories-category-items">
+                        {foreach $category.items as $setting}
+                            {assign var=active value=false}
+                            {if $currentCategory == $category.name && $currentSetting == $setting.name}
+                                {assign var=active value=true}
+                            {/if}
+                            <a href="{$Site->getUrlRewritten()}/{$category.name}/{$setting.name}"
+                                class="quiqqer-fupc-category-items-item"
+                                {if $active}data-active{/if}
+                                data-name="nav-category-item"
+                                data-setting="{$setting.name}"
+                            >
+                                {if $setting.icon}
+                                <span class="fa-fw quiqqer-fupc-category-items-item-icon {$setting.icon}"></span>
+                                {/if}
+                                <span>{$setting.title}</span>
+                            </a>
+                        {/foreach}
+                    </div>
+                </div>
+                {/foreach}
+            </div>
+        {/if}
 
-{if $this->getAttribute('menu')}
-<div class="quiqqer-frontendUsers-controls-profile-categories">
-    {foreach $categories as $category}
-    <div class="quiqqer-fupc-category quiqqer-fupc-category--open"
-         data-category="{$category.name}"
-    >
-        <div class="quiqqer-fupc-category-header">
-            {$category.title}
-        </div>
-        <div class="quiqqer-fu-profile-categories-category-items">
-            {foreach $category.items as $setting}
-
-            {assign var=active value=""}
-            {if $currentCategory == $category.name && $currentSetting == $setting.name}
-            {assign var=active value=" quiqqer-fupc-category-items-item--active"}
-            {/if}
-            <a href="{$Site->getUrlRewritten()}/{$category.name}/{$setting.name}"
-               class="quiqqer-fupc-category-items-item{$active}"
-               data-setting="{$setting.name}"
-            >
-                {if $setting.icon}
-                <span class="quiqqer-fupc-category-items-item-icon {$setting.icon}"></span>
-                {/if}
-                <span>{$setting.title}</span>
-            </a>
-            {/foreach}
-        </div>
+        {* mobile categories *}
+        <form action="" method="post" class="quiqqer-frontendUsers-controls-profile-categories-mobile">
+            <label class="quiqqer-frontendUsers-controls-profile-categories-mobile-label">
+                <select name="profile-categories-mobile">
+                    {foreach $categories as $category}
+                        <optgroup label="{$category.title}">
+                            {foreach $category.items as $setting}
+                                {assign var=active value=""}
+                                {if $currentCategory == $category.name && $currentSetting == $setting.name}
+                                    {assign var=active value="selected"}
+                                {/if}
+                                <option value="{$category.name}:{$setting.name}" {$active}>
+                                    {$setting.title}
+                                </option>
+                            {/foreach}
+                        </optgroup>
+                    {/foreach}
+                </select>
+            </label>
+        </form>
     </div>
-    {/foreach}
-</div>
-{/if}
-
-<form action="" method="post">
-    <label class="quiqqer-frontendUsers-controls-profile-categories-mobile">
-        <select name="profile-categories">
-            {foreach $categories as $category}
-            <optgroup label="{$category.title}">
-                {foreach $category.items as $setting}
-                {assign var=active value=""}
-                {if $currentCategory== $category.name}
-                {assign var=active value=" selected"}
-                {/if}
-                <option value="{$category.name}:{$setting.name}"{$active}>
-                    {$setting.title}
-                </option>
-                {/foreach}
-            </optgroup>
-            {/foreach}
-        </select>
-    </label>
-</form>
 
-<form class="quiqqer-frontendUsers-controls-profile-categoryContent"
-      method="post"
-      action=""
-      data-category="{$currentCategory}"
-      data-setting="{$currentSetting}"
->
-    <div class="quiqqer-frontendUsers-controls-profile-categoryContentAnimation">
-        {$Category->create()}
-        <input type="hidden" name="profile-save" value="1">
+    <div class="quiqqer-frontendUsers-controls-profile__content">
+        <form class="quiqqer-frontendUsers-controls-profile-categoryContent"
+              data-name="form"
+              method="post"
+              action=""
+              data-category="{$currentCategory}"
+              data-setting="{$currentSetting}"
+        >
+            <div class="quiqqer-frontendUsers-controls-profile-categoryContentAnimation" data-name="content-animated">
+                {$Category->create()}
+                <input type="hidden" name="profile-save" value="1">
+            </div>
+        </form>
     </div>
-</form>
 {/if}
\ No newline at end of file
diff --git a/src/QUI/FrontendUsers/Controls/Profile.php b/src/QUI/FrontendUsers/Controls/Profile.php
index 4c14aa214254d015e8f4b07146749e8867dbcff6..abdec5ed99aca5e57f3e1ace026533d792543ed0 100644
--- a/src/QUI/FrontendUsers/Controls/Profile.php
+++ b/src/QUI/FrontendUsers/Controls/Profile.php
@@ -35,8 +35,10 @@ public function __construct(array $attributes = [])
 
         parent::__construct($attributes);
 
+//        if (!defined('QUIQQER_CONTROL_TEMPLATE_USE_BASIC') || QUIQQER_CONTROL_TEMPLATE_USE_BASIC !== true) {
         $this->addCSSFile(dirname(__FILE__) . '/Profile.css');
         $this->addCSSClass('quiqqer-frontendUsers-controls-profile');
+//        }
 
         $this->setAttribute(
             'data-qui',
@@ -82,7 +84,7 @@ public function getBody(): string
          * @param bool $category
          * @return bool
          */
-        $getFirstCategorySetting = function ($array, bool|string|int $category = false) use ($getFirstCategory) {
+        $getFirstCategorySetting = function ($array, bool | string | int $category = false) use ($getFirstCategory) {
             if ($category === false) {
                 $category = $getFirstCategory($array);
             }
@@ -145,7 +147,9 @@ public function getBody(): string
                     return '';
                 }
 
-                $Control->setAttribute('User', $this->getUser());
+                if (method_exists($Control, 'setAttribute')) {
+                    $Control->setAttribute('User', $this->getUser());
+                }
 
                 if ($Request->request->get('profile-save')) {
                     try {
@@ -171,7 +175,7 @@ public function getBody(): string
             'this' => $this
         ]);
 
-        return $Engine->fetch(dirname(__FILE__) . '/Profile.html');
+        return $Engine->fetch($this->getTemplateFile());
     }
 
     /**
diff --git a/src/QUI/FrontendUsers/Controls/Profile/Address.html b/src/QUI/FrontendUsers/Controls/Profile/Address.html
index 3802f1c277c9cfe6e21a5b0ddb180d303f37276f..5360bdfae01b3b2df6f4f9a9b11aceec71885b8b 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/Address.html
+++ b/src/QUI/FrontendUsers/Controls/Profile/Address.html
@@ -1,23 +1,27 @@
 {if isset($manager) && $manager}
-<div class="quiqqer-frontendUsers-manager"
-     data-qui="package/quiqqer/frontend-users/bin/frontend/controls/address/Manager"
-></div>
+    <div class="quiqqer-frontendUsers-manager"
+         data-qui="package/quiqqer/frontend-users/bin/frontend/controls/address/Manager"
+    ></div>
 {else}
-{foreach $addressFields as $field => $options}
-<label>
-    <span class="quiqqer-frontendUsers-label">
-        {locale group="quiqqer/system" var=$field}
-        {if $options['required']}*{/if}
-    </span>
-    {if $field == 'country'}
-    {$CountrySelect->create()}
-    {else}
-    <input name="{$field}" value="{$options['value']}"/>
-    {/if}
-</label>
-{/foreach}
+    <section class="quiqqer-frontendUsers-profile-section">
+        <h2>{locale group="quiqqer/frontend-users" var="profile.address.category.title"}</h2>
 
-<button type="submit" class="quiqqer-frontendUsers-saveButton">
-    {locale group="quiqqer/frontend-users" var="profile.address.btn.submit"}
-</button>
+        {foreach $addressFields as $field => $options}
+            <label>
+                <span class="quiqqer-frontendUsers-label">
+                    {locale group="quiqqer/system" var=$field}
+                    {if $options['required']}*{/if}
+                </span>
+                {if $field == 'country'}
+                    {$CountrySelect->create()}
+                {else}
+                    <input name="{$field}" value="{$options['value']}"/>
+                {/if}
+            </label>
+        {/foreach}
+    </section>
+
+    <button type="submit" class="btn btn-primary quiqqer-frontendUsers-saveButton">
+        {locale group="quiqqer/frontend-users" var="profile.address.btn.submit"}
+    </button>
 {/if}
diff --git a/src/QUI/FrontendUsers/Controls/Profile/Address.php b/src/QUI/FrontendUsers/Controls/Profile/Address.php
index 820433c14f87208ea59c5c63ee59adf61ef1551e..3196715188b2c99c33f0b5c82211799754be51a6 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/Address.php
+++ b/src/QUI/FrontendUsers/Controls/Profile/Address.php
@@ -126,7 +126,7 @@ public function getBody(): string
             'addressFields' => $addressFields
         ]);
 
-        return $Engine->fetch(dirname(__FILE__) . '/Address.html');
+        return $Engine->fetch($this->getTemplateFile());
     }
 
     /**
diff --git a/src/QUI/FrontendUsers/Controls/Profile/Address_basic.html b/src/QUI/FrontendUsers/Controls/Profile/Address_basic.html
new file mode 100644
index 0000000000000000000000000000000000000000..5360bdfae01b3b2df6f4f9a9b11aceec71885b8b
--- /dev/null
+++ b/src/QUI/FrontendUsers/Controls/Profile/Address_basic.html
@@ -0,0 +1,27 @@
+{if isset($manager) && $manager}
+    <div class="quiqqer-frontendUsers-manager"
+         data-qui="package/quiqqer/frontend-users/bin/frontend/controls/address/Manager"
+    ></div>
+{else}
+    <section class="quiqqer-frontendUsers-profile-section">
+        <h2>{locale group="quiqqer/frontend-users" var="profile.address.category.title"}</h2>
+
+        {foreach $addressFields as $field => $options}
+            <label>
+                <span class="quiqqer-frontendUsers-label">
+                    {locale group="quiqqer/system" var=$field}
+                    {if $options['required']}*{/if}
+                </span>
+                {if $field == 'country'}
+                    {$CountrySelect->create()}
+                {else}
+                    <input name="{$field}" value="{$options['value']}"/>
+                {/if}
+            </label>
+        {/foreach}
+    </section>
+
+    <button type="submit" class="btn btn-primary quiqqer-frontendUsers-saveButton">
+        {locale group="quiqqer/frontend-users" var="profile.address.btn.submit"}
+    </button>
+{/if}
diff --git a/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.css b/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.css
index a172ceb808d000c7be1157122567f255475cd85b..6823ba2575ead50fb270d791a4d7378814b09d49 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.css
+++ b/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.css
@@ -1,12 +1,5 @@
 .quiqqer-frontendUsers-changepassword-error,
 .quiqqer-frontendUsers-changepassword-success {
     display: none;
-    margin-bottom: 20px;
+    margin-bottom: 1rem;
 }
-
-@media screen and (min-width: 768px) {
-    .quiqqer-frontendUsers-controls-profile-changepassword input {
-        float: left;
-        width: 70%;
-    }
-}
\ No newline at end of file
diff --git a/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.html b/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.html
index 651137e64afc16789973d7755d7301f58512e5d4..eec50fa05d6dcff036e3138e2fbc00a455485b59 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.html
+++ b/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.html
@@ -1,29 +1,31 @@
-<h2>{locale group="quiqqer/frontend-users" var="profile.changepassword.title"}</h2>
+<div class="quiqqer-frontendUsers-profile-section">
+    <h2>{locale group="quiqqer/frontend-users" var="profile.changepassword.title"}</h2>
 
-<div class="quiqqer-frontendUsers-changepassword-error content-message-error"></div>
-<div class="quiqqer-frontendUsers-changepassword-success content-message-success"></div>
+    <div class="quiqqer-frontendUsers-changepassword-error content-message-error" data-name="msg-error"></div>
+    <div class="quiqqer-frontendUsers-changepassword-success content-message-success" data-name="msg-success"></div>
 
-<label>
-    <span class="quiqqer-frontendUsers-label">
-        {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_old"}
-    </span>
-    <input name="passwordOld" type="password"/>
-</label>
+    <label>
+        <span class="quiqqer-frontendUsers-label">
+            {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_old"}
+        </span>
+        <input name="passwordOld" type="password"/>
+    </label>
 
-<label>
-    <span class="quiqqer-frontendUsers-label">
-        {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_new"}
-    </span>
-    <input name="passwordNew" type="password"/>
-</label>
+    <label>
+        <span class="quiqqer-frontendUsers-label">
+            {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_new"}
+        </span>
+        <input name="passwordNew" type="password"/>
+    </label>
 
-<label>
-    <span class="quiqqer-frontendUsers-label">
-        {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_new_confirm"}
-    </span>
-    <input name="passwordNewConfirm" type="password"/>
-</label>
+    <label>
+        <span class="quiqqer-frontendUsers-label">
+            {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_new_confirm"}
+        </span>
+        <input name="passwordNewConfirm" type="password"/>
+    </label>
+</div>
 
-<button type="submit" class="quiqqer-frontendUsers-saveButton">
+<button type="submit" class="btn btn-primary quiqqer-frontendUsers-saveButton">
     {locale group="quiqqer/frontend-users" var="profile.changepassword.btn.submit"}
 </button>
\ No newline at end of file
diff --git a/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.php b/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.php
index fa0dadf052554614b020693edc54ecc0bd6439db..6c567c906f75d9d97fbf160aa030aeba3ba0925f 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.php
+++ b/src/QUI/FrontendUsers/Controls/Profile/ChangePassword.php
@@ -27,6 +27,10 @@ public function __construct(array $attributes = [])
         $this->addCSSClass('quiqqer-frontendUsers-controls-profile-changepassword');
         $this->addCSSClass('quiqqer-frontendUsers-controls-profile-control');
 
+        if (!defined('QUIQQER_CONTROL_TEMPLATE_USE_BASIC') || QUIQQER_CONTROL_TEMPLATE_USE_BASIC !== true) {
+            $this->addCSSFile(dirname(__FILE__) . '/ChangePassword.css');
+        }
+
         $this->setJavaScriptControl('package/quiqqer/frontend-users/bin/frontend/controls/profile/ChangePassword');
     }
 
@@ -41,9 +45,7 @@ public function getBody(): string
             'User' => QUI::getUserBySession()
         ]);
 
-        $this->addCSSFile(dirname(__FILE__) . '/ChangePassword.css');
-
-        return $Engine->fetch(dirname(__FILE__) . '/ChangePassword.html');
+        return $Engine->fetch($this->getTemplateFile());
     }
 
     /**
diff --git a/src/QUI/FrontendUsers/Controls/Profile/ChangePassword_basic.html b/src/QUI/FrontendUsers/Controls/Profile/ChangePassword_basic.html
new file mode 100644
index 0000000000000000000000000000000000000000..b4ffd1db8cb90a1a29bda1bffccea1986e1ea22d
--- /dev/null
+++ b/src/QUI/FrontendUsers/Controls/Profile/ChangePassword_basic.html
@@ -0,0 +1,31 @@
+<div class="quiqqer-frontendUsers-profile-section">
+    <h2>{locale group="quiqqer/frontend-users" var="profile.changepassword.title"}</h2>
+
+    <div class="content-message-error" data-name="msg-error"></div>
+    <div class="content-message-success" data-name="msg-success"></div>
+
+    <label class="qui-form-label">
+        <span class="qui-form-label__text">
+            {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_old"}
+        </span>
+        <input name="passwordOld" type="password" class="qui-form-label__input"/>
+    </label>
+
+    <label class="qui-form-label">
+        <span class="qui-form-label__text">
+            {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_new"}
+        </span>
+        <input name="passwordNew" type="password" class="qui-form-label__input"/>
+    </label>
+
+    <label class="qui-form-label">
+        <span class="qui-form-label__text">
+            {locale group="quiqqer/frontend-users" var="profile.changepassword.label.password_new_confirm"}
+        </span>
+        <input name="passwordNewConfirm" type="password" class="qui-form-label__input"/>
+    </label>
+</div>
+
+<button type="submit" class="quiqqer-frontendUsers-saveButton">
+    {locale group="quiqqer/frontend-users" var="profile.changepassword.btn.submit"}
+</button>
\ No newline at end of file
diff --git a/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount.html b/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount.html
index f4d723916bd308907aac53caa4548d6ed86092c9..c9bc58ef1399dbc0533de85741c4897317f39eb9 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount.html
+++ b/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount.html
@@ -1,34 +1,38 @@
-<h2>{locale group="quiqqer/frontend-users" var="profile.deleteaccount.title"}</h2>
+<div class="quiqqer-frontendUsers-profile-section">
+    <h2>{locale group="quiqqer/frontend-users" var="profile.deleteaccount.title"}</h2>
 
-{if $action == 'deleteaccount_error'}
-<div class="content-message-error">
-    {locale group="quiqqer/frontend-users" var="profile.deleteaccount.message.error"}
-</div>
-{/if}
+    {if $action == 'deleteaccount_error'}
+        <div class="content-message-error">
+            {locale group="quiqqer/frontend-users" var="profile.deleteaccount.message.error"}
+        </div>
+    {/if}
 
-{if $action == 'deleteaccount_confirm_wait'}
-<div class="content-message-information">
-    {locale group="quiqqer/frontend-users" var="profile.deleteaccount.message.confirm_wait"}
+    {if $action == 'deleteaccount_confirm_wait'}
+        <div class="content-message-information">
+            {locale group="quiqqer/frontend-users" var="profile.deleteaccount.message.confirm_wait"}
+        </div>
+    {else}
+        <p>
+            {locale group="quiqqer/frontend-users" var="profile.deleteaccount.info"}
+        </p>
+    {/if}
 </div>
 
-<button type="submit" class="quiqqer-frontendUsers-saveButton">
-    <span class="fa fa-envelope"></span>
-    {locale group="quiqqer/frontend-users" var="profile.deleteaccount.btn.submit_again"}
-</button>
+{if $action == 'deleteaccount_confirm_wait'}
+    <button type="submit" class="quiqqer-frontendUsers-saveButton">
+        <span class="fa fa-envelope"></span>
+        {locale group="quiqqer/frontend-users" var="profile.deleteaccount.btn.submit_again"}
+    </button>
 
-<script>
-    require(['qui/QUI'], function (QUI) {
-        QUI.fireEvent('quiqqerFrontendUsersAccountDeleteStart');
-        QUI.setAttribute('QUIQQER_FRONTEND_USERS_ACCOUNT_DELETE_START', true);
-    });
-</script>
+    <script>
+        require(['qui/QUI'], function (QUI) {
+            QUI.fireEvent('quiqqerFrontendUsersAccountDeleteStart');
+            QUI.setAttribute('QUIQQER_FRONTEND_USERS_ACCOUNT_DELETE_START', true);
+        });
+    </script>
 {else}
-<p>
-    {locale group="quiqqer/frontend-users" var="profile.deleteaccount.info"}
-</p>
-
-<button type="submit" class="quiqqer-frontendUsers-saveButton btn btn-danger">
-    <span class="fa fa-trash"></span>
-    {locale group="quiqqer/frontend-users" var="profile.deleteaccount.btn.submit"}
-</button>
+    <button type="submit" class="quiqqer-frontendUsers-saveButton btn btn-danger">
+        <span class="fa fa-trash"></span>
+        {locale group="quiqqer/frontend-users" var="profile.deleteaccount.btn.submit"}
+    </button>
 {/if}
\ No newline at end of file
diff --git a/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount.php b/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount.php
index 78dd4f5ef888986c05bc80e1d2b65d9f8878dd03..c994093f23e45f8c4081ea21d28817cccc6386e6 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount.php
+++ b/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount.php
@@ -10,7 +10,8 @@
 use QUI;
 use QUI\FrontendUsers\Handler;
 use QUI\System\Log;
-use QUI\Verification\Verifier;
+use QUI\Verification\Interface\VerificationRepositoryInterface;
+use QUI\Verification\VerificationRepository;
 
 /**
  * Class DeleteAccount
@@ -23,13 +24,22 @@ class DeleteAccount extends AbstractProfileControl
      * DeleteAccount constructor.
      * @param array $attributes
      */
-    public function __construct(array $attributes = [])
-    {
+    public function __construct(
+        array $attributes = [],
+        private ?VerificationRepositoryInterface $verificationRepository = null
+    ) {
+        if (is_null($this->verificationRepository)) {
+            $this->verificationRepository = new VerificationRepository();
+        }
+
         parent::__construct($attributes);
 
         $this->addCSSClass('quiqqer-frontendUsers-controls-profile-deleteaccount');
         $this->addCSSClass('quiqqer-frontendUsers-controls-profile-control');
-        $this->addCSSFile(dirname(__FILE__) . '/DeleteAccount.css');
+
+        if (!defined('QUIQQER_CONTROL_TEMPLATE_USE_BASIC') || QUIQQER_CONTROL_TEMPLATE_USE_BASIC !== true) {
+            $this->addCSSFile(dirname(__FILE__) . '/DeleteAccount.css');
+        }
 
         $this->setJavaScriptControl('package/quiqqer/frontend-users/bin/frontend/controls/profile/DeleteAccount');
         $this->setJavaScriptControlOption('username', QUI::getUserBySession()->getUsername());
@@ -44,17 +54,17 @@ public function getBody(): string
         $action = false;
 
         try {
-            $DeleteVerification = Verifier::getVerificationByIdentifier(
-                QUI::getUserBySession()->getUUID(),
-                QUI\FrontendUsers\UserDeleteConfirmVerification::getType(),
-                true
+            $verification = $this->verificationRepository->findByIdentifier(
+                'confirmdelete-' . QUI::getUserBySession()->getUUID()
             );
 
-            if (Verifier::isVerificationValid($DeleteVerification)) {
-                $action = 'deleteaccount_confirm_wait';
-                $this->setJavaScriptControlOption('deletestarted', 1);
-            } else {
-                Verifier::removeVerification($DeleteVerification);
+            if ($verification) {
+                if ($verification->isValid()) {
+                    $action = 'deleteaccount_confirm_wait';
+                    $this->setJavaScriptControlOption('deletestarted', 1);
+                } else {
+                    $this->verificationRepository->delete($verification);
+                }
             }
         } catch (Exception) {
             // nothing - no active user delete verification
@@ -69,7 +79,7 @@ public function getBody(): string
             'action' => $action
         ]);
 
-        return $Engine->fetch(dirname(__FILE__) . '/DeleteAccount.html');
+        return $Engine->fetch($this->getTemplateFile());
     }
 
     /**
diff --git a/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount_basic.html b/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount_basic.html
new file mode 100644
index 0000000000000000000000000000000000000000..c9bc58ef1399dbc0533de85741c4897317f39eb9
--- /dev/null
+++ b/src/QUI/FrontendUsers/Controls/Profile/DeleteAccount_basic.html
@@ -0,0 +1,38 @@
+<div class="quiqqer-frontendUsers-profile-section">
+    <h2>{locale group="quiqqer/frontend-users" var="profile.deleteaccount.title"}</h2>
+
+    {if $action == 'deleteaccount_error'}
+        <div class="content-message-error">
+            {locale group="quiqqer/frontend-users" var="profile.deleteaccount.message.error"}
+        </div>
+    {/if}
+
+    {if $action == 'deleteaccount_confirm_wait'}
+        <div class="content-message-information">
+            {locale group="quiqqer/frontend-users" var="profile.deleteaccount.message.confirm_wait"}
+        </div>
+    {else}
+        <p>
+            {locale group="quiqqer/frontend-users" var="profile.deleteaccount.info"}
+        </p>
+    {/if}
+</div>
+
+{if $action == 'deleteaccount_confirm_wait'}
+    <button type="submit" class="quiqqer-frontendUsers-saveButton">
+        <span class="fa fa-envelope"></span>
+        {locale group="quiqqer/frontend-users" var="profile.deleteaccount.btn.submit_again"}
+    </button>
+
+    <script>
+        require(['qui/QUI'], function (QUI) {
+            QUI.fireEvent('quiqqerFrontendUsersAccountDeleteStart');
+            QUI.setAttribute('QUIQQER_FRONTEND_USERS_ACCOUNT_DELETE_START', true);
+        });
+    </script>
+{else}
+    <button type="submit" class="quiqqer-frontendUsers-saveButton btn btn-danger">
+        <span class="fa fa-trash"></span>
+        {locale group="quiqqer/frontend-users" var="profile.deleteaccount.btn.submit"}
+    </button>
+{/if}
\ No newline at end of file
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.css b/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.css
index d34eb1e9828fd5ed71fb58cb83dd12b9eb8954ec..df487bc934fd3e73997e7d000e2b3cd6326eb3ae 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.css
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.css
@@ -23,8 +23,8 @@
 }
 
 .quiqqer-frontendUsers-userAvatar-upload-control {
-    height: 30px;
-    margin-bottom: 2rem;
+    display: flow-root;
+    margin-bottom: 1rem;
 }
 
 .quiqqer-frontendUsers-userAvatar-gravatar-section {
@@ -32,11 +32,5 @@
 }
 
 .quiqqer-frontendUsers-userAvatar-gravatar input {
-    float: left;
-}
-
-@media screen and (max-width: 767px) {
-    .quiqqer-frontendUsers-userAvatar-saveButton {
-        width: 100%;
-    }
+    margin-right: 0.5em;
 }
\ No newline at end of file
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.html b/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.html
index 3dd0409d92081ea24f0c928dc8e7a2398b10f611..f42b974ada4191416ada5eed8b8f86620ac8e1fb 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.html
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.html
@@ -1,18 +1,16 @@
-<section class="quiqqer-frontendUsers-userAvatar-section">
-    <header>
-        <h2>
-            {locale group="quiqqer/frontend-users" var="profile.avatar.title"}
-        </h2>
-    </header>
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-userAvatar-section">
+    <h2>
+        {locale group="quiqqer/frontend-users" var="profile.avatar.title"}
+    </h2>
 
     {if $AvatarImage}
     <div class="quiqqer-frontendUsers-userAvatar-icon"
          title="{$User->getName()}"
          {$avatarImageUrl}></div>
     {else}
-    <span class="quiqqer-frontendUsers-userAvatar-icon-none content-message-information">
+    <div class="quiqqer-frontendUsers-userAvatar-icon-none content-message-information">
         {locale group="quiqqer/frontend-users" var="profile.no.avatar.message"}
-    </span>
+    </div>
     {/if}
 
     {if $uploadEnabled}
@@ -29,29 +27,28 @@
 </section>
 
 {if $gravatarEnabled}
-<section class="quiqqer-frontendUsers-userAvatar-gravatar-section">
-    <header>
-        <h2>
-            {locale group="quiqqer/frontend-users" var="profile.avatar.gravatar.title"}
-        </h2>
-    </header>
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-userAvatar-gravatar-section">
+    <h2>
+        {locale group="quiqqer/frontend-users" var="profile.avatar.gravatar.title"}
+    </h2>
 
     <div class="quiqqer-frontendUsers-userAvatar-gravatar">
         <label>
+            <input name="useGravatar" type="checkbox" {if $userGravatarIcon} checked{/if}/>
+
             <span>
                 {locale group="quiqqer/frontend-users"
-                        var="profile.useravatar.gravatar_option"
-                        email=$User->getAttribute('email')
+                    var="profile.useravatar.gravatar_option"
+                    email=$User->getAttribute('email')
                 }
             </span>
-            <input name="useGravatar" type="checkbox" {if $userGravatarIcon} checked{/if}/>
         </label>
     </div>
 </section>
 {/if}
 
 {if $uploadEnabled || $gravatarEnabled}
-<button type="submit" class="quiqqer-frontendUsers-userAvatar-saveButton">
+<button type="submit" class="btn btn-primary quiqqer-frontendUsers-saveButton">
     {locale group="quiqqer/frontend-users" var="profile.userdata.save"}
 </button>
 {/if}
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.php b/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.php
index 3b3b43d978e7ee9677794a3f85246ae605d620fb..0f047467fc021488ef80c87c7f9ca04535d532dc 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.php
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserAvatar.php
@@ -28,8 +28,12 @@ public function __construct(array $attributes = [])
 
         $this->setAttribute('data-qui', 'package/quiqqer/frontend-users/bin/frontend/controls/profile/UserAvatar');
 
+        $this->addCSSClass('quiqqer-frontendUsers-controls-profile-control');
         $this->addCSSClass('quiqqer-frontendUsers-UserAvatar');
-        $this->addCSSFile(dirname(__FILE__) . '/UserAvatar.css');
+
+        if (!defined('QUIQQER_CONTROL_TEMPLATE_USE_BASIC') || QUIQQER_CONTROL_TEMPLATE_USE_BASIC !== true) {
+            $this->addCSSFile(dirname(__FILE__) . '/UserAvatar.css');
+        }
     }
 
     /**
@@ -55,7 +59,7 @@ public function getBody(): string
         if (!empty($userGravatarIcon) && $gravatarEnabled && !empty($userEmail)) {
             $userGravatarIcon = true;
             $AvatarImage = new ExternalImage(Utils::getGravatarUrl($userEmail, 100));
-            $url = $AvatarImage->getSizeCacheUrl(100, 100);
+            $url = $AvatarImage->getSizeCacheUrl();
 
             $Engine->assign([
                 'avatarImageUrl' => ' style="background-image: url(\'' . $url . '\')"'
@@ -103,7 +107,7 @@ public function getBody(): string
             )
         );
 
-        return $Engine->fetch(dirname(__FILE__) . '/UserAvatar.html');
+        return $Engine->fetch($this->getTemplateFile());
     }
 
     /**
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserAvatarUpload.php b/src/QUI/FrontendUsers/Controls/Profile/UserAvatarUpload.php
index 324574ae5f993720e3aa7b9dc30f29e135dfb5e3..3a2850325e8b67ed7f8d1fb983f526713fc14cd8 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/UserAvatarUpload.php
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserAvatarUpload.php
@@ -114,7 +114,10 @@ public function onFileFinish($file, $params): void
         );
 
         $File->activate(QUI::getUsers()->getSystemUser());
-        $File->setTitle($SessionUser->getUsername());
+
+        if (method_exists($File, 'setTitle')) {
+            $File->setTitle($SessionUser->getUsername());
+        }
 
         $SessionUser->setAttribute('avatar', $File->getUrl());
         $SessionUser->save();
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserAvatar_basic.html b/src/QUI/FrontendUsers/Controls/Profile/UserAvatar_basic.html
new file mode 100644
index 0000000000000000000000000000000000000000..d336868820601e67ed752ea36a451de585e48fc9
--- /dev/null
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserAvatar_basic.html
@@ -0,0 +1,54 @@
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-userAvatar-section">
+    <h2>
+        {locale group="quiqqer/frontend-users" var="profile.avatar.title"}
+    </h2>
+
+    {if $AvatarImage}
+    <div class="quiqqer-frontendUsers-userAvatar-icon"
+         title="{$User->getName()}"
+         {$avatarImageUrl}></div>
+    {else}
+    <div class="content-message-information">
+        {locale group="quiqqer/frontend-users" var="profile.no.avatar.message"}
+    </div>
+    {/if}
+
+    {if $uploadEnabled}
+    <div class="quiqqer-frontendUsers-userAvatar-upload">
+        <h3>
+            {locale group="quiqqer/frontend-users" var="profile.avatar.upload.title"}
+        </h3>
+
+        <div class="quiqqer-frontendUsers-userAvatar-upload-control">
+            {$AvatarUpload->create()}
+        </div>
+    </div>
+    {/if}
+</section>
+
+{if $gravatarEnabled}
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-userAvatar-gravatar-section">
+    <h2>
+        {locale group="quiqqer/frontend-users" var="profile.avatar.gravatar.title"}
+    </h2>
+
+    <div class="quiqqer-frontendUsers-userAvatar-gravatar">
+        <label>
+            <input name="useGravatar" type="checkbox" {if $userGravatarIcon} checked{/if}/>
+
+            <span>
+                {locale group="quiqqer/frontend-users"
+                    var="profile.useravatar.gravatar_option"
+                    email=$User->getAttribute('email')
+                }
+            </span>
+        </label>
+    </div>
+</section>
+{/if}
+
+{if $uploadEnabled || $gravatarEnabled}
+<button type="submit" class="btn btn-primary quiqqer-frontendUsers-saveButton">
+    {locale group="quiqqer/frontend-users" var="profile.userdata.save"}
+</button>
+{/if}
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserData.css b/src/QUI/FrontendUsers/Controls/Profile/UserData.css
index 224e493e237e2ea2972916ec126d76e22615ed1e..bc505fee63123d8d6918cfbb9d587540aeb11dc7 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/UserData.css
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserData.css
@@ -1,140 +1,20 @@
-/**
-1. because children are floated and we don't want to set float: left on this element
-   we need to create a new stacking context
- */
-.quiqqer-frontendUsers-userdata-section,
-.quiqqer-frontendUsers-userdata-address,
-.quiqqer-frontendUsers-userdata-address-additional {
-    clear: both;
-    width: 100%;
-    max-width: 100%;
-    margin-bottom: 1rem;
-    display: flow-root; /* 1 */
-}
-
-.quiqqer-frontendUsers-userdata-saveButton {
-    clear: both;
-    display: block;
-}
-
-.quiqqer-frontendUsers-userdata-email__hidden {
+[data-hidden] {
     display: none;
 }
 
-.quiqqer-frontendUsers-userdata-email-new-hint {
-    clear: both;
-    width: 100%;
-    float: left;
-}
-
 .package-intranet-profile-birthday {
-    width: 100%;
-}
-
-/*.quiqqer-frontendUsers-controls-profile-userdata input[name="firstname"],*/
-/*.quiqqer-frontendUsers-controls-profile-userdata input[name="lastname"],*/
-/*.quiqqer-frontendUsers-controls-profile-userdata input[name="street_no"],*/
-/*.quiqqer-frontendUsers-controls-profile-userdata input[name="zip"],*/
-/*.quiqqer-frontendUsers-controls-profile-userdata input[name="city"],*/
-/*.quiqqer-frontendUsers-controls-profile-userdata input[name="tel"],*/
-/*.quiqqer-frontendUsers-controls-profile-userdata input,*/
-/*.quiqqer-frontendUsers-userdata-address-country-select,*/
-/*.quiqqer-frontendUsers-userdata-field {*/
-/*    float: left;*/
-/*    width: 70%;*/
-/*}*/
-
-@media screen and (min-width: 768px) {
-    .quiqqer-frontendUsers-userdata-label {
-        float: left;
-        width: 30%;
-    }
-
-    .quiqqer-frontendUsers-controls-profile-userdata input,
-    .quiqqer-frontendUsers-userdata-address-country-select,
-    .quiqqer-frontendUsers-userdata-field {
-        float: left;
-        width: 70%;
-    }
-}
-
-.quiqqer-frontendUsers-controls-profile-userdata input[name="street"] {
-    float: left;
-    width: 50%;
-}
-
-.quiqqer-frontendUsers-controls-profile-userdata input[name="street_number"] {
-    float: left;
-    margin-left: 10px;
-    width: calc(20% - 10px);
-}
-
-.quiqqer-frontendUsers-controls-profile-userdata select[name="country"] {
-    display: none;
-}
-
-.quiqqer-frontendUsers-controls-profile-userdata .qui-select {
-    width: 100%;
-}
-
-/*.quiqqer-frontendUsers-userdata-address-country,*/
-/*.quiqqer-frontendUsers-controls-profile-userdata .qui-select,*/
-/*.quiqqer-frontendUsers-controls-profile-userdata .qui-select .text {*/
-/*    height: 40px;*/
-/*    line-height: 36px;*/
-/*}*/
-
-.quiqqer-frontendUsers-controls-profile-userdata .qui-select .drop-icon {
-    height: 36px;
+    display: grid;
+    grid-template-columns: 2fr 3fr 2fr;
+    gap: 1rem;
 }
 
 .quiqqer-frontendUsers-userdata-email {
-    display: block;
-    width: 100%;
-}
-
-.quiqqer-frontendUsers-userdata-email input {
-    float: left;
-    width: calc(100% - 60px);
+    display: grid;
+    grid-template-columns: 1fr auto;
+    gap: 1rem;
 }
 
 .quiqqer-frontendUsers-userdata-email-edit {
-    border-width: 1px 1px 1px 0;
-    border-color: #ced9d9;
-    border-style: solid;
-    cursor: pointer;
-    float: left;
-    line-height: 38px;
     text-align: center;
-    width: 60px;
-}
-
-.quiqqer-order-customerData-edit-vatId > select {
-    width: 100%;
-    max-width: 100%;
-}
-
-@media (max-width: 767px) {
-    /*.quiqqer-frontendUsers-userdata-label {*/
-    /*    display: block;*/
-    /*    width: 100%;*/
-    /*    margin-bottom: 0.25rem;*/
-    /*}*/
-
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="firstname"],*/
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="lastname"],*/
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="street_no"],*/
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="zip"],*/
-    /*.quiqqer-frontendUsers-controls-profile-userdata input[name="city"],*/
-    /*.quiqqer-frontendUsers-userdata-address-country-select,*/
-    /*.package-intranet-profile-birthday,*/
-    /*.quiqqer-frontendUsers-userdata-email,*/
-    /*.quiqqer-frontendUsers-userdata-field {*/
-    /*    display: block;*/
-    /*    width: 100%;*/
-    /*}*/
-
-    .quiqqer-frontendUsers-userdata-saveButton {
-        width: 100%;
-    }
+    width: 3em;
 }
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserData.html b/src/QUI/FrontendUsers/Controls/Profile/UserData.html
index c2a7646b49b0648a7ab22872dc0214eb15fa4831..88dc4f5d634da90f68e3c43a9fd397af2d959670 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/UserData.html
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserData.html
@@ -1,6 +1,6 @@
 <noscript>
     <style>
-        .quiqqer-frontendUsers-userdata-email__hidden {
+        [data-hidden] {
             display: inline-block;
         }
     </style>
@@ -26,10 +26,8 @@
 </div>
 {/if}
 
-<section class="quiqqer-frontendUsers-userdata-address">
-    <header>
-        <h2>{locale group="quiqqer/frontend-users" var="profile.userdata.title"}</h2>
-    </header>
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-userdata-address">
+    <h2>{locale group="quiqqer/frontend-users" var="profile.userdata.title"}</h2>
 
     {template_event name="quiqqer::frontend-users::profile::customer-data-begin" User=$User Address=$Address}
 
@@ -61,14 +59,16 @@
         </span>
 
         {if $Address->getAttribute('street_no') === ''}
-        <input type="text" name="street" value="" autocomplete="street-address"/>
-        <input type="text" name="street_number" value=""/>
+            <div class="address-street--2-col">
+                <input type="text" name="street" value="" autocomplete="street-address"/>
+                <input type="text" name="street_number" value=""/>
+            </div>
         {else}
-        <input type="text"
-               name="street_no"
-               autocomplete="street-address"
-               value="{$Address->getAttribute('street_no')|escape:'html'}"
-        />
+            <input type="text"
+                   name="street_no"
+                   autocomplete="street-address"
+                   value="{$Address->getAttribute('street_no')|escape:'html'}"
+            />
         {/if}
     </label>
 
@@ -123,10 +123,8 @@
 
 {template_event name="quiqqer::frontend-users::profile::user-data-middle" User=$User Address=$Address}
 
-<section class="quiqqer-frontendUsers-userdata-address-additional quiqqer-frontendUsers-userdata-section">
-    <header>
-        <h2>{locale group="quiqqer/frontend-users" var="profile.userdata.additional.title"}</h2>
-    </header>
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-userdata-address-additional">
+    <h2>{locale group="quiqqer/frontend-users" var="profile.userdata.additional.title"}</h2>
 
     <label>
         <span class="quiqqer-frontendUsers-userdata-label">
@@ -187,11 +185,15 @@
                    value="{$User->getAttribute('email')|escape:'html'}"
                    disabled
             />
-            <span class="fa fa-edit quiqqer-frontendUsers-userdata-email-edit"></span>
+            <button type="button" data-name="email-edit"
+                    class="btn btn-secondary btn-icon quiqqer-frontendUsers-userdata-email-edit"
+            >
+                <span class="fa fa-edit"></span>
+            </button>
         </div>
     </label>
 
-    <label class="quiqqer-frontendUsers-userdata-email-new quiqqer-frontendUsers-userdata-email__hidden">
+    <label class="quiqqer-frontendUsers-userdata-email-new" data-name="email-new" data-hidden>
         <span class="quiqqer-frontendUsers-userdata-label">
             {locale group="quiqqer/frontend-users" var="profile.userdata.email_new"}
         </span>
@@ -204,7 +206,7 @@
 
 {template_event name="quiqqer::frontend-users::profile::user-data-end" User=$User Address=$Address}
 
-<button type="submit" class="quiqqer-frontendUsers-userdata-saveButton">
+<button type="submit" class="btn btn-primary quiqqer-frontendUsers-saveButton">
     {locale group="quiqqer/frontend-users" var="profile.userdata.save"}
 </button>
 
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserData.php b/src/QUI/FrontendUsers/Controls/Profile/UserData.php
index f8f82d7d174143e949fef786f9d915e393caa341..7e8a0b259a11eab043e2233db391a1250618787d 100644
--- a/src/QUI/FrontendUsers/Controls/Profile/UserData.php
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserData.php
@@ -10,6 +10,9 @@
 use QUI;
 use QUI\FrontendUsers\Handler as FrontendUsersHandler;
 use QUI\Utils\Security\Orthos;
+use QUI\Verification\Enum\VerificationStatus;
+use QUI\Verification\Interface\VerificationRepositoryInterface;
+use QUI\Verification\VerificationRepository;
 
 use function array_filter;
 use function array_keys;
@@ -29,13 +32,22 @@ class UserData extends AbstractProfileControl
      * UserData constructor.
      * @param array $attributes
      */
-    public function __construct(array $attributes = [])
-    {
+    public function __construct(
+        array $attributes = [],
+        private ?VerificationRepositoryInterface $verificationRepository = null
+    ) {
+        if (is_null($this->verificationRepository)) {
+            $this->verificationRepository = new VerificationRepository();
+        }
+
         parent::__construct($attributes);
 
         $this->addCSSClass('quiqqer-frontendUsers-controls-profile-userdata');
         $this->addCSSClass('quiqqer-frontendUsers-controls-profile-control');
-        $this->addCSSFile(dirname(__FILE__) . '/UserData.css');
+
+        if (!defined('QUIQQER_CONTROL_TEMPLATE_USE_BASIC') || QUIQQER_CONTROL_TEMPLATE_USE_BASIC !== true) {
+            $this->addCSSFile(dirname(__FILE__) . '/UserData.css');
+        }
 
         $this->setJavaScriptControl('package/quiqqer/frontend-users/bin/frontend/controls/profile/UserData');
     }
@@ -60,11 +72,13 @@ public function getBody(): string
         }
 
         try {
-            QUI\Verification\Verifier::getVerificationByIdentifier(
-                $User->getUUID(),
-                QUI\FrontendUsers\EmailConfirmVerification::getType(),
-                true
+            $verification = $this->verificationRepository->findByIdentifier(
+                'confirmemail-' . $User->getUUID()
             );
+
+            if (is_null($verification) || $verification->status !== VerificationStatus::PENDING) {
+                $emailChangeRequested = false;
+            }
         } catch (Exception) {
             $emailChangeRequested = false;
         }
@@ -91,7 +105,7 @@ public function getBody(): string
             'showLanguageChangeInProfile' => $Config->getValue('userProfile', 'showLanguageChangeInProfile')
         ]);
 
-        return $Engine->fetch(dirname(__FILE__) . '/UserData.html');
+        return $Engine->fetch($this->getTemplateFile());
     }
 
     /**
diff --git a/src/QUI/FrontendUsers/Controls/Profile/UserData_basic.html b/src/QUI/FrontendUsers/Controls/Profile/UserData_basic.html
new file mode 100644
index 0000000000000000000000000000000000000000..3935830d75e7a3e921b6e53bea9f993f59aa6103
--- /dev/null
+++ b/src/QUI/FrontendUsers/Controls/Profile/UserData_basic.html
@@ -0,0 +1,213 @@
+<noscript>
+    <style>
+        [data-hidden] {
+            display: inline-block;
+        }
+    </style>
+</noscript>
+
+{template_event name="quiqqer::frontend-users::profile::user-data-begin" User=$User Address=$Address}
+
+{if $changeMailRequest}
+<div class="content-message-information">
+    {locale group="quiqqer/frontend-users" var="profile.userdata.message.change_email_request"}
+</div>
+{/if}
+
+{if $action == 'change_email_success'}
+<div class="content-message-success">
+    {locale group="quiqqer/frontend-users" var="profile.userdata.message.change_email_success"}
+</div>
+{/if}
+
+{if $action == 'change_email_error'}
+<div class="content-message-error">
+    {locale group="quiqqer/frontend-users" var="profile.userdata.message.change_email_error"}
+</div>
+{/if}
+
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-userdata-address">
+    <h2>{locale group="quiqqer/frontend-users" var="profile.userdata.title"}</h2>
+
+    {template_event name="quiqqer::frontend-users::profile::customer-data-begin" User=$User Address=$Address}
+
+    <label class="quiqqer-frontendUsers-userdata-address-firstname">
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/frontend-users" var="profile.userdata.firstname"}
+        </span>
+        <input type="text"
+               name="firstname"
+               autocomplete="given-name"
+               value="{$User->getAttribute('firstname')|escape:'html'}"
+        />
+    </label>
+
+    <label class="quiqqer-frontendUsers-userdata-address-lastname">
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/frontend-users" var="profile.userdata.lastname"}
+        </span>
+        <input type="text"
+               name="lastname"
+               autocomplete="family-name"
+               value="{$User->getAttribute('lastname')|escape:'html'}"
+        />
+    </label>
+
+    <label class="quiqqer-frontendUsers-userdata-address-street">
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/frontend-users" var="street_no"}
+        </span>
+
+        {if $Address->getAttribute('street_no') === ''}
+            <div class="quiqqer-frontendUsers-userdata-address-street-2-col">
+                <input type="text" name="street" value="" autocomplete="street-address"/>
+                <input type="text" name="street_number" value=""/>
+            </div>
+        {else}
+            <input type="text"
+                   name="street_no"
+                   autocomplete="street-address"
+                   value="{$Address->getAttribute('street_no')|escape:'html'}"
+            />
+        {/if}
+    </label>
+
+    <label class="quiqqer-frontendUsers-userdata-address-zip">
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/frontend-users" var="zip"}
+        </span>
+        <input type="text"
+               name="zip"
+               autocomplete="postal-code"
+               value="{$Address->getAttribute('zip')|escape:'html'}"
+        />
+    </label>
+
+    <label class="quiqqer-frontendUsers-userdata-address-city">
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/frontend-users" var="city"}
+        </span>
+        <input type="text"
+               name="city"
+               autocomplete="address-level2"
+               value="{$Address->getAttribute('city')|escape:'html'}"
+        />
+    </label>
+
+    <label class="quiqqer-frontendUsers-userdata-address-country">
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/system" var="country"}
+        </span>
+        <span class="quiqqer-frontendUsers-userdata-address-country-select">
+            {control
+            name="country"
+            control="QUI\Countries\Controls\Select"
+            selected=$Address->getAttribute('country')
+            }
+        </span>
+    </label>
+
+    <label class="quiqqer-frontendUsers-userdata-address-phone">
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/system" var="phone"}
+        </span>
+        <input type="text"
+               name="tel"
+               autocomplete="address-phone"
+               value="{$Address->getPhone()|escape:'html'}"
+        />
+    </label>
+
+    {template_event name="quiqqer::frontend-users::profile::customer-data-end" User=$User Address=$Address}
+</section>
+
+{template_event name="quiqqer::frontend-users::profile::user-data-middle" User=$User Address=$Address}
+
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-userdata-additional">
+    <h2>{locale group="quiqqer/frontend-users" var="profile.userdata.additional.title"}</h2>
+
+    <label>
+        <span class="quiqqer-frontendUsers-userdata-label">
+           {locale group="quiqqer/frontend-users" var="profile.userdata.dateOfBirth"}
+        </span>
+
+        {assign var=day value=$User->getAttribute('birthday')|date_format:"%d"}
+        {assign var=month value=$User->getAttribute('birthday')|date_format:"%m"}
+        {assign var=year value=$User->getAttribute('birthday')|date_format:"%Y"}
+
+        <div class="package-intranet-profile-birthday">
+            {birthday type="day"
+            name="birth_day"
+            id="intranet-profile-birthday-day"
+            value=$day
+            }
+
+            {birthday type="month"
+            name="birth_month"
+            id="intranet-profile-birthday-month"
+            value=$month
+            }
+
+            {birthday type="year"
+            name="birth_year"
+            id="intranet-profile-birthday-year"
+            value=$year
+            }
+        </div>
+    </label>
+
+    {if $username}
+        <label>
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/frontend-users" var="profile.userdata.username"}
+        </span>
+            <input name="username" value="{$User->getUsername()}"/>
+        </label>
+    {/if}
+
+    {if $showLanguageChangeInProfile}
+        <label>
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/frontend-users" var="profile.userdata.language"}
+        </span>
+            <div class="quiqqer-frontendUsers-userdata-language">
+                <input data-qui="controls/lang/Select" name="language" value="{$User->getLang()}"/>
+            </div>
+        </label>
+    {/if}
+
+    <label class="qui-form-label">
+        <span class="qui-form-label__text">
+            {locale group="quiqqer/frontend-users" var="profile.userdata.email"}
+        </span>
+        <div class="quiqqer-frontendUsers-userdata-email">
+            <input name="email" autocomplete="email" class="qui-form-label__input"
+                   value="{$User->getAttribute('email')|escape:'html'}"
+                   disabled
+            />
+            <button type="button" data-name="email-edit"
+                    class="btn btn-secondary btn-icon quiqqer-frontendUsers-userdata-email-edit"
+            >
+                <span class="fa fa-edit"></span>
+            </button>
+        </div>
+    </label>
+
+    <label class="qui-frontendUsers-userdata-email-new" data-name="email-new" data-hidden>
+        <span class="quiqqer-frontendUsers-userdata-label">
+            {locale group="quiqqer/frontend-users" var="profile.userdata.email_new"}
+        </span>
+        <input name="emailNew"/>
+        <span class="quiqqer-frontendUsers-userdata-email-new-hint">
+        {locale group="quiqqer/frontend-users" var="profile.userdata.email_new_hint"}
+    </span>
+    </label>
+</section>
+
+{template_event name="quiqqer::frontend-users::profile::user-data-end" User=$User Address=$Address}
+
+<button type="submit" class="quiqqer-frontendUsers-saveButton">
+    {locale group="quiqqer/frontend-users" var="profile.userdata.save"}
+</button>
+
+{template_event name="quiqqer::frontend-users::profile::user-data-last" User=$User Address=$Address}
diff --git a/src/QUI/FrontendUsers/Controls/Profile_basic.html b/src/QUI/FrontendUsers/Controls/Profile_basic.html
new file mode 100644
index 0000000000000000000000000000000000000000..85d8645b7e099df479a27b4daea1e2e715494acb
--- /dev/null
+++ b/src/QUI/FrontendUsers/Controls/Profile_basic.html
@@ -0,0 +1,81 @@
+{if !$Category}
+    <div class="quiqqer-frontendUsers-controls-profile__noCategoriesInfo">
+        <p>
+            {locale group="quiqqer/frontend-users" var="profile.no_categories_available"}
+        </p>
+    </div>
+{else}
+    <div class="quiqqer-frontendUsers-controls-profile__sidebar">
+        {if $this->getAttribute('menu')}
+            <div class="quiqqer-frontendUsers-controls-profile-categories">
+                {foreach $categories as $category}
+                    <div class="quiqqer-fupc-category"
+                         data-category="{$category.name}"
+                         data-name="nav-category"
+                         data-open="1"
+                    >
+                        <div class="quiqqer-fupc-category-header" data-name="header">
+                            <span>{$category.title}</span>
+                            <span class="fa-solid fa-angle-right quiqqer-fupc-category-header-opener" data-name="opener"></span>
+                        </div>
+                        <div class="quiqqer-fu-profile-categories-category-items">
+                            {foreach $category.items as $setting}
+                                {assign var=active value=false}
+                                {if $currentCategory == $category.name && $currentSetting == $setting.name}
+                                    {assign var=active value=true}
+                                {/if}
+                                <a href="{$Site->getUrlRewritten()}/{$category.name}/{$setting.name}"
+                                    class="quiqqer-fupc-category-items-item"
+                                    {if $active}data-active{/if}
+                                    data-name="nav-category-item"
+                                    data-setting="{$setting.name}"
+                                >
+                                    {if $setting.icon}
+                                    <span class="fa-fw quiqqer-fupc-category-items-item-icon {$setting.icon}"></span>
+                                    {/if}
+                                    <span>{$setting.title}</span>
+                                </a>
+                            {/foreach}
+                        </div>
+                    </div>
+                {/foreach}
+            </div>
+        {/if}
+
+        {* mobile categories *}
+        <form action="" method="post" class="quiqqer-frontendUsers-controls-profile-categories-mobile">
+            <label class="quiqqer-frontendUsers-controls-profile-categories-mobile-label">
+                <select name="profile-categories-mobile">
+                    {foreach $categories as $category}
+                        <optgroup label="{$category.title}">
+                            {foreach $category.items as $setting}
+                                {assign var=active value=""}
+                                {if $currentCategory == $category.name && $currentSetting == $setting.name}
+                                    {assign var=active value="selected"}
+                                {/if}
+                                <option value="{$category.name}:{$setting.name}" {$active} data-test="{$currentCategory} - {$category.name}" >
+                                    {$setting.title}
+                                </option>
+                            {/foreach}
+                        </optgroup>
+                    {/foreach}
+                </select>
+            </label>
+        </form>
+    </div>
+
+    <div class="quiqqer-frontendUsers-controls-profile__content">
+        <form class="quiqqer-frontendUsers-controls-profile-categoryContent"
+              data-name="form"
+              method="post"
+              action=""
+              data-category="{$currentCategory}"
+              data-setting="{$currentSetting}"
+        >
+            <div class="quiqqer-frontendUsers-controls-profile-categoryContentAnimation" data-name="content-animated">
+                {$Category->create()}
+                <input type="hidden" name="profile-save" value="1">
+            </div>
+        </form>
+    </div>
+{/if}
\ No newline at end of file
diff --git a/src/QUI/FrontendUsers/Controls/Registration.html b/src/QUI/FrontendUsers/Controls/Registration.html
index d991fe1265d878d34a782b1e262bd1f4a4a015d0..53c96b0aeeca7deea5bc955ca9e2046e2de586d3 100644
--- a/src/QUI/FrontendUsers/Controls/Registration.html
+++ b/src/QUI/FrontendUsers/Controls/Registration.html
@@ -25,9 +25,13 @@
     {if !$instantRedirect}
         {$Registrar->getSuccessMessage()}
     {/if}
-    {if $redirectUrl}
-    <div class="quiqqer-frontendUsers-redirect" data-url="{$redirectUrl}" data-instant="{if $instantRedirect}1{else}0{/if}">
-        {if !$instantRedirect}
+    {if $redirectUrl || $instantReload}
+    <div class="quiqqer-frontendUsers-redirect"
+         {if !empty($redirectUrl)}data-url="{$redirectUrl}"{/if}
+         data-instant="{if $instantRedirect}1{else}0{/if}"
+         data-reload="{if $instantReload}1{else}0{/if}"
+    >
+        {if !$instantRedirect && !$instantReload}
             {locale group="quiqqer/frontend-users" var="control.registration.auto_redirect" url=$redirectUrl}
         {/if}
     </div>
diff --git a/src/QUI/FrontendUsers/Controls/Registration.php b/src/QUI/FrontendUsers/Controls/Registration.php
index db44d25aafdb83d381238baa315c1f51f9a116f5..7b1a1e438132c8042df81ac6933dcc952da368bc 100644
--- a/src/QUI/FrontendUsers/Controls/Registration.php
+++ b/src/QUI/FrontendUsers/Controls/Registration.php
@@ -129,7 +129,7 @@ public function getBody(): string
 
                 $Engine->assign(
                     'error',
-                    QUI::getLocale()->get('quiqqer/frontend-user', 'controls.Registation.general_error')
+                    QUI::getLocale()->get('quiqqer/frontend-users', 'controls.Registation.general_error')
                 );
             }
         }
@@ -157,12 +157,16 @@ public function getBody(): string
         // redirect directives
         $redirectUrl = false;
         $instantRedirect = false;
+        $instantReload = false;
 
         if ($success) {
+            $instantReload = !empty($registrationSettings['reloadOnSuccess']);
+
             if (
-                $this->RegisteredUser
-                && $this->RegisteredUser->isActive()
-                && $registrationSettings['autoLoginOnActivation']
+                !$instantReload &&
+                $this->RegisteredUser &&
+                $this->RegisteredUser->isActive() &&
+                $registrationSettings['autoLoginOnActivation']
             ) {
                 // instantly redirect (only used on auto-login)
                 $loginSettings = $RegistrarHandler->getLoginSettings();
@@ -180,7 +184,9 @@ public function getBody(): string
                 } catch (Exception $Exception) {
                     QUI\System\Log::writeException($Exception);
                 }
-            } elseif (!empty($registrationSettings['autoRedirectOnSuccess'][$projectLang])) {
+            }
+
+            if (!$instantReload && !$redirectUrl && !empty($registrationSettings['autoRedirectOnSuccess'][$projectLang])) {
                 // show success message and redirect after 10 seconds
                 try {
                     $RedirectSite = QUI\Projects\Site\Utils::getSiteByLink(
@@ -333,6 +339,7 @@ public function getBody(): string
             'success' => $success,
             'redirectUrl' => $redirectUrl,
             'instantRedirect' => $instantRedirect,
+            'instantReload' => $instantReload,
             'Login' => $Login,
             'termsOfUseLabel' => $termsOfUseLabel,
             'termsOfUseRequired' => $termsOfUseRequired,
@@ -551,8 +558,17 @@ public function register()
                 break;
 
             case $RegistrarHandler::ACTIVATION_MODE_AUTO:
+            case $RegistrarHandler::ACTIVATION_MODE_AUTO_WITH_EMAIL_CONFIRM:
                 if (!$NewUser->isActive()) {
-                    $NewUser->activate(false, $SystemUser);
+                    $NewUser->activate('', $SystemUser);
+                }
+
+                if ($registrarSettings['activationMode'] == $RegistrarHandler::ACTIVATION_MODE_AUTO_WITH_EMAIL_CONFIRM) {
+                    $RegistrarHandler->sendEmailConfirmationMail(
+                        $NewUser,
+                        $NewUser->getAttribute('email'),
+                        $Registrar->getProject()
+                    );
                 }
                 break;
         }
diff --git a/src/QUI/FrontendUsers/Controls/RegistrationSignUp.html b/src/QUI/FrontendUsers/Controls/RegistrationSignUp.html
index cfc8405777b8d3786224fbe55e6be2a274aedb09..79bb67e43252101cf15e2627d2ceef3b297d61e2 100644
--- a/src/QUI/FrontendUsers/Controls/RegistrationSignUp.html
+++ b/src/QUI/FrontendUsers/Controls/RegistrationSignUp.html
@@ -6,8 +6,8 @@
 
 {if isset($fireUserActivationEvent)}
     <script>
-        require(['qui/QUI'], function(QUI) {
-            (function() {
+        require(['qui/QUI'], function (QUI) {
+            (function () {
                 QUI.fireEvent('quiqqerFrontendUsersUserActivate', [
                     '{$User->getUUID()}',
                     '{$registrarHash}',
@@ -23,64 +23,62 @@
         style="display: none"
 >
     {if $showLoggedInWarning}
-    <div class="quiqqer-fu-registrationSignUp-registration-logged-in message-information">
-        {locale group="quiqqer/frontend-users" var="message.types.registration.already_registered"}
-    </div>
+        <div class="quiqqer-fu-registrationSignUp-registration-logged-in message-information">
+            {locale group="quiqqer/frontend-users" var="message.types.registration.already_registered"}
+        </div>
     {else}
 
-    {if $msgSuccess}
-    <div class="content-message-success">
-        {$msgSuccess}
-        {if $redirect}
-        <span data-redirecturl="{$redirect}" class="quiqqer-fu-registrationSignUp-registration-redirect">
+        {if $msgSuccess}
+            <div class="content-message-success">
+                {$msgSuccess}
+                {if $redirect}
+                    <span data-redirecturl="{$redirect}" class="quiqqer-fu-registrationSignUp-registration-redirect">
             {locale group="quiqqer/frontend-users" var="RegistrationSignUp.message.redirect" url=$redirect}
             </span>
-        {elseif $nextLinksText}
-        <p class="quiqqer-fu-registrationSignUp-registration-nextlinks">
-            {$nextLinksText}
-        </p>
-        {/if}
-    </div>
-    {elseif $msgError}
-    <div class="content-message-error">
-        {$msgError}
-    </div>
-    {else}
-    {if $this->getAttribute('header')}
-        <h2>{locale group="quiqqer/frontend-users" var="control.registration.sign.up.title"}</h2>
-    {/if}
-    <div class="quiqqer-fu-registrationSignUp-registration-social">
-        {foreach $Registrars as $Registrar}
-        <form action=""
-              method="POST"
-              class="quiqqer-fu-registrationSignUp-registration-social-entry {$Registrar->getAttribute('icon-css-class')}"
-              data-registrar="{$Registrar->getHash()}"
-              data-registration_id="{$registrationId}"
-        >
-            {$this->getRegistrarIcon($Registrar)}
-            <input type="hidden" name="registrar" value="{$Registrar->getHash()}"/>
-            <input type="hidden" name="registration" value="1"/>
-            <input type="hidden" name="registration_id" value="{$registrationId}"/>
-        </form>
-        {/foreach}
-    </div>
-
-    {if !$msgSuccess && $Email}
-        {if $Registrars->count()}
-            {locale group="quiqqer/frontend-users" var="control.registration.sign.up.message.between"}
-        {/if}
-
-        <form name="quiqqer-fu-registrationSignUp-email"
-              class="quiqqer-fu-registrationSignUp-registration-email"
-              data-registrar="{$Email->getHash()}"
-              data-registration_id="{$registrationId}"
-        >
-            <section class="quiqqer-fu-registrationSignUp-email-mailSection">
-                <label>
+                {elseif $nextLinksText}
+                    <p class="quiqqer-fu-registrationSignUp-registration-nextlinks">
+                        {$nextLinksText}
+                    </p>
+                {/if}
+            </div>
+        {elseif $msgError}
+            <div class="content-message-error">
+                {$msgError}
+            </div>
+        {else}
+            {if $this->getAttribute('header')}
+                <h2>{locale group="quiqqer/frontend-users" var="control.registration.sign.up.title"}</h2>
+            {/if}
+            <div class="quiqqer-fu-registrationSignUp-registration-social">
+                {foreach $Registrars as $Registrar}
+                    <form action=""
+                          method="POST"
+                          class="quiqqer-fu-registrationSignUp-registration-social-entry {$Registrar->getAttribute('icon-css-class')}"
+                          data-registrar="{$Registrar->getHash()}"
+                          data-registration_id="{$registrationId}"
+                    >
+                        {$this->getRegistrarIcon($Registrar)}
+                        <input type="hidden" name="registrar" value="{$Registrar->getHash()}"/>
+                        <input type="hidden" name="registration" value="1"/>
+                        <input type="hidden" name="registration_id" value="{$registrationId}"/>
+                    </form>
+                {/foreach}
+            </div>
+            {if !$msgSuccess && $Email}
+                {if $Registrars->count()}
+                    {locale group="quiqqer/frontend-users" var="control.registration.sign.up.message.between"}
+                {/if}
+                <form name="quiqqer-fu-registrationSignUp-email"
+                      class="quiqqer-fu-registrationSignUp-registration-email"
+                      data-registrar="{$Email->getHash()}"
+                      data-registration_id="{$registrationId}"
+                >
+                    <section class="quiqqer-fu-registrationSignUp-email-mailSection">
+                        <label>
                     <span class="label">
                         {locale group="quiqqer/frontend-users" var="control.registration.sign.up.email.title"}
                     </span>
-                    <span class="field">
+                            <span class="field">
                     <span class="icon fa fa-envelope"></span>
                         <input type="email"
                                name="email"
@@ -89,106 +87,109 @@
                                {if $this->getAttribute('autocomplete')}autocomplete="email"{else}autocomplete="false"{/if}
                         />
                     </span>
-                </label>
-
-                {if $useCaptcha && $isCaptchaInvisible}
-                <div class="visible">
-                    {$captchaHTML}
-                </div>
-                {/if}
-
-                <div class="quiqqer-fu-registrationSignUp-email-buttons">
-                    {if $RegistrationTrial && $this->getAttribute('registration-trial')}
-                    <button type="submit" name="trial-account">
-                        {locale group="quiqqer/frontend-users" var="control.registration.sign.up.try"}
-                    </button>
-                    <input type="hidden"
-                           name="registration-trial-registrator"
-                           value="{$RegistrationTrial->getHash()}"
-                    />
+                        </label>
+
+                        {if $useCaptcha && $isCaptchaInvisible}
+                            <div class="visible">
+                                {$captchaHTML}
+                            </div>
+                        {/if}
+
+                        <div class="quiqqer-fu-registrationSignUp-email-buttons">
+                            {if $RegistrationTrial && $this->getAttribute('registration-trial')}
+                                <button type="submit" name="trial-account">
+                                    {locale group="quiqqer/frontend-users" var="control.registration.sign.up.try"}
+                                </button>
+                                <input type="hidden"
+                                       name="registration-trial-registrator"
+                                       value="{$RegistrationTrial->getHash()}"
+                                />
+                            {/if}
+                            <button type="submit" name="email-next">
+                                {locale group="quiqqer/frontend-users" var="control.registration.sign.up.password.next"}
+                            </button>
+                        </div>
+                    </section>
+
+                    {if $useCaptcha && $isCaptchaInvisible === false}
+                        {$captchaHTML}
                     {/if}
-                    <button type="submit" name="email-next">
-                        {locale group="quiqqer/frontend-users" var="control.registration.sign.up.password.next"}
-                    </button>
-                </div>
-            </section>
 
-            {if $useCaptcha && $isCaptchaInvisible === false}
-                {$captchaHTML}
-            {/if}
-
-            {if $fullnameInput !== 'none'}
-            <section class="quiqqer-fu-registrationSignUp-email-fullnameSection">
-                <label>
+                    {if $fullnameInput !== 'none'}
+                        <section class="quiqqer-fu-registrationSignUp-email-fullnameSection">
+                            <label>
                     <span class="label">
                         {locale group="quiqqer/frontend-users" var="control.registration.sign.up.firstname.title"}
                     </span>
-                    <span class="field">
+                                <span class="field">
                     <span class="icon fa fa-user"></span>
-                        <input type="text" name="firstname"{if $fullnameInput === 'firstname_required' || $fullnameInput === 'fullname_required'} data-required="1"{/if}/>
+                        <input type="text"
+                               name="firstname"{if $fullnameInput === 'firstname_required' || $fullnameInput === 'fullname_required'} data-required="1"{/if}/>
                     </span>
-                </label>
+                            </label>
 
-                {if $fullnameInput === 'fullname_optional' || fullname_optional === 'fullname_required'}
-                <label>
+                            {if $fullnameInput === 'fullname_optional' || fullname_optional === 'fullname_required'}
+                                <label>
                     <span class="label">
                         {locale group="quiqqer/frontend-users" var="control.registration.sign.up.lastname.title"}
                     </span>
-                    <span class="field">
+                                    <span class="field">
                     <span class="icon fa fa-user"></span>
-                        <input type="text" name="lastname"{if $fullnameInput === 'fullname_required'} data-required="1"{/if}/>
+                        <input type="text"
+                               name="lastname"{if $fullnameInput === 'fullname_required'} data-required="1"{/if}/>
                     </span>
-                </label>
-                {/if}
-
-                <div class="quiqqer-fu-registrationSignUp-email-buttons">
-                    <button type="submit" name="fullname-next">
-                        {locale group="quiqqer/frontend-users" var="control.registration.sign.up.fullname.next"}
-                    </button>
-                </div>
-            </section>
-            {/if}
+                                </label>
+                            {/if}
+
+                            <div class="quiqqer-fu-registrationSignUp-email-buttons">
+                                <button type="submit" name="fullname-next">
+                                    {locale group="quiqqer/frontend-users" var="control.registration.sign.up.fullname.next"}
+                                </button>
+                            </div>
+                        </section>
+                    {/if}
 
-            {if $passwordInput !== 'none'}
-            <section class="quiqqer-fu-registrationSignUp-email-passwordSection">
-                <label>
+                    {if $passwordInput !== 'none'}
+                        <section class="quiqqer-fu-registrationSignUp-email-passwordSection">
+                            <label>
                     <span class="label">
                         {locale group="quiqqer/frontend-users" var="control.registration.sign.up.password.title"}
                     </span>
-                    <span class="field">
+                                <span class="field">
                     <span class="icon fa fa-key"></span>
                         <input type="password" name="password" required autocomplete="off"/>
                     </span>
-                </label>
-
-                <div class="quiqqer-fu-registrationSignUp-email-buttons">
-                    <button type="submit" name="create-account">
-                        {locale group="quiqqer/frontend-users" var="control.registration.sign.up.password.next"}
-                    </button>
-                </div>
-            </section>
+                            </label>
+
+                            <div class="quiqqer-fu-registrationSignUp-email-buttons">
+                                <button type="submit" name="create-account">
+                                    {locale group="quiqqer/frontend-users" var="control.registration.sign.up.password.next"}
+                                </button>
+                            </div>
+                        </section>
+                    {/if}
+                </form>
             {/if}
-        </form>
-    {/if}
-
-    <div class="quiqqer-fu-registrationSignUp-terms">
+            <div class="quiqqer-fu-registrationSignUp-terms">
         <span class="quiqqer-fu-registrationSignUp-terms-text">
             {$termsPrivacyMessage}
 
+            {template_event name="quiqqer::frontend-users::RegistrationSignUp::termsAfter"}
+
             <button name="decline"
                     title="{locale group='quiqqer/frontend-users' var='control.registration.sign.up.button.terms.decline'}"
             >
                 <span class="fa fa-close"></span>
             </button>
         </span>
-        <div class="quiqqer-fu-registrationSignUp-terms-buttons"></div>
-    </div>
-    {/if}
+                <div class="quiqqer-fu-registrationSignUp-terms-buttons"></div>
+            </div>
+        {/if}
     {/if}
 </section>
 
 {if !empty($this->getAttribute('content')) && $showContent && !$msgSuccess && !$msgError}
-<section class="quiqqer-fu-registrationSignUp-info" style="display: none">
-    {$this->getAttribute('content')}
-</section>
+    <section class="quiqqer-fu-registrationSignUp-info" style="display: none">
+        {$this->getAttribute('content')}
+    </section>
 {/if}
diff --git a/src/QUI/FrontendUsers/Controls/RegistrationSignUp.php b/src/QUI/FrontendUsers/Controls/RegistrationSignUp.php
index bb8ebe1cfa15abfda06c5670e16365e8849240f9..9c8cdda44994c2f42263408da90db2d6fcf9fb64 100644
--- a/src/QUI/FrontendUsers/Controls/RegistrationSignUp.php
+++ b/src/QUI/FrontendUsers/Controls/RegistrationSignUp.php
@@ -415,8 +415,10 @@ protected function siteTermsPrivacy(QUI\Interfaces\Template\EngineInterface $Eng
                 'control.sign.up.terms_of_use_and_privacy_policy.label',
                 [
                     'termsOfUseUrl' => $SiteTerms->getUrlRewritten(),
+                    'termsOfUseSiteId' => $SiteTerms->getId(),
                     'termsOfUseSiteTitle' => $SiteTerms->getAttribute('title'),
                     'privacyPolicyUrl' => $SitePrivacy->getUrlRewritten(),
+                    'privacyPolicySiteId' => $SitePrivacy->getId(),
                     'privacyPolicySiteTitle' => $SitePrivacy->getAttribute('title')
                 ]
             );
@@ -426,6 +428,7 @@ protected function siteTermsPrivacy(QUI\Interfaces\Template\EngineInterface $Eng
                 'control.sign.up.terms_of_use.label',
                 [
                     'termsOfUseUrl' => $SiteTerms->getUrlRewritten(),
+                    'termsOfUseSiteId' => $SiteTerms->getId(),
                     'termsOfUseSiteTitle' => $SiteTerms->getAttribute('title')
                 ]
             );
@@ -435,6 +438,7 @@ protected function siteTermsPrivacy(QUI\Interfaces\Template\EngineInterface $Eng
                 'control.sign.up.privacy_policy.label',
                 [
                     'privacyPolicyUrl' => $SitePrivacy->getUrlRewritten(),
+                    'privacyPolicySiteId' => $SitePrivacy->getId(),
                     'privacyPolicySiteTitle' => $SitePrivacy->getAttribute('title')
                 ]
             );
diff --git a/src/QUI/FrontendUsers/Controls/UserIcon.php b/src/QUI/FrontendUsers/Controls/UserIcon.php
index 15646984d3bf9ead8f1cb15b3c20cc1cb5482620..a2813b232cf4a2f4fbeb219a34b475ef2ebe40da 100644
--- a/src/QUI/FrontendUsers/Controls/UserIcon.php
+++ b/src/QUI/FrontendUsers/Controls/UserIcon.php
@@ -81,7 +81,7 @@ public function getBody(): string
             $AvatarImage = new ExternalImage(Utils::getGravatarUrl($userEmail, $iconHeight));
 
             $Engine->assign([
-                'avatarImageUrl' => $AvatarImage->getSizeCacheUrl($iconWidth, $iconHeight)
+                'avatarImageUrl' => $AvatarImage->getSizeCacheUrl()
             ]);
         } else {
             $avatarMediaUrl = $User->getAttribute('avatar');
@@ -133,7 +133,7 @@ public function getBody(): string
      *
      * @return false|QUI\Projects\Media\Image|string
      */
-    protected function getDefaultAvatarImage(): QUI\Projects\Media\Image|bool|string
+    protected function getDefaultAvatarImage(): QUI\Projects\Media\Image | bool | string
     {
         try {
             $Conf = QUI::getPackage('quiqqer/frontend-users')->getConfig();
diff --git a/src/QUI/FrontendUsers/EmailConfirmVerification.php b/src/QUI/FrontendUsers/EmailConfirmLinkVerification.php
similarity index 55%
rename from src/QUI/FrontendUsers/EmailConfirmVerification.php
rename to src/QUI/FrontendUsers/EmailConfirmLinkVerification.php
index 9ddf5af0fcdcf54f816a344ef4dc9bd1a4033e86..ef085a23ca31a7d72a5ae583211501c961843e51 100644
--- a/src/QUI/FrontendUsers/EmailConfirmVerification.php
+++ b/src/QUI/FrontendUsers/EmailConfirmLinkVerification.php
@@ -4,7 +4,9 @@
 
 use QUI;
 use QUI\Exception;
-use QUI\Verification\AbstractVerification;
+use QUI\Verification\Entity\LinkVerification;
+use QUI\Verification\Enum\VerificationErrorReason;
+use QUI\Verification\Entity\AbstractVerification;
 
 /**
  * Class EmailConfirmVerification
@@ -13,16 +15,17 @@
  *
  * @package QUI\FrontendUsers
  */
-class EmailConfirmVerification extends AbstractVerification
+class EmailConfirmLinkVerification extends AbstractFrontendUsersLinkVerificationHandler
 {
     /**
      * Get the duration of a Verification (minutes)
      *
+     * @param AbstractVerification $verification
      * @return int - duration in minutes;
      * if this method returns false use the module setting default value
      * @throws Exception
      */
-    public function getValidDuration(): int
+    public function getValidDuration(AbstractVerification $verification): int
     {
         $settings = Handler::getInstance()->getMailSettings();
         return (int)$settings['verificationValidityDuration'];
@@ -31,21 +34,21 @@ public function getValidDuration(): int
     /**
      * Execute this method on successful verification
      *
+     * @param LinkVerification $verification
      * @return void
      */
-    public function onSuccess(): void
+    public function onSuccess(LinkVerification $verification): void
     {
-        $userId = $this->getIdentifier();
-
         try {
             $RegistrarHandler = QUI\FrontendUsers\Handler::getInstance();
-            $User = QUI::getUsers()->get($userId);
-            $newEmail = $this->additionalData['newEmail'];
+            $userUuid = $verification->getCustomDataEntry('uuid');
+            $User = QUI::getUsers()->get($userUuid);
+            $newEmail = $verification->getCustomDataEntry('newEmail');
+            $oldEmail = $User->getAttribute('email');
 
             // if users cannot set their own username -> change username as well
             // if it equals the old email-address
             if (!$RegistrarHandler->isUsernameInputAllowed()) {
-                $oldEmail = $User->getAttribute('email');
                 $username = $User->getUsername();
 
                 if ($oldEmail === $username) {
@@ -55,9 +58,11 @@ public function onSuccess(): void
 
             $User->setAttribute('email', $newEmail);
             $User->save(QUI::getUsers()->getSystemUser());
+
+            QUI::getEvents()->fireEvent('quiqqerFrontendUsersEmailChanged', [$User, $oldEmail, $newEmail]);
         } catch (\Exception $Exception) {
             QUI\System\Log::addError(
-                self::class . ' :: onSuccess -> Could not find user #' . $userId
+                self::class . ' :: onSuccess -> Could not find user #' . $userUuid
             );
 
             QUI\System\Log::writeException($Exception);
@@ -67,9 +72,11 @@ public function onSuccess(): void
     /**
      * Execute this method on unsuccessful verification
      *
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
      * @return void
      */
-    public function onError(): void
+    public function onError(LinkVerification $verification, VerificationErrorReason $reason): void
     {
         // nothing
     }
@@ -77,9 +84,10 @@ public function onError(): void
     /**
      * This message is displayed to the user on successful verification
      *
+     * @param LinkVerification $verification
      * @return string
      */
-    public function getSuccessMessage(): string
+    public function getSuccessMessage(LinkVerification $verification): string
     {
         return '';
     }
@@ -87,10 +95,11 @@ public function getSuccessMessage(): string
     /**
      * This message is displayed to the user on unsuccessful verification
      *
-     * @param string $reason - The reason for the error (see \QUI\Verification\Verifier::REASON_)
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
      * @return string
      */
-    public function getErrorMessage(string $reason): string
+    public function getErrorMessage(LinkVerification $verification, VerificationErrorReason $reason): string
     {
         return '';
     }
@@ -98,17 +107,22 @@ public function getErrorMessage(string $reason): string
     /**
      * Automatically redirect the user to this URL on successful verification
      *
-     * @return string|false - If this method returns false, no redirection takes place
+     * @param LinkVerification $verification
+     * @return string|null - If this method returns false, no redirection takes place
      * @throws Exception
      */
-    public function getOnSuccessRedirectUrl(): bool|string
+    public function getOnSuccessRedirectUrl(LinkVerification $verification): ?string
     {
-        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite(
-            $this->getProject()
-        );
+        $project = $this->getProject($verification);
+
+        if (!$project) {
+            return null;
+        }
+
+        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite($project);
 
         if (!$RegistrationSite) {
-            return false;
+            return null;
         }
 
         return $RegistrationSite->getUrlRewritten([], [
@@ -119,37 +133,23 @@ public function getOnSuccessRedirectUrl(): bool|string
     /**
      * Automatically redirect the user to this URL on unsuccessful verification
      *
-     * @return string|false - If this method returns false, no redirection takes place
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
+     * @return string|null - If this method returns false, no redirection takes place
      * @throws Exception
      */
-    public function getOnErrorRedirectUrl(): bool|string
+    public function getOnErrorRedirectUrl(LinkVerification $verification, VerificationErrorReason $reason): ?string
     {
-        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite(
-            $this->getProject()
-        );
+        $project = $this->getProject($verification);
+
+        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite($project);
 
         if (!$RegistrationSite) {
-            return false;
+            return null;
         }
 
         return $RegistrationSite->getUrlRewritten([], [
             'error' => 'emailconfirm'
         ]);
     }
-
-    /**
-     * Get the Project this Verification is intended for
-     *
-     * @return QUI\Projects\Project
-     * @throws Exception
-     */
-    protected function getProject(): QUI\Projects\Project
-    {
-        $additionalData = $this->getAdditionalData();
-
-        return QUI::getProjectManager()->getProject(
-            $additionalData['project'],
-            $additionalData['projectLang']
-        );
-    }
 }
diff --git a/src/QUI/FrontendUsers/EmailVerification.php b/src/QUI/FrontendUsers/EmailVerification.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c0d1d6c4bbce3e7fc2081d6e0cd2fd868be29f1
--- /dev/null
+++ b/src/QUI/FrontendUsers/EmailVerification.php
@@ -0,0 +1,134 @@
+<?php
+
+namespace QUI\FrontendUsers;
+
+use QUI;
+use QUI\Exception;
+use QUI\Verification\Entity\LinkVerification;
+use QUI\Verification\Enum\VerificationErrorReason;
+use QUI\Verification\Entity\AbstractVerification;
+
+/**
+ * User verification to confirm an e-mail-address
+ */
+class EmailVerification extends AbstractFrontendUsersLinkVerificationHandler
+{
+    /**
+     * Get the duration of a Verification (minutes)
+     *
+     * @param AbstractVerification $verification
+     * @return int - duration in minutes;
+     * if this method returns false use the module setting default value
+     * @throws Exception
+     */
+    public function getValidDuration(AbstractVerification $verification): int
+    {
+        $settings = Handler::getInstance()->getMailSettings();
+        return (int)$settings['verificationValidityDuration'];
+    }
+
+    /**
+     * Execute this method on successful verification
+     *
+     * @param LinkVerification $verification
+     * @return void
+     * @throws \Exception
+     */
+    public function onSuccess(LinkVerification $verification): void
+    {
+        try {
+            $User = QUI::getUsers()->get($verification->getCustomDataEntry('uuid'));
+            $email = $verification->getCustomDataEntry('email');
+
+            // Set primary email as verified
+            if ($email === $User->getAttribute('email')) {
+                Utils::setDefaultUserEmailVerified($User);
+            }
+
+            Utils::setEmailAddressAsVerfifiedForUser($email, $User);
+        } catch (\Exception $Exception) {
+            QUI\System\Log::writeException($Exception);
+            throw $Exception;
+        }
+    }
+
+    /**
+     * Execute this method on unsuccessful verification
+     *
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
+     * @return void
+     */
+    public function onError(LinkVerification $verification, VerificationErrorReason $reason): void
+    {
+        // nothing
+    }
+
+    /**
+     * This message is displayed to the user on successful verification
+     *
+     * @param LinkVerification $verification
+     * @return string
+     */
+    public function getSuccessMessage(LinkVerification $verification): string
+    {
+        return '';
+    }
+
+    /**
+     * This message is displayed to the user on unsuccessful verification
+     *
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
+     * @return string
+     */
+    public function getErrorMessage(LinkVerification $verification, VerificationErrorReason $reason): string
+    {
+        return '';
+    }
+
+    /**
+     * Automatically redirect the user to this URL on successful verification
+     *
+     * @param LinkVerification $verification
+     * @return string|null - If this method returns false, no redirection takes place
+     * @throws Exception
+     */
+    public function getOnSuccessRedirectUrl(LinkVerification $verification): ?string
+    {
+        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite(
+            $this->getProject($verification)
+        );
+
+        if (!$RegistrationSite) {
+            return null;
+        }
+
+        return $RegistrationSite->getUrlRewritten([], [
+            'success' => 'emailconfirm'
+        ]);
+    }
+
+    /**
+     * Automatically redirect the user to this URL on unsuccessful verification
+     *
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
+     * @return string|null - If this method returns false, no redirection takes place
+     * @throws Exception
+     */
+    public function getOnErrorRedirectUrl(LinkVerification $verification, VerificationErrorReason $reason): ?string
+    {
+        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite(
+            $this->getProject($verification)
+        );
+
+        if (!$RegistrationSite) {
+            return null;
+        }
+
+        return $RegistrationSite->getUrlRewritten([], [
+            'error' => 'emailconfirm'
+        ]);
+    }
+}
diff --git a/src/QUI/FrontendUsers/ErpProvider.php b/src/QUI/FrontendUsers/ErpProvider.php
index 21da7a92dff456be401619ebdb190e06f0fe5cba..fce15d2ff5ded07ffc5920ef647c938ee301c249 100644
--- a/src/QUI/FrontendUsers/ErpProvider.php
+++ b/src/QUI/FrontendUsers/ErpProvider.php
@@ -54,6 +54,23 @@ public static function getMailLocale(): array
                 'content.description' => ['quiqqer/frontend-users', 'mail.registration_activation.body.description']
             ],
 
+            [
+                'title' => QUI::getLocale()->get(
+                    'quiqqer/frontend-users',
+                    'mail.text.confirmEmail.title'
+                ),
+                'description' => QUI::getLocale()->get(
+                    'quiqqer/frontend-users',
+                    'mail.text.confirmEmail.description'
+                ),
+                'subject' => ['quiqqer/frontend-users', 'mail.confirm_email_address.subject'],
+                'content' => ['quiqqer/frontend-users', 'mail.confirm_email_address.body'],
+
+                'subject.description' => ['quiqqer/frontend-users', 'mail.confirm_email_address.subject.description'],
+                'content.description' => ['quiqqer/frontend-users', 'mail.confirm_email_address.body.description']
+            ],
+
+
             [
                 'title' => QUI::getLocale()->get(
                     'quiqqer/frontend-users',
diff --git a/src/QUI/FrontendUsers/Events.php b/src/QUI/FrontendUsers/Events.php
index a5c0d482e37f8453f0db23953456ce0ea9f5b206..2e695ccad0f09ec9160eb90498eb772dd7f49e1b 100644
--- a/src/QUI/FrontendUsers/Events.php
+++ b/src/QUI/FrontendUsers/Events.php
@@ -5,8 +5,8 @@
 use QUI;
 use QUI\Exception;
 use QUI\Interfaces\Users\User;
-use QUI\Verification\Verifier;
 use QUI\Smarty\Collector;
+use QUI\Verification\VerificationRepository;
 
 use function base64_encode;
 use function json_encode;
@@ -62,8 +62,9 @@ public static function onSiteSave(QUI\Interfaces\Projects\Site $Site): void
     {
         // register path
         if (
-            $Site->getAttribute('active') &&
-            $Site->getAttribute('type') == 'quiqqer/frontend-users:types/profile'
+            $Site->getAttribute('active')
+            && $Site->getAttribute('type') == 'quiqqer/frontend-users:types/profile'
+            && method_exists($Site, 'getLocation')
         ) {
             $url = $Site->getLocation();
             $url = str_replace(QUI\Rewrite::URL_DEFAULT_SUFFIX, '', $url);
@@ -196,7 +197,7 @@ public static function autoLogin(QUI\Interfaces\Users\User $User, bool $checkEli
                 'user_agent' => $useragent,
                 'secHash' => $secHash
             ],
-            ['id' => $User->getUUID()]
+            ['uuid' => $User->getUUID()]
         );
 
         QUI::getEvents()->fireEvent(
@@ -234,13 +235,16 @@ public static function onUserDelete(User $User): void
     {
         // delete Verification for user (if not yet deleted by quiqqer/verification cron)
         try {
-            $Verification = Verifier::getVerificationByIdentifier(
-                $User->getUUID(),
-                ActivationVerification::getType()
+            $repository = new VerificationRepository();
+            $verification = $repository->findByIdentifier(
+                'activate-' . $User->getUUID()
             );
 
-            Verifier::removeVerification($Verification);
-        } catch (\Exception) {
+            // if Verification not found it does not have to be deleted
+            if ($verification) {
+                $repository->delete($verification);
+            }
+        } catch (\Throwable) {
             // nothing -> if Verification not found it does not have to be deleted
         }
     }
diff --git a/src/QUI/FrontendUsers/Exception/EmailAddressNotVerifiableException.php b/src/QUI/FrontendUsers/Exception/EmailAddressNotVerifiableException.php
new file mode 100644
index 0000000000000000000000000000000000000000..f057515c7fa9e4d91bcf3ac666db248a6d0c3d93
--- /dev/null
+++ b/src/QUI/FrontendUsers/Exception/EmailAddressNotVerifiableException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace QUI\FrontendUsers\Exception;
+
+use QUI\FrontendUsers\Exception;
+
+class EmailAddressNotVerifiableException extends Exception
+{
+    protected $code = 50002;
+}
diff --git a/src/QUI/FrontendUsers/Handler.php b/src/QUI/FrontendUsers/Handler.php
index 114793fdebcdaf03987097fb1e4f29da624d3d62..036f8d2849ed015b5e989a2e94cc94892e643038 100644
--- a/src/QUI/FrontendUsers/Handler.php
+++ b/src/QUI/FrontendUsers/Handler.php
@@ -1,17 +1,16 @@
 <?php
 
-/**
- * This file contains QUI\FrontendUsers\Handler
- */
-
 namespace QUI\FrontendUsers;
 
 use QUI;
+use QUI\Interfaces\Users\User as QUIUserInterface;
 use QUI\Mail\Mailer;
 use QUI\Utils\Singleton;
-use QUI\Verification\Verifier;
+use QUI\Verification\Interface\VerificationFactoryInterface;
+use QUI\Verification\VerificationFactory;
 
 use function array_filter;
+use function time;
 
 /**
  * Class Registration Handling
@@ -33,6 +32,7 @@ class Handler extends Singleton
      */
     const ACTIVATION_MODE_MAIL = 'mail';
     const ACTIVATION_MODE_AUTO = 'auto';
+    const ACTIVATION_MODE_AUTO_WITH_EMAIL_CONFIRM = 'autoWithEmailConfirm';
     const ACTIVATION_MODE_MANUAL = 'manual';
 
     /**
@@ -75,6 +75,7 @@ class Handler extends Singleton
     const USER_ATTR_REGISTRAR = 'quiqqer.frontendUsers.registrar';
     const USER_ATTR_ACTIVATION_LOGIN_EXECUTED = 'quiqqer.frontendUsers.activationLoginExecuted';
     const USER_ATTR_EMAIL_VERIFIED = 'quiqqer.frontendUsers.emailVerified';
+    const USER_ATTR_EMAIL_ADDRESSES_VERIFIED = 'quiqqer.frontendUsers.emailAddressesVerified';
     const USER_ATTR_USER_ACTIVATION_REQUIRED = 'quiqqer.frontendUsers.userActivationRequired';
 
     /**
@@ -97,8 +98,13 @@ class Handler extends Singleton
     /**
      * Handler constructor.
      */
-    public function __construct()
-    {
+    public function __construct(
+        private ?VerificationFactoryInterface $verificationFactory = null
+    ) {
+        if (is_null($this->verificationFactory)) {
+            $this->verificationFactory = new VerificationFactory();
+        }
+
         $this->Registrar = new RegistrarCollection();
     }
 
@@ -135,7 +141,7 @@ public function getRegistrars(): RegistrarCollection
      * @param string $registrar - Registrar type
      * @return false|RegistrarInterface
      */
-    public function getRegistrar(string $registrar): bool|RegistrarInterface
+    public function getRegistrar(string $registrar): bool | RegistrarInterface
     {
         /** @var RegistrarInterface $Registrar */
         foreach ($this->getAvailableRegistrars() as $Registrar) {
@@ -153,7 +159,7 @@ public function getRegistrar(string $registrar): bool|RegistrarInterface
      * @param QUI\Interfaces\Users\User $User
      * @return RegistrarInterface|false
      */
-    public function getRegistrarByUser(QUI\Interfaces\Users\User $User): bool|RegistrarInterface
+    public function getRegistrarByUser(QUI\Interfaces\Users\User $User): bool | RegistrarInterface
     {
         $registrar = $User->getAttribute(self::USER_ATTR_REGISTRAR);
 
@@ -170,7 +176,7 @@ public function getRegistrarByUser(QUI\Interfaces\Users\User $User): bool|Regist
      * @param string $hash
      * @return false|RegistrarInterface
      */
-    public function getRegistrarByHash(string $hash): bool|RegistrarInterface
+    public function getRegistrarByHash(string $hash): bool | RegistrarInterface
     {
         /** @var RegistrarInterface $Registrar */
         foreach ($this->getAvailableRegistrars() as $Registrar) {
@@ -341,10 +347,10 @@ public function getMailSettings(): array
     /**
      * Get settings for one or all Registrars
      *
-     * @param string|null $registrarClass (optional) - Registar class path (namespace)
+     * @param string|null $registrarClass (optional) - Registrar class path (namespace)
      * @return array
      */
-    public function getRegistrarSettings(string $registrarClass = null): array
+    public function getRegistrarSettings(null | string $registrarClass = null): array
     {
         try {
             $Conf = QUI::getPackage('quiqqer/frontend-users')->getConfig();
@@ -412,13 +418,17 @@ public function sendActivationMail(QUI\Interfaces\Users\User $User, RegistrarInt
     {
         $Project = $Registrar->getProject();
 
-        $ActivationVerification = new ActivationVerification($User->getUUID(), [
-            'project' => $Project->getName(),
-            'projectLang' => $Project->getLang(),
-            'registrar' => $Registrar->getHash()
-        ]);
-
-        $activationLink = Verifier::startVerification($ActivationVerification, true);
+        $verification = $this->verificationFactory->createLinkVerification(
+            'activate-' . $User->getUUID(),
+            new ActivationLinkVerification(),
+            [
+                'uuid' => $User->getUUID(),
+                'project' => $Project->getName(),
+                'projectLang' => $Project->getLang(),
+                'registrar' => $Registrar->getHash()
+            ],
+            true
+        );
 
         $L = QUI::getLocale();
         $lg = 'quiqqer/frontend-users';
@@ -445,7 +455,7 @@ public function sendActivationMail(QUI\Interfaces\Users\User $User, RegistrarInt
                         'userLastName' => $User->getAttribute('lastname') ?: '',
                         'email' => $User->getAttribute('email'),
                         'date' => $L->formatDate(time()),
-                        'activationLink' => $activationLink
+                        'activationLink' => $verification->getVerificationUrl()
                     ])
                 ]
             );
@@ -474,7 +484,7 @@ public function sendActivationMail(QUI\Interfaces\Users\User $User, RegistrarInt
     public function sendWelcomeMail(
         QUI\Interfaces\Users\User $User,
         QUI\Projects\Project $Project,
-        string $userPassword = null
+        null | string $userPassword = null
     ): void {
         $email = $User->getAttribute('email');
 
@@ -590,10 +600,10 @@ public function sendRegistrationNotice(QUI\Interfaces\Users\User $User, QUI\Proj
     }
 
     /**
-     * Send activtion mail for a user account
+     * Send deactivation mail for a user account
      *
-     * @param QUI\Users\User $User
-     * @param string $newEmail - New E-Mail-Adress
+     * @param QUI\Interfaces\Users\User $User
+     * @param string $newEmail - New E-Mail-Address
      * @param QUI\Projects\Project $Project - The QUIQQER Project where the change action took place
      * @return void
      * @throws QUI\Exception
@@ -603,13 +613,17 @@ public function sendChangeEmailAddressMail(
         string $newEmail,
         QUI\Projects\Project $Project
     ): void {
-        $EmailConfirmVerification = new EmailConfirmVerification($User->getUUID(), [
-            'project' => $Project->getName(),
-            'projectLang' => $Project->getLang(),
-            'newEmail' => $newEmail
-        ]);
-
-        $confirmLink = Verifier::startVerification($EmailConfirmVerification, true);
+        $verification = $this->verificationFactory->createLinkVerification(
+            'confirmemail-' . $User->getUUID(),
+            new EmailConfirmLinkVerification(),
+            [
+                'uuid' => $User->getUUID(),
+                'project' => $Project->getName(),
+                'projectLang' => $Project->getLang(),
+                'newEmail' => $newEmail
+            ],
+            true
+        );
 
         $L = QUI::getLocale();
         $lg = 'quiqqer/frontend-users';
@@ -632,9 +646,71 @@ public function sendChangeEmailAddressMail(
                         'username' => $User->getUsername(),
                         'userFirstName' => $User->getAttribute('firstname') ?: '',
                         'userLastName' => $User->getAttribute('lastname') ?: '',
-                        'newEmail' => $newEmail,
+                        'email' => $newEmail,
+                        'date' => $L->formatDate(time()),
+                        'confirmLink' => $verification->getVerificationUrl()
+                    ])
+                ]
+            );
+        } catch (\Exception $Exception) {
+            QUI\System\Log::addError(
+                self::class . ' :: sendChangeEmailAddressMail -> Send mail failed'
+            );
+
+            QUI\System\Log::writeException($Exception);
+        }
+    }
+
+    /**
+     * Send email to confirm an email address.
+     *
+     * @param QUIUserInterface $User
+     * @param string $email - New E-Mail-Adress
+     * @param QUI\Projects\Project $Project - The QUIQQER Project where the change action took place
+     * @return void
+     *
+     * @throws QUI\Exception
+     */
+    public function sendEmailConfirmationMail(
+        QUIUserInterface $User,
+        string $email,
+        QUI\Projects\Project $Project
+    ): void {
+        $verification = $this->verificationFactory->createLinkVerification(
+            'confirmemail-' . $User->getUUID(),
+            new EmailVerification(),
+            [
+                'uuid' => $User->getUUID(),
+                'project' => $Project->getName(),
+                'projectLang' => $Project->getLang(),
+                'email' => $email
+            ]
+        );
+
+        $L = QUI::getLocale();
+        $lg = 'quiqqer/frontend-users';
+        $tplDir = QUI::getPackage('quiqqer/frontend-users')->getDir() . 'templates/';
+        $host = $Project->getVHost();
+
+        try {
+            $this->sendMail(
+                [
+                    'subject' => $L->get($lg, 'mail.confirm_email_address.subject')
+                ],
+                [
+                    $email
+                ],
+                $tplDir . 'mail.confirm_email_address.html',
+                [
+                    'body' => $L->get($lg, 'mail.confirm_email_address.body', [
+                        'host' => $host,
+                        'userId' => $User->getUUID(),
+                        'username' => $User->getUsername(),
+                        'userFirstName' => $User->getAttribute('firstname') ?: '',
+                        'userLastName' => $User->getAttribute('lastname') ?: '',
+                        'email' => $email,
                         'date' => $L->formatDate(time()),
-                        'confirmLink' => $confirmLink
+                        'confirmLink' => $verification->getVerificationUrl()
                     ])
                 ]
             );
@@ -659,12 +735,15 @@ public function sendChangeEmailAddressMail(
      */
     public function sendDeleteUserConfirmationMail(QUI\Interfaces\Users\User $User, QUI\Projects\Project $Project): void
     {
-        $DeleteUserVerification = new UserDeleteConfirmVerification($User->getUUID(), [
-            'project' => $Project->getName(),
-            'projectLang' => $Project->getLang()
-        ]);
-
-        $confirmLink = Verifier::startVerification($DeleteUserVerification, true);
+        $verification = $this->verificationFactory->createLinkVerification(
+            'confirmdelete-' . $User->getUUID(),
+            new UserDeleteConfirmLinkVerification(),
+            [
+                'uuid' => $User->getUUID(),
+                'project' => $Project->getName(),
+                'projectLang' => $Project->getLang()
+            ]
+        );
 
         $L = QUI::getLocale();
         $lg = 'quiqqer/frontend-users';
@@ -688,7 +767,7 @@ public function sendDeleteUserConfirmationMail(QUI\Interfaces\Users\User $User,
                         'userFirstName' => $User->getAttribute('firstname') ?: '',
                         'userLastName' => $User->getAttribute('lastname') ?: '',
                         'date' => $L->formatDate(time()),
-                        'confirmLink' => $confirmLink
+                        'confirmLink' => $verification->getVerificationUrl()
                     ])
                 ]
             );
@@ -759,7 +838,7 @@ public function sendMail(array $mailData, array $recipients, string $templateFil
      * @return QUI\Projects\Site|false - Site object or false if no ACTIVE registration site found
      * @throws QUI\Exception
      */
-    public function getRegistrationSite(QUI\Projects\Project $Project = null): bool|QUI\Projects\Site
+    public function getRegistrationSite(null | QUI\Projects\Project $Project = null): bool | QUI\Projects\Site
     {
         if (is_null($Project)) {
             $Project = QUI::getProjectManager()->getStandard();
@@ -786,7 +865,7 @@ public function getRegistrationSite(QUI\Projects\Project $Project = null): bool|
      * @return QUI\Projects\Site|false - Site object or false if no ACTIVE registration site found
      * @throws QUI\Exception
      */
-    public function getRegistrationSignUpSite(QUI\Projects\Project $Project = null): bool|QUI\Projects\Site
+    public function getRegistrationSignUpSite(null | QUI\Projects\Project $Project = null): bool | QUI\Projects\Site
     {
         if (is_null($Project)) {
             $Project = QUI::getProjectManager()->getStandard();
@@ -813,7 +892,7 @@ public function getRegistrationSignUpSite(QUI\Projects\Project $Project = null):
      * @return QUI\Projects\Site|false - Site object or false if no ACTIVE login site found
      * @throws QUI\Exception
      */
-    public function getLoginSite(QUI\Projects\Project $Project = null): bool|QUI\Projects\Site
+    public function getLoginSite(null | QUI\Projects\Project $Project = null): bool | QUI\Projects\Site
     {
         if (is_null($Project)) {
             $Project = QUI::getProjectManager()->getStandard();
@@ -840,7 +919,7 @@ public function getLoginSite(QUI\Projects\Project $Project = null): bool|QUI\Pro
      * @return QUI\Projects\Site|false - Site object or false if no ACTIVE profile site found
      * @throws QUI\Exception
      */
-    public function getProfileSite(QUI\Projects\Project $Project = null): bool|QUI\Projects\Site
+    public function getProfileSite(null | QUI\Projects\Project $Project = null): bool | QUI\Projects\Site
     {
         if (is_null($Project)) {
             $Project = QUI::getProjectManager()->getStandard();
@@ -865,7 +944,7 @@ public function getProfileSite(QUI\Projects\Project $Project = null): bool|QUI\P
      *
      * @return false|QUI\Projects\Site
      */
-    public function getRedirectOnActivationSite(): bool|QUI\Projects\Site
+    public function getRedirectOnActivationSite(): bool | QUI\Projects\Site
     {
         try {
             $registrationSettings = $this->getRegistrationSettings();
diff --git a/src/QUI/FrontendUsers/RegistrarInterface.php b/src/QUI/FrontendUsers/RegistrarInterface.php
index e8b76bf1e2ab1b1a0e5643f67a5bbdbe2b923753..2a54cf8825e961ecb6d9b1141274978ad54ba00f 100644
--- a/src/QUI/FrontendUsers/RegistrarInterface.php
+++ b/src/QUI/FrontendUsers/RegistrarInterface.php
@@ -98,7 +98,7 @@ public function getControl(): Control;
      * @param ?QUI\Locale $Locale (optional) - If omitted use QUI::getLocale()
      * @return string
      */
-    public function getTitle(QUI\Locale $Locale = null): string;
+    public function getTitle(null | QUI\Locale $Locale = null): string;
 
     /**
      * Get description
@@ -106,7 +106,7 @@ public function getTitle(QUI\Locale $Locale = null): string;
      * @param ?QUI\Locale $Locale (optional) - If omitted use QUI::getLocale()
      * @return string
      */
-    public function getDescription(QUI\Locale $Locale = null): string;
+    public function getDescription(null | QUI\Locale $Locale = null): string;
 
     /**
      * Set current Project the Registrar works for
diff --git a/src/QUI/FrontendUsers/Registrars/Email/Registrar.php b/src/QUI/FrontendUsers/Registrars/Email/Registrar.php
index 6e90350ac0a703825315127bb658018355410d8d..cb0f6a7c984c4a56de34dd93d234db9a387c1ead 100644
--- a/src/QUI/FrontendUsers/Registrars/Email/Registrar.php
+++ b/src/QUI/FrontendUsers/Registrars/Email/Registrar.php
@@ -37,7 +37,6 @@ public function onRegistered(QUI\Interfaces\Users\User $User): void
         $registrationSettings = $RegistrarHandler->getRegistrationSettings();
         $useAddress = boolval($registrationSettings['addressInput']);
 
-        /** @var QUI\Users\User $User */
         $firstname = $this->getAttribute('firstname');
         $lastname = $this->getAttribute('lastname');
 
@@ -382,7 +381,7 @@ public function getTitle(?QUI\Locale $Locale = null): string
      * @param QUI\Locale|null $Locale (optional) - If omitted use QUI::getLocale()
      * @return string
      */
-    public function getDescription(QUI\Locale $Locale = null): string
+    public function getDescription(null | QUI\Locale $Locale = null): string
     {
         if (is_null($Locale)) {
             $Locale = QUI::getLocale();
diff --git a/src/QUI/FrontendUsers/RegistrationUtils.php b/src/QUI/FrontendUsers/RegistrationUtils.php
index 3b79a742672c4061bed00bc691b863838b205849..31fac37e77b741b3466bf15288dc0a5d3df8856f 100644
--- a/src/QUI/FrontendUsers/RegistrationUtils.php
+++ b/src/QUI/FrontendUsers/RegistrationUtils.php
@@ -19,7 +19,7 @@ class RegistrationUtils
      * @param Project|null $Project $Project (optional) - QUIQQER Project [default: QUI::getRewrite()->getProject()]
      * @return string
      */
-    public static function getFurtherLinksText(Project $Project = null): string
+    public static function getFurtherLinksText(null | Project $Project = null): string
     {
         try {
             if (empty($Project)) {
diff --git a/src/QUI/FrontendUsers/Rest/Routes/GetRegisterRequiredFields.php b/src/QUI/FrontendUsers/Rest/Routes/GetRegisterRequiredFields.php
index 2ab20745d75822281b2f7e7f76eea4e5cfaf9bf0..a72d9bde0f8d64ea2cd4fe7d3f1187f2440956fd 100644
--- a/src/QUI/FrontendUsers/Rest/Routes/GetRegisterRequiredFields.php
+++ b/src/QUI/FrontendUsers/Rest/Routes/GetRegisterRequiredFields.php
@@ -22,6 +22,10 @@ class GetRegisterRequiredFields
      */
     public static function call(SlimRequest $Request, SlimResponse $Response, array $args): SlimResponse
     {
+        if (!class_exists('QUI\REST\ResponseFactory')) {
+            throw new QUI\Exception('Class "QUI\REST\ResponseFactory" not found.');
+        }
+
         $ResponseFactory = new QUI\REST\ResponseFactory();
 
         try {
diff --git a/src/QUI/FrontendUsers/Rest/Routes/PostRegister.php b/src/QUI/FrontendUsers/Rest/Routes/PostRegister.php
index b596fa49802ddf5841028bb7d24b0f6c42187bdf..18da1763bd19490cc6b067d6f6c3170c80a9ebe4 100644
--- a/src/QUI/FrontendUsers/Rest/Routes/PostRegister.php
+++ b/src/QUI/FrontendUsers/Rest/Routes/PostRegister.php
@@ -6,9 +6,9 @@
 use Psr\Http\Message\ResponseInterface as SlimResponse;
 use Psr\Http\Message\ServerRequestInterface as SlimRequest;
 use QUI;
-use QUI\FrontendUsers\ActivationVerification;
+use QUI\FrontendUsers\ActivationLinkVerification;
 use QUI\FrontendUsers\Exception;
-use QUI\Verification\Verifier;
+use QUI\Verification\VerificationFactory;
 
 use function boolval;
 use function explode;
@@ -212,19 +212,23 @@ protected static function addRegistrationDataToUser(
 
     /**
      * @throws QUI\Exception
-     * @throws QUI\Verification\Exception
+     * @throws QUI\Verification\Exception|\DateMalformedStringException
      */
     protected static function sendActivationMail(
         QUI\Interfaces\Users\User $User,
         QUI\Projects\Project $Project
     ): bool {
         // TODO: Verification uses Project from QUI::getRewrite instead of the parameter, therefore the default project is always used (see quiqqer/verification#5)
-        $ActivationVerification = new ActivationVerification($User->getUUID(), [
-            'project' => $Project->getName(),
-            'projectLang' => $Project->getLang()
-        ]);
-
-        $activationLink = Verifier::startVerification($ActivationVerification, true);
+        $verificationFactory = new VerificationFactory();
+        $verification = $verificationFactory->createLinkVerification(
+            'activate-' . $User->getUUID(),
+            new ActivationLinkVerification(),
+            [
+                'uuid' => $User->getUUID(),
+                'project' => $Project->getName(),
+                'projectLang' => $Project->getLang()
+            ]
+        );
 
         $L = QUI::getLocale();
         $lg = 'quiqqer/frontend-users';
@@ -253,7 +257,7 @@ protected static function sendActivationMail(
                         'userLastName' => $User->getAttribute('lastname') ?: '',
                         'email' => $User->getAttribute('email'),
                         'date' => $L->formatDate(time()),
-                        'activationLink' => $activationLink
+                        'activationLink' => $verification->getVerificationUrl()
                     ])
                 ]
             );
diff --git a/src/QUI/FrontendUsers/UserDeleteConfirmVerification.php b/src/QUI/FrontendUsers/UserDeleteConfirmLinkVerification.php
similarity index 59%
rename from src/QUI/FrontendUsers/UserDeleteConfirmVerification.php
rename to src/QUI/FrontendUsers/UserDeleteConfirmLinkVerification.php
index b2a6cd2e64aeaf37b98f5522ea309a38ed8aa9e6..74aaa17dd8ca925fef15f2a6ecc7c5dbd879593a 100644
--- a/src/QUI/FrontendUsers/UserDeleteConfirmVerification.php
+++ b/src/QUI/FrontendUsers/UserDeleteConfirmLinkVerification.php
@@ -5,7 +5,9 @@
 use QUI;
 use QUI\Exception;
 use QUI\ExceptionStack;
-use QUI\Verification\AbstractVerification;
+use QUI\Verification\Entity\AbstractVerification;
+use QUI\Verification\Entity\LinkVerification;
+use QUI\Verification\Enum\VerificationErrorReason;
 
 /**
  * Class UserDeleteConfirmVerification
@@ -14,16 +16,17 @@
  *
  * @package QUI\FrontendUsers
  */
-class UserDeleteConfirmVerification extends AbstractVerification
+class UserDeleteConfirmLinkVerification extends AbstractFrontendUsersLinkVerificationHandler
 {
     /**
      * Get the duration of a Verification (minutes)
      *
-     * @return int|false - duration in minutes;
+     * @param AbstractVerification $verification
+     * @return int|null - duration in minutes;
      * if this method returns false use the module setting default value
      * @throws Exception
      */
-    public function getValidDuration(): bool|int
+    public function getValidDuration(AbstractVerification $verification): ?int
     {
         $settings = Handler::getInstance()->getMailSettings();
         return (int)$settings['verificationValidityDuration'];
@@ -32,16 +35,17 @@ public function getValidDuration(): bool|int
     /**
      * Execute this method on successful verification
      *
+     * @param LinkVerification $verification
      * @return void
      * @throws \Exception
      */
-    public function onSuccess(): void
+    public function onSuccess(LinkVerification $verification): void
     {
-        $userId = $this->getIdentifier();
+        $userUuid = $verification->getCustomDataEntry('uuid');
         $userProfileSettings = Handler::getInstance()->getUserProfileSettings();
 
         try {
-            $User = QUI::getUsers()->get($userId);
+            $User = QUI::getUsers()->get($userUuid);
 
             switch ($userProfileSettings['userDeleteMode']) {
                 case 'delete':
@@ -68,7 +72,7 @@ public function onSuccess(): void
             QUI\System\Log::writeException($Exception);
 
             QUI\System\Log::addError(
-                self::class . ' :: onSuccess -> Could not find/delete user #' . $userId
+                self::class . ' :: onSuccess -> Could not find/delete user #' . $userUuid
             );
 
             QUI\System\Log::writeException($Exception);
@@ -80,18 +84,21 @@ public function onSuccess(): void
     /**
      * Execute this method on unsuccessful verification
      *
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
      * @return void
      */
-    public function onError(): void
+    public function onError(LinkVerification $verification, VerificationErrorReason $reason): void
     {
     }
 
     /**
      * This message is displayed to the user on successful verification
      *
+     * @param LinkVerification $verification
      * @return string
      */
-    public function getSuccessMessage(): string
+    public function getSuccessMessage(LinkVerification $verification): string
     {
         return QUI::getLocale()->get(
             'quiqqer/frontend-users',
@@ -102,10 +109,11 @@ public function getSuccessMessage(): string
     /**
      * This message is displayed to the user on unsuccessful verification
      *
-     * @param string $reason - The reason for the error (see \QUI\Verification\Verifier::REASON_)
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason - The reason for the error (see \QUI\Verification\Verifier::REASON_)
      * @return string
      */
-    public function getErrorMessage(string $reason): string
+    public function getErrorMessage(LinkVerification $verification, VerificationErrorReason $reason): string
     {
         return '';
     }
@@ -113,18 +121,23 @@ public function getErrorMessage(string $reason): string
     /**
      * Automatically redirect the user to this URL on successful verification
      *
-     * @return string|false - If this method returns false, no redirection takes place
+     * @param LinkVerification $verification
+     * @return string|null - If this method returns false, no redirection takes place
      * @throws Exception
      * @throws ExceptionStack
      */
-    public function getOnSuccessRedirectUrl(): bool|string
+    public function getOnSuccessRedirectUrl(LinkVerification $verification): ?string
     {
-        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite(
-            $this->getProject()
-        );
+        $project = $this->getProject($verification);
+
+        if (!$project) {
+            return null;
+        }
+
+        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite($project);
 
         if (!$RegistrationSite) {
-            return false;
+            return null;
         }
 
         return $RegistrationSite->getUrlRewritten([], [
@@ -135,37 +148,27 @@ public function getOnSuccessRedirectUrl(): bool|string
     /**
      * Automatically redirect the user to this URL on unsuccessful verification
      *
-     * @return string|false - If this method returns false, no redirection takes place
+     * @param LinkVerification $verification
+     * @param VerificationErrorReason $reason
+     * @return string|null - If this method returns false, no redirection takes place
      * @throws Exception
      */
-    public function getOnErrorRedirectUrl(): bool|string
+    public function getOnErrorRedirectUrl(LinkVerification $verification, VerificationErrorReason $reason): ?string
     {
-        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite(
-            $this->getProject()
-        );
+        $project = $this->getProject($verification);
+
+        if (!$project) {
+            return null;
+        }
+
+        $RegistrationSite = Handler::getInstance()->getRegistrationSignUpSite($project);
 
         if (!$RegistrationSite) {
-            return false;
+            return null;
         }
 
         return $RegistrationSite->getUrlRewritten([], [
             'error' => 'userdelete'
         ]);
     }
-
-    /**
-     * Get the Project this Verification is intended for
-     *
-     * @return QUI\Projects\Project
-     * @throws Exception
-     */
-    protected function getProject(): QUI\Projects\Project
-    {
-        $additionalData = $this->getAdditionalData();
-
-        return QUI::getProjectManager()->getProject(
-            $additionalData['project'],
-            $additionalData['projectLang']
-        );
-    }
 }
diff --git a/src/QUI/FrontendUsers/Utils.php b/src/QUI/FrontendUsers/Utils.php
index 32b051562bf9f49aa847dc9080dd237cff4dbd70..393756dd5c136f52e658611500706d2fd3d93ae9 100644
--- a/src/QUI/FrontendUsers/Utils.php
+++ b/src/QUI/FrontendUsers/Utils.php
@@ -1,17 +1,16 @@
 <?php
 
-/**
- * This file contains QUI\FrontendUsers\Utils
- */
-
 namespace QUI\FrontendUsers;
 
 use QUI;
 use QUI\FrontendUsers\Controls\Profile\ControlInterface;
 use QUI\Package\Package;
 use QUI\Permissions;
+use QUI\Interfaces\Users\User as QUIUserInterface;
+use QUI\FrontendUsers\Exception\EmailAddressNotVerifiableException;
 
 use function class_exists;
+use function in_array;
 use function is_a;
 use function json_decode;
 
@@ -32,7 +31,6 @@ public static function getFrontendUsersPackages(): array
         $packages = QUI::getPackageManager()->getInstalled();
         $list = [];
 
-        /* @var $Package <Package */
         foreach ($packages as $package) {
             try {
                 $Package = QUI::getPackage($package['name']);
@@ -73,7 +71,6 @@ public static function getProfileCategories(): array
         $packages = self::getFrontendUsersPackages();
         $Engine = QUI::getTemplateManager()->getEngine();
 
-        /** @var Package $Package */
         foreach ($packages as $Package) {
             $Parser = new QUI\Utils\XML\Settings();
             $Parser->setXMLPath('//quiqqer/frontend-users/profile');
@@ -137,7 +134,7 @@ public static function getProfileCategories(): array
      *
      * @throws Exception
      */
-    public static function getProfileSetting(string $category, bool|string $settings = false): array
+    public static function getProfileSetting(string $category, bool | string $settings = false): array
     {
         if ($category) {
             $categories = [self::getProfileCategory($category)];
@@ -168,8 +165,10 @@ public static function getProfileSetting(string $category, bool|string $settings
      *
      * @throws Exception
      */
-    public static function getProfileSettingControl(string $category, bool|string $settings = false): ?ControlInterface
-    {
+    public static function getProfileSettingControl(
+        string $category,
+        bool | string $settings = false
+    ): ?ControlInterface {
         $setting = self::getProfileSetting($category, $settings);
         $Control = null;
 
@@ -292,8 +291,8 @@ public static function getProfileBarCategorySettings(): array
      */
     public static function hasPermissionToViewCategory(
         string $category,
-        bool|string $setting = false,
-        QUI\Interfaces\Users\User $User = null
+        bool | string $setting = false,
+        null | QUI\Interfaces\Users\User $User = null
     ): bool {
         if ($User === null) {
             $User = QUI::getUserBySession();
@@ -347,8 +346,10 @@ public static function loadTranslationForCategories(array $categories = []): arr
      * @param null|QUI\Projects\Project $Project
      * @return array
      */
-    public static function setUrlsToCategorySettings(array $categories = [], QUI\Projects\Project $Project = null): array
-    {
+    public static function setUrlsToCategorySettings(
+        array $categories = [],
+        null | QUI\Projects\Project $Project = null
+    ): array {
         try {
             if ($Project === null) {
                 $Project = QUI::getRewrite()->getProject();
@@ -426,12 +427,24 @@ public static function getGravatarUrl(string $email, int $s = 80): string
     }
 
     /**
-     * Check if the standard e-mail address of a user is verified
+     * Check if the STANDARD e-mail address of a user is verified
      *
-     * @param QUI\Users\User $User
+     * @param QUIUserInterface $User
      * @return bool
+     * @deprecated use isDefaultUserEmailVerified
      */
-    public static function isUserEmailVerified(QUI\Users\User $User): bool
+    public static function isUserEmailVerified(QUIUserInterface $User): bool
+    {
+        return self::isDefaultUserEmailVerified($User);
+    }
+
+    /**
+     * Check if the STANDARD e-mail address of a user is verified
+     *
+     * @param QUIUserInterface $User
+     * @return bool
+     */
+    public static function isDefaultUserEmailVerified(QUIUserInterface $User): bool
     {
         $email = $User->getAttribute('email');
 
@@ -442,21 +455,124 @@ public static function isUserEmailVerified(QUI\Users\User $User): bool
         return $User->getAttribute(Handler::USER_ATTR_EMAIL_VERIFIED);
     }
 
+    /**
+     * Check if any e-mail address (user, user address) is verified for a specific user.
+     *
+     * @param string $email
+     * @param QUIUserInterface $User
+     * @return bool
+     */
+    public static function isEmailAddressVerifiedForUser(string $email, QUIUserInterface $User): bool
+    {
+        $verifiedEmailAddresses = $User->getAttribute(Handler::USER_ATTR_EMAIL_ADDRESSES_VERIFIED);
+
+        if (empty($verifiedEmailAddresses)) {
+            return false;
+        }
+
+        return in_array($email, $verifiedEmailAddresses);
+    }
+
+    /**
+     * Set a specific email address as verified for a user.
+     *
+     * @param string $email
+     * @param QUIUserInterface $User
+     * @return void
+     *
+     * @throws EmailAddressNotVerifiableException
+     */
+    public static function setEmailAddressAsVerfifiedForUser(string $email, QUIUserInterface $User): void
+    {
+        if (self::isEmailAddressVerifiedForUser($email, $User)) {
+            return;
+        }
+
+        if (empty($email)) {
+            throw new EmailAddressNotVerifiableException('Cannot verify empty email address.');
+        }
+
+        if (!QUI\Utils\Security\Orthos::checkMailSyntax($email)) {
+            throw new EmailAddressNotVerifiableException("Cannot verify invalid email address $email.");
+        }
+
+        if (!self::doesUserHaveEmailAddress($email, $User)) {
+            throw new EmailAddressNotVerifiableException(
+                "Cannot verify email address $email for user {$User->getId()}, because this email address"
+                . " is not associated with this user (neither saved in user or user addresses)."
+            );
+        }
+
+        $verifiedEmailAddresses = $User->getAttribute(Handler::USER_ATTR_EMAIL_ADDRESSES_VERIFIED);
+
+        if (empty($verifiedEmailAddresses)) {
+            $verifiedEmailAddresses = [];
+        }
+
+        $verifiedEmailAddresses[] = $email;
+
+        $User->setAttribute(Handler::USER_ATTR_EMAIL_ADDRESSES_VERIFIED, $verifiedEmailAddresses);
+        $User->save(QUI::getUsers()->getSystemUser());
+    }
+
+    /**
+     * Check if a user has a specific email address (either in user or one of user addresses).
+     *
+     * @param string $email
+     * @param QUIUserInterface $User
+     * @return bool
+     */
+    public static function doesUserHaveEmailAddress(string $email, QUIUserInterface $User): bool
+    {
+        $userEmail = $User->getAttribute('email');
+
+        if ($email === $userEmail) {
+            return true;
+        }
+
+        foreach ($User->getAddressList() as $Address) {
+            if (!($Address instanceof QUI\Users\Address)) {
+                continue;
+            }
+
+            $addressEmails = $Address->getMailList();
+
+            if (in_array($email, $addressEmails)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Set the standard e-mail address of a user to status "verified"
      *
-     * @param QUI\Users\User $User
+     * @param QUIUserInterface $User
      * @return void
+     * @throws EmailAddressNotVerifiableException
+     * @deprecated use setDefaultUserEmailVerified
+     */
+    public static function setUserEmailVerified(QUIUserInterface $User): void
+    {
+        self::setDefaultUserEmailVerified($User);
+    }
+
+    /**
+     * Set the standard e-mail address of a user to status "verified"
      *
-     * @throws QUI\Exception
+     * @param QUIUserInterface $User
+     * @return void
+     * @throws EmailAddressNotVerifiableException
      */
-    public static function setUserEmailVerified(QUI\Users\User $User): void
+    public static function setDefaultUserEmailVerified(QUIUserInterface $User): void
     {
+        self::setEmailAddressAsVerfifiedForUser($User->getAttribute('email'), $User);
+
         $User->setAttribute(Handler::USER_ATTR_EMAIL_VERIFIED, true);
         $User->save(QUI::getUsers()->getSystemUser());
     }
 
-
     public static function getMissingAddressFields(QUI\Users\Address $Address): array
     {
         $missing = [];
diff --git a/templates/mail.confirm_email_address.html b/templates/mail.confirm_email_address.html
new file mode 100644
index 0000000000000000000000000000000000000000..734c938f1726958422ec4329c01504b851ac9744
--- /dev/null
+++ b/templates/mail.confirm_email_address.html
@@ -0,0 +1 @@
+{$body}
\ No newline at end of file
diff --git a/tests/phpunit-bootstrap.php b/tests/phpunit-bootstrap.php
new file mode 100644
index 0000000000000000000000000000000000000000..eca92fd67bed8ae4ec424ed82d300119d792f042
--- /dev/null
+++ b/tests/phpunit-bootstrap.php
@@ -0,0 +1,11 @@
+<?php
+
+if (!defined('QUIQQER_SYSTEM')) {
+    define('QUIQQER_SYSTEM', true);
+}
+
+if (!defined('QUIQQER_AJAX')) {
+    define('QUIQQER_AJAX', true);
+}
+
+require_once __DIR__ . '/../../../../bootstrap.php';
diff --git a/types/profile.php b/types/profile.php
index f2056707e0ca5743622b592fe709f9941bb4fed8..4acafce8852fe4ddedc34eac96f15bc41db67160 100644
--- a/types/profile.php
+++ b/types/profile.php
@@ -12,7 +12,7 @@
 $SessionUser = QUI::getUserBySession();
 
 if (QUI::getUsers()->isNobodyUser($SessionUser)) {
-    $Control = new QUI\Users\Controls\Login();
+    $Control = new QUI\FrontendUsers\Controls\Login();
 } else {
     $_REQUEST['_url'] = ltrim($_REQUEST['_url'], '/'); // nginx fix
     $_REQUEST['_url'] = urldecode($_REQUEST['_url']);
diff --git a/user.xml b/user.xml
index 80e9f515bc6e8cf803972f1a7753a119c54a0f9f..b086a9eb99a5b29277c107b800d8b0934ba7bca4 100644
--- a/user.xml
+++ b/user.xml
@@ -7,7 +7,8 @@
         <attribute>quiqqer.frontendUsers.registrar</attribute>
         <attribute>quiqqer.frontendUsers.userActivationRequired</attribute>
         <attribute>quiqqer.frontendUsers.activationLoginExecuted</attribute>
-        <attribute>quiqqer.frontendUsers.emailVerified</attribute>
+        <attribute>quiqqer.frontendUsers.emailVerified</attribute> <!-- main email address -->
+        <attribute>quiqqer.frontendUsers.emailAddressesVerified</attribute> <!-- additional email addresses -->
         <attribute>quiqqer.frontendUsers.useGravatarIcon</attribute>
     </attributes>
 </user>
\ No newline at end of file