diff --git a/app/__init__.py b/app/__init__.py
index bf465cbbf5f0bd26ea55f1d10523eb3115b00ba9..50e70fd29fc32ef33160daf603e84c3214d4fb75 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -91,6 +91,10 @@ def create_app(config: Config = Config) -> Flask:
     default_breadcrumb_root(services_blueprint, '.services')
     app.register_blueprint(services_blueprint, url_prefix='/services')
 
+    from .settings import bp as settings_blueprint
+    default_breadcrumb_root(settings_blueprint, '.settings')
+    app.register_blueprint(settings_blueprint, url_prefix='/settings')
+
     from .users import bp as users_blueprint
     default_breadcrumb_root(users_blueprint, '.social_area.users')
     app.register_blueprint(users_blueprint, url_prefix='/users')
diff --git a/app/settings/__init__.py b/app/settings/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..aaa1cb1ba97f0c2f8b94da9a8340e32ba846fcbe
--- /dev/null
+++ b/app/settings/__init__.py
@@ -0,0 +1,6 @@
+from flask import Blueprint
+
+
+bp = Blueprint('settings', __name__)
+from . import routes, json_routes
+
diff --git a/app/users/forms.py b/app/settings/forms.py
similarity index 93%
rename from app/users/forms.py
rename to app/settings/forms.py
index 73d72c8dcee458a5172c7cd416cc01ceaf93e1a9..a814feee301bfc65f614335eab9176267d002e2b 100644
--- a/app/users/forms.py
+++ b/app/settings/forms.py
@@ -56,6 +56,9 @@ class EditProfileSettingsForm(FlaskForm):
             raise ValidationError('Username already in use')
 
 class EditPublicProfileInformationForm(FlaskForm):
+    show_email = BooleanField('Email')
+    show_last_seen = BooleanField('Last seen')
+    show_member_since = BooleanField('Member since')
     avatar = FileField(
         'Image File', 
         [FileSizeLimit(max_size_in_mb=2)]
@@ -97,13 +100,6 @@ class EditPublicProfileInformationForm(FlaskForm):
         if not field.data.filename.lower().endswith('.jpg' or '.png' or '.jpeg'):
             raise ValidationError('only .jpg, .png and .jpeg!')
 
-class EditPrivacySettingsForm(FlaskForm):
-    is_public = BooleanField('Public profile')
-    show_email = BooleanField('Show email')
-    show_last_seen = BooleanField('Show last seen')
-    show_member_since = BooleanField('Show member since')
-    submit = SubmitField()
-
 class ChangePasswordForm(FlaskForm):
     password = PasswordField('Old password', validators=[DataRequired()])
     new_password = PasswordField(
diff --git a/app/users/json_routes.py b/app/settings/json_routes.py
similarity index 71%
rename from app/users/json_routes.py
rename to app/settings/json_routes.py
index 0e421078fdfeaf3f21eb38187abbb5ea4bbd1115..77b421d9e0c9a5d4411e08e90ee986c5a66389e3 100644
--- a/app/users/json_routes.py
+++ b/app/settings/json_routes.py
@@ -1,4 +1,4 @@
-from flask import abort, current_app
+from flask import abort, current_app, request
 from flask_login import current_user, login_required, logout_user
 from threading import Thread
 import os
@@ -52,3 +52,22 @@ def delete_profile_avatar(user_id):
         'message': f'Avatar marked for deletion'
     }
     return response_data, 202
+
+@bp.route('/<hashid:user_id>/is_public', methods=['PUT'])
+@login_required
+@content_negotiation(consumes='application/json', produces='application/json')
+def update_user_is_public(user_id):
+    is_public = request.json
+    if not isinstance(is_public, bool):
+        abort(400)
+    user = User.query.get_or_404(user_id)
+    user.is_public = is_public
+    db.session.commit()
+    response_data = {
+        'message': (
+            f'User "{user.username}" is now'
+            f' {"public" if is_public else "private"}'
+        ),
+        'category': 'corpus'
+    }
+    return response_data, 200
diff --git a/app/settings/routes.py b/app/settings/routes.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc36a9c8fcf91c974bbcc66a7c2767555392c428
--- /dev/null
+++ b/app/settings/routes.py
@@ -0,0 +1,108 @@
+from flask import (
+    abort,
+    flash, 
+    redirect, 
+    render_template,
+    url_for
+)
+from flask_breadcrumbs import register_breadcrumb
+from flask_login import current_user, login_required
+import os
+from app import db
+from app.models import Avatar, Corpus, ProfilePrivacySettings, User
+from . import bp
+from .forms import (
+  ChangePasswordForm,
+  EditNotificationSettingsForm,
+  EditProfileSettingsForm,
+  EditPublicProfileInformationForm
+)
+from .utils import user_endpoint_arguments_constructor as user_eac
+
+
+@bp.route('/<hashid:user_id>/edit', methods=['GET', 'POST'])
+@register_breadcrumb(bp, 'breadcrumbs.settings', '<i class="material-icons left">settings</i>Settings', endpoint_arguments_constructor=user_eac)
+@login_required
+def edit_profile(user_id):
+    user = User.query.get_or_404(user_id)
+    if not (user == current_user or current_user.is_administrator()):
+        abort(403)
+    # region forms
+    edit_profile_settings_form = EditProfileSettingsForm(
+        current_user,
+        data=current_user.to_json_serializeable(),
+        prefix='edit-profile-settings-form'
+    )
+    edit_public_profile_information_form = EditPublicProfileInformationForm(
+        data=current_user.to_json_serializeable(),
+        prefix='edit-public-profile-information-form'
+    )
+    change_password_form = ChangePasswordForm(
+        current_user,
+        prefix='change-password-form'
+    )
+    edit_notification_settings_form = EditNotificationSettingsForm(
+        data=current_user.to_json_serializeable(),
+        prefix='edit-notification-settings-form'
+    )
+    # endregion forms
+    # region handle edit profile settings form
+    if edit_profile_settings_form.validate_on_submit():
+        current_user.email = edit_profile_settings_form.email.data
+        current_user.username = edit_profile_settings_form.username.data
+        db.session.commit()
+        flash('Profile settings updated')
+        return redirect(url_for('users.user', user_id=user.id))
+    # endregion handle edit profile settings forms
+    # region handle edit public profile information form
+    if edit_public_profile_information_form.submit.data and edit_public_profile_information_form.validate():
+        print(edit_public_profile_information_form.show_email.data)
+        if edit_public_profile_information_form.show_email.data:
+            current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL)
+        else:
+            current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL)
+        if edit_public_profile_information_form.show_last_seen.data:
+            current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN)
+        else:
+            current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN)
+        if edit_public_profile_information_form.show_member_since.data:
+            current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE)
+        else:
+            current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE)
+        if edit_public_profile_information_form.avatar.data:
+            try:
+                Avatar.create(edit_public_profile_information_form.avatar.data, user=current_user)
+            except (AttributeError, OSError):
+                abort(500)
+        current_user.about_me = edit_public_profile_information_form.about_me.data
+        current_user.location = edit_public_profile_information_form.location.data
+        current_user.organization = edit_public_profile_information_form.organization.data
+        current_user.website = edit_public_profile_information_form.website.data
+        current_user.full_name = edit_public_profile_information_form.full_name.data
+        db.session.commit()
+        flash('Profile settings updated')
+        return redirect(url_for('users.user', user_id=user.id))
+    # endregion handle edit public profile information form
+    # region handle change_password_form POST
+    if change_password_form.submit.data and change_password_form.validate():
+        current_user.password = change_password_form.new_password.data
+        db.session.commit()
+        flash('Your changes have been saved')
+        return redirect(url_for('.edit_profile', user_id=user.id))
+    # endregion handle change_password_form POST
+    # region handle edit_notification_settings_form POST
+    if edit_notification_settings_form.submit and edit_notification_settings_form.validate():
+        current_user.setting_job_status_mail_notification_level = edit_notification_settings_form.job_status_mail_notification_level.data
+        db.session.commit()
+        flash('Your changes have been saved')
+        return redirect(url_for('.edit_profile', user_id=user.id))
+    # endregion handle edit_notification_settings_form POST
+    return render_template(
+        'settings/edit_profile.html.j2',
+        edit_profile_settings_form=edit_profile_settings_form,
+        edit_public_profile_information_form=edit_public_profile_information_form,
+        change_password_form=change_password_form,
+        edit_notification_settings_form=edit_notification_settings_form,
+        user=user,
+        title='Settings'
+    )
diff --git a/app/settings/utils.py b/app/settings/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..53572740ddd417ad228b9d8def0604c77e94a769
--- /dev/null
+++ b/app/settings/utils.py
@@ -0,0 +1,6 @@
+from flask import request, url_for
+from app.models import User
+
+
+def user_endpoint_arguments_constructor():
+    return {'user_id': request.view_args['user_id']}
diff --git a/app/static/js/Requests/settings/settings.js b/app/static/js/Requests/settings/settings.js
new file mode 100644
index 0000000000000000000000000000000000000000..55ae94b27ed9f6bbb9466a77deb588dc976878fb
--- /dev/null
+++ b/app/static/js/Requests/settings/settings.js
@@ -0,0 +1,35 @@
+/*****************************************************************************
+* Users                                                              *
+* Fetch requests for /users routes                                   *
+*****************************************************************************/
+Requests.settings = {};
+
+Requests.settings.entity = {};
+
+Requests.settings.entity.delete = (userId) => {
+  let input = `/settings/${userId}`;
+  let init = {
+    method: 'DELETE'
+  };
+  return Requests.JSONfetch(input, init);
+}
+
+Requests.settings.entity.deleteAvatar = (userId) => {
+  let input = `/settings/${userId}/avatar`;
+  let init = {
+    method: 'DELETE'
+  };
+  return Requests.JSONfetch(input, init);
+}
+
+Requests.settings.entity.isPublic = {};
+
+Requests.settings.entity.isPublic.update = (userId, isPublic) => {
+  let input = `/settings/${userId}/is_public`;
+  let init = {
+    method: 'PUT',
+    body: JSON.stringify(isPublic)
+  };
+  return Requests.JSONfetch(input, init);
+};
+
diff --git a/app/static/js/Requests/users/users.js b/app/static/js/Requests/users/users.js
deleted file mode 100644
index 0ae1434e68893546eea6b4c5ae3957b70258f19f..0000000000000000000000000000000000000000
--- a/app/static/js/Requests/users/users.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/*****************************************************************************
-* Users                                                              *
-* Fetch requests for /users routes                                   *
-*****************************************************************************/
-Requests.users = {};
-
-Requests.users.entity = {};
-
-Requests.users.entity.delete = (userId) => {
-  let input = `/users/${userId}`;
-  let init = {
-    method: 'DELETE'
-  };
-  return Requests.JSONfetch(input, init);
-}
-
-Requests.users.entity.deleteAvatar = (userId) => {
-  let input = `/users/${userId}/avatar`;
-  let init = {
-    method: 'DELETE'
-  };
-  return Requests.JSONfetch(input, init);
-}
diff --git a/app/templates/_navbar.html.j2 b/app/templates/_navbar.html.j2
index 467db7dd878d9f3922159ce2d869b6f46579100d..8819d076eb493a1e09425dc2317c71eed0cfe746 100644
--- a/app/templates/_navbar.html.j2
+++ b/app/templates/_navbar.html.j2
@@ -32,7 +32,7 @@
 <ul class="dropdown-content" id="nav-more-dropdown">
   {# <li><a href="{{ url_for('main.user_manual') }}"><i class="material-icons left">help</i>Manual</a></li> #}
   {% if current_user.is_authenticated %}
-  <li><a href="{{ url_for('users.edit_profile', user_id=current_user.id) }}"><i class="material-icons left">settings</i>User settings</a></li>
+  <li><a href="{{ url_for('settings.edit_profile', user_id=current_user.id) }}"><i class="material-icons left">settings</i>User settings</a></li>
   <li class="divider" tabindex="-1"></li>
   <li><a href="{{ url_for('auth.logout') }}">Log out</a></li>
   {% else %}
diff --git a/app/templates/_scripts.html.j2 b/app/templates/_scripts.html.j2
index 11398cb9b0358b81d974272451e784dbfc6689fa..bed2aef2ce9a4c91e1ec8ca55d83453bbc5fe142 100644
--- a/app/templates/_scripts.html.j2
+++ b/app/templates/_scripts.html.j2
@@ -65,7 +65,7 @@
   'js/Requests/corpora/files.js',
   'js/Requests/corpora/followers.js',
   'js/Requests/jobs/jobs.js',
-  'js/Requests/users/users.js'
+  'js/Requests/settings/settings.js'
 %}
 <script src="{{ ASSET_URL }}"></script>
 {%- endassets %}
diff --git a/app/templates/_sidenav.html.j2 b/app/templates/_sidenav.html.j2
index 2d66dc2390f4faa6cf17edaa212642057d8ed6d8..f48ae4be4bc0e8dd80ccb51b512fe2c8a530da10 100644
--- a/app/templates/_sidenav.html.j2
+++ b/app/templates/_sidenav.html.j2
@@ -46,7 +46,7 @@
   <li><a href="{{ url_for('main.social_area', _anchor='public-corproa') }}"><i class="nopaque-icons">I</i>Public Corpora</a></li>
   <li><div class="divider"></div></li>
   <li><a class="subheader">Account</a></li>
-  <li><a href="{{ url_for('users.edit_profile', user_id=current_user.id) }}"><i class="material-icons left">settings</i>User Settings</a></li>
+  <li><a href="{{ url_for('settings.edit_profile', user_id=current_user.id) }}"><i class="material-icons left">settings</i>User Settings</a></li>
   <li><a href="{{ url_for('auth.logout') }}">Log out</a></li>
   {% if current_user.can('ADMINISTRATE') or current_user.can('USE_API') %}
   <li><div class="divider"></div></li>
diff --git a/app/templates/users/edit_profile.html.j2 b/app/templates/settings/edit_profile.html.j2
similarity index 79%
rename from app/templates/users/edit_profile.html.j2
rename to app/templates/settings/edit_profile.html.j2
index 1da2f37777cf3cba5dbc788b20ddd8aa6473abe8..afdc652de848ebc8d3e1856999f1f3c4e7ce725a 100644
--- a/app/templates/users/edit_profile.html.j2
+++ b/app/templates/settings/edit_profile.html.j2
@@ -16,7 +16,8 @@
       sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. 
       Stet clita kasd gubergren, no sea tak</p>
     </div>
-    <div class="col s8" style="margin-top: 22.8px;">
+    <div class="col s8">
+      <br>
       <ul class="collapsible">
         <li>
           <div class="collapsible-header" style="justify-content: space-between;">
@@ -38,7 +39,7 @@
             </form>
           </div>
         </li>
-        <li>
+        {# <li>
           <div class="collapsible-header" style="justify-content: space-between;"><span>Privacy Settings</span><i class="material-icons caret right">keyboard_arrow_right</i></div>
           <div class="collapsible-body">
             <form method="POST">
@@ -59,21 +60,48 @@
               </div>
             </form>
           </div>
-        </li>
+        </li> #}
         <li>
           <div class="collapsible-header" style="justify-content: space-between;"><span>Public Profile</span><i class="material-icons caret right">keyboard_arrow_right</i></div>
           <div class="collapsible-body">
             <form method="POST" enctype="multipart/form-data">
               {{ edit_public_profile_information_form.hidden_tag() }}
+              <div class="switch">
+                <label>
+                  private
+                  <input {% if user.is_public %}checked{% endif %} id="profile-is-public-switch" type="checkbox">
+                  <span class="lever"></span>
+                  public
+                </label>
+              </div>
+              <p></p>
+              <br>
+              <div class="divider"></div>
+              <p>Show:</p>
               <div class="row">
-                <div class="col s12 m2">
-                  <img src="{{ url_for('.profile_avatar', user_id=user.id) }}" alt="user-image" class="circle responsive-img" id="avatar">
+                <div class="col s3">
+                  <p>
+                    <label>
+                      {{ edit_public_profile_information_form.show_email() }}
+                      <span>{{ edit_public_profile_information_form.show_email.label.text }}</span>
+                    </label>
+                  </p>
                 </div>
-                <div class="col s12 m6">
-                  {{ wtf.render_field(edit_public_profile_information_form.avatar, accept='image/jpeg, image/png, image/gif', placeholder='Choose an image file', id='avatar-upload') }}
-                </div>                    
-                <div class="col s12 m1">
-                  <a class="btn-floating red waves-effect waves-light modal-trigger" style="margin-top:15px;" href="#delete-avatar-modal"><i class="material-icons">delete</i></a>
+                <div class="col s3">
+                  <p>
+                    <label>
+                      {{ edit_public_profile_information_form.show_last_seen() }}
+                      <span>{{ edit_public_profile_information_form.show_last_seen.label.text }}</span>
+                    </label>
+                  </p>
+                </div>
+                <div class="col s4">
+                  <p>
+                    <label>
+                      {{ edit_public_profile_information_form.show_member_since() }}
+                      <span>{{ edit_public_profile_information_form.show_member_since.label.text }}</span>
+                    </label>
+                  </p>
                 </div>
               </div>
               <p></p>
@@ -83,9 +111,23 @@
               {{ wtf.render_field(edit_public_profile_information_form.website, material_icon='laptop') }}
               {{ wtf.render_field(edit_public_profile_information_form.organization, material_icon='business') }}
               {{ wtf.render_field(edit_public_profile_information_form.location, material_icon='location_on') }}
+              <p></p>
+              <div class="row">
+                <div class="col s12 m2">
+                  <img src="{{ url_for('users.profile_avatar', user_id=user.id) }}" alt="user-image" class="circle responsive-img" id="avatar">
+                </div>
+                <div class="col s12 m6">
+                  {{ wtf.render_field(edit_public_profile_information_form.avatar, accept='image/jpeg, image/png, image/gif', placeholder='Choose an image file', id='avatar-upload') }}
+                </div>
+                <div class="col s12 m1">
+                  <a class="btn-floating red waves-effect waves-light modal-trigger" style="margin-top:15px;" href="#delete-avatar-modal"><i class="material-icons">delete</i></a>
+                </div>
+              </div>
+              <br>
+              <p></p>
               <div class="right-align">
                 {{ wtf.render_field(edit_public_profile_information_form.submit, material_icon='send') }}
-              </div>
+              </div>              
             </form>
           </div>
         </li>
@@ -100,7 +142,8 @@
       sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. 
       Stet clita kasd gubergren, no sea tak</p>
     </div>
-    <div class="col s8" style="margin-top: 22.8px;">
+    <div class="col s8">
+      <br>
       <ul class="collapsible">
         <li>
           <div class="collapsible-header" style="justify-content: space-between;">
@@ -182,36 +225,17 @@
 {% block scripts %}
 {{ super() }}
 <script>
-let publicProfile = document.querySelector('#public-profile');
-let disableButtons = document.querySelectorAll('[data-action="disable"]');
 let deleteButton = document.querySelector('#delete-avatar');
 let avatar = document.querySelector('#avatar');
 let avatarUpload = document.querySelector('#avatar-upload');
 
-for (let disableButton of disableButtons) {
-  disableButton.disabled = !publicProfile.checked;
-}
-
-publicProfile.addEventListener('change', () => {
-  if (publicProfile.checked) {
-    for (let disableButton of disableButtons) {
-      disableButton.disabled = false;
-    }
-  } else {
-    for (let disableButton of disableButtons) {
-      disableButton.checked = false;
-      disableButton.disabled = true;
-    }
-  }
-});
-
 avatarUpload.addEventListener('change', function() {
   let file = this.files[0];
   avatar.src = URL.createObjectURL(file);
 });
 
 deleteButton.addEventListener('click', () => {
-  Requests.users.entity.deleteAvatar(currentUserId)
+  Requests.settings.entity.deleteAvatar(currentUserId)
     .then(
       (response) => {
         avatar.src = "{{ url_for('static', filename='images/user_avatar.png') }}";
@@ -220,7 +244,7 @@ deleteButton.addEventListener('click', () => {
 });
 
 document.querySelector('#delete-user-button').addEventListener('click', (event) => {
-  Requests.users.entity.delete(currentUserId)
+  Requests.settings.entity.delete(currentUserId)
     .then((response) => {window.location.href = '/';});
 });
 
@@ -239,5 +263,16 @@ document.querySelectorAll('.collapsible').forEach((collapsible) => {
     });
 });
 
+// #region Public Switch
+let profileIsPublicSwitchElement = document.querySelector('#profile-is-public-switch');
+profileIsPublicSwitchElement.addEventListener('change', (event) => {
+  let newIsPublic = profileIsPublicSwitchElement.checked;
+  Requests.settings.entity.isPublic.update(currentUserId, newIsPublic)
+    .catch((response) => {
+      profileIsPublicSwitchElement.checked = !newIsPublic;
+    });
+});
+// #endregion Public Switch
+
 </script>
 {% endblock scripts %}
diff --git a/app/templates/users/edit_profile_testing.html.j2 b/app/templates/users/edit_profile_testing.html.j2
deleted file mode 100644
index 88eb8fb5a1e3cec735f92183627ee11e16ad31ca..0000000000000000000000000000000000000000
--- a/app/templates/users/edit_profile_testing.html.j2
+++ /dev/null
@@ -1,236 +0,0 @@
-{% extends "base.html.j2" %}
-{% import "materialize/wtf.html.j2" as wtf %}
-
-{% block page_content %}
-<div class="container">
-  <div class="row">
-    <div class="col s12">
-      <h1 id="title">{{ title }}</h1>
-    </div>
-  </div>
-  <div class="row"> 
-    <div class="col s12 m9 l10">
-      
-      <div id="user-settings" class="card section scrollspy">
-        <form method="POST" enctype="multipart/form-data">
-          <div class="card-content">
-            <span class="card-title">User Settings</span>
-            <div class="row">
-              <div class="col s6">
-                {{ edit_profile_settings_form.hidden_tag() }}
-                {{ wtf.render_field(edit_profile_settings_form.username, material_icon='person') }}
-                {{ wtf.render_field(edit_profile_settings_form.email, material_icon='email') }}
-              </div>
-            </div>
-          </div>
-          <div class="card-action">
-            <div class="right-align">
-              {{ wtf.render_field(edit_profile_settings_form.submit, material_icon='send') }}
-            </div>
-          </div>
-        </form>
-      </div>
-
-      <form method="POST">
-        {{ edit_privacy_settings_form.hidden_tag() }}
-        <div id="privacy-settings" class="card section scrollspy">
-          <div class="card-content">
-            <span class="card-title">Privacy settings</span>
-            <br>
-            {{ wtf.render_field(edit_privacy_settings_form.is_public, id='public-profile') }}
-            <br>
-            <hr>
-            <br>
-            {{ wtf.render_field(edit_privacy_settings_form.show_email, data_action='disable', disabled=true) }}
-            <br>
-            {{ wtf.render_field(edit_privacy_settings_form.show_last_seen, data_action='disable', disabled=true) }}
-            <br>
-            {{ wtf.render_field(edit_privacy_settings_form.show_member_since, data_action='disable', disabled=true) }}
-            <br>
-          </div>
-          <div class="card-action">
-            <div class="right-align">
-              {{ wtf.render_field(edit_privacy_settings_form.submit, material_icon='send') }}
-            </div>
-          </div>
-        </div>
-      </form>
-
-      <div id="public-profile-settings" class="card section scrollspy">
-        <form method="POST" enctype="multipart/form-data">
-          <div class="card-content">
-            {{ edit_public_profile_information_form.hidden_tag() }}
-            <div class="row">
-              <div class="col s12">
-                <span class="card-title">Public Profile</span>
-              </div>
-            </div>
-            <div class="row">
-              <div class="col s5">
-                <div class="row">
-                  <div class="col s2"></div>
-                  <div class="col s8">
-                    <img src="{{ url_for('.profile_avatar', user_id=user.id) }}" alt="user-image" class="circle responsive-img" id="avatar">
-                  </div>
-                  <div class="col s2"></div>
-                </div>
-                <div class="row">
-                  <div class="col s2">
-                    <div class="center-align">
-                      <a class="btn-floating red waves-effect waves-light modal-trigger" style="margin-top:15px;" href="#delete-avatar-modal"><i class="material-icons">delete</i></a>
-                    </div>
-                  </div>
-                  <div class="col s10">
-                    {{ wtf.render_field(edit_public_profile_information_form.avatar, accept='image/jpeg, image/png, image/gif', placeholder='Choose an image file', id='avatar-upload') }}
-                  </div>
-                </div>
-              </div>
-              <div class="col s7">
-                <p></p>
-                <br>
-                {{ wtf.render_field(edit_public_profile_information_form.full_name, material_icon='badge') }}
-                {{ wtf.render_field(edit_public_profile_information_form.about_me, material_icon='description') }}
-                {{ wtf.render_field(edit_public_profile_information_form.website, material_icon='laptop') }}
-                {{ wtf.render_field(edit_public_profile_information_form.organization, material_icon='business') }}
-                {{ wtf.render_field(edit_public_profile_information_form.location, material_icon='location_on') }}
-              </div>
-            </div>
-          </div>
-          <div class="card-action">
-            <div class="right-align">
-              {{ wtf.render_field(edit_public_profile_information_form.submit, material_icon='send') }}
-            </div>
-          </div>
-        </form>
-      </div>
-
-      <form method="POST">
-        {{ edit_notification_settings_form.hidden_tag() }}
-        <div id="notification-settings" class="card section scrollspy">
-          <div class="card-content">
-            <span class="card-title">Notification settings</span>
-            {{ wtf.render_field(edit_notification_settings_form.job_status_mail_notification_level, material_icon='notifications') }}
-          </div>
-          <div class="card-action">
-            <div class="right-align">
-              {{ wtf.render_field(edit_notification_settings_form.submit, material_icon='send') }}
-            </div>
-          </div>
-        </div>
-      </form>
-
-      <form method="POST">
-        {{ change_password_form.hidden_tag() }}
-        <div id="change-password" class="card section scrollspy">
-          <div class="card-content">
-            <span class="card-title">Change Password</span>
-            {{ wtf.render_field(change_password_form.password, material_icon='vpn_key') }}
-            {{ wtf.render_field(change_password_form.new_password, material_icon='vpn_key') }}
-            {{ wtf.render_field(change_password_form.new_password_2, material_icon='vpn_key') }}
-          </div>
-          <div class="card-action">
-            <div class="right-align">
-              {{ wtf.render_field(change_password_form.submit, material_icon='send') }}
-            </div>
-          </div>
-        </div>
-      </form>
-
-      <div id="delete-account" class="card section scrollspy">
-        <div class="card-content">
-          <span class="card-title">Delete account</span>
-          <p>Deleting an account has the following effects:</p>
-          <ul>
-            <li>All data associated with your corpora and jobs will be permanently deleted.</li>
-            <li>All settings will be permanently deleted.</li>
-          </ul>
-        </div>
-        <div class="card-action right-align">
-          <a class="btn red waves-effect waves-light modal-trigger" href="#delete-user"><i class="material-icons left">delete</i>Delete</a>
-        </div>
-      </div>
-
-    </div>
-    <div class="col hide-on-small-only m3 l2">
-      <ul class="section table-of-contents" style="position: fixed !important;">
-        <li><a href="#user-settings">User Settings</a></li>
-        <li><a href="#privacy-settings">Privacy Settings</a></li>
-        <li><a href="#public-profile-settings">Public Profile Settings</a></li>
-        <li><a href="#notification-settings">Notification Settings</a></li>
-        <li><a href="#change-password">Change Password</a></li>
-        <li><a href="#delete-account">Delete Account</a></li>
-      </ul>
-    </div>
-  </div>
-</div>
-{% endblock page_content %}
-
-{% block modals %}
-<div class="modal" id="delete-avatar-modal">
-  <div class="modal-content">
-    <h4>Confirm Avatar deletion</h4>
-    <p>Do you really want to delete your Avatar?</p>
-  </div>
-  <div class="modal-footer">
-    <a class="btn modal-close waves-effect waves-light">Cancel</a>
-    <a class="btn modal-close red waves-effect waves-light" id="delete-avatar">Delete</a>
-  </div>
-</div>
-<div class="modal" id="delete-user">
-  <div class="modal-content">
-    <h4>Confirm User deletion</h4>
-    <p>Do you really want to delete the User <b>{{ current_user.username }}</b>? All files will be permanently deleted!</p>
-  </div>
-  <div class="modal-footer">
-    <a class="btn modal-close waves-effect waves-light">Cancel</a>
-    <a class="btn modal-close red waves-effect waves-light" id="delete-user-button">Delete</a>
-  </div>
-</div>
-{% endblock modals %}
-
-{% block scripts %}
-{{ super() }}
-<script>
-let publicProfile = document.querySelector('#public-profile');
-let disableButtons = document.querySelectorAll('[data-action="disable"]');
-let deleteButton = document.querySelector('#delete-avatar');
-let avatar = document.querySelector('#avatar');
-let avatarUpload = document.querySelector('#avatar-upload');
-
-for (let disableButton of disableButtons) {
-  disableButton.disabled = !publicProfile.checked;
-}
-
-publicProfile.addEventListener('change', () => {
-  if (publicProfile.checked) {
-    for (let disableButton of disableButtons) {
-      disableButton.disabled = false;
-    }
-  } else {
-    for (let disableButton of disableButtons) {
-      disableButton.checked = false;
-      disableButton.disabled = true;
-    }
-  }
-});
-
-avatarUpload.addEventListener('change', function() {
-  let file = this.files[0];
-  avatar.src = URL.createObjectURL(file);
-});
-
-deleteButton.addEventListener('click', () => {
-  Requests.users.entity.deleteAvatar(currentUserId)
-    .then(
-      (response) => {
-        avatar.src = "{{ url_for('static', filename='images/user_avatar.png') }}";
-      }
-    );
-});
-
-document.querySelector('#delete-user-button').addEventListener('click', (event) => {
-  Requests.users.entity.delete(currentUserId)
-    .then((response) => {window.location.href = '/';});
-});
-</script>
-{% endblock scripts %}
diff --git a/app/templates/users/profile.html.j2 b/app/templates/users/profile.html.j2
index 31c12359cc476569ab3cdef04baa4550841c0534..895fba82e975e1004ae59ae430d6730d79856f56 100644
--- a/app/templates/users/profile.html.j2
+++ b/app/templates/users/profile.html.j2
@@ -81,7 +81,7 @@
                 <p></p>
                 <br>
                 {% if current_user.is_authenticated and current_user.hashid == user.id %}
-                <a class="waves-effect waves-light btn-small" href="{{ url_for('.edit_profile', user_id=current_user.id) }}">Edit profile</a>
+                <a class="waves-effect waves-light btn-small" href="{{ url_for('settings.edit_profile', user_id=current_user.id) }}">Edit profile</a>
                 {% endif %}
               </div>
             </div>
diff --git a/app/users/routes.py b/app/users/routes.py
index 52e25f1842c47672db35f6d2810aa1608110d129..876df2915a2f8cb0b6562c1bd5e16a5ba0f0b1dd 100644
--- a/app/users/routes.py
+++ b/app/users/routes.py
@@ -1,6 +1,5 @@
 from flask import (
     abort,
-    flash, 
     redirect, 
     render_template, 
     send_from_directory,
@@ -10,19 +9,9 @@ from flask_breadcrumbs import register_breadcrumb
 from flask_login import current_user, login_required
 import os
 from app import db
-from app.models import Avatar, Corpus, ProfilePrivacySettings, User
+from app.models import Corpus, User
 from . import bp
-from .forms import (
-  ChangePasswordForm,
-  EditNotificationSettingsForm,  
-  EditPrivacySettingsForm,
-  EditProfileSettingsForm,
-  EditPublicProfileInformationForm
-)
-from .utils import (
-    user_endpoint_arguments_constructor as user_eac,
-    user_dynamic_list_constructor as user_dlc
-)
+from .utils import user_dynamic_list_constructor as user_dlc
 
 
 @bp.route('')
@@ -75,102 +64,3 @@ def profile_avatar(user_id):
         attachment_filename=user.avatar.filename,
         mimetype=user.avatar.mimetype
     )
-
-
-@bp.route('/<hashid:user_id>/edit', methods=['GET', 'POST'])
-@register_breadcrumb(bp, 'breadcrumbs.settings', '<i class="material-icons left">settings</i>Settings', endpoint_arguments_constructor=user_eac)
-@login_required
-def edit_profile(user_id):
-    user = User.query.get_or_404(user_id)
-    if not (user == current_user or current_user.is_administrator()):
-        abort(403)
-    # region forms
-    edit_profile_settings_form = EditProfileSettingsForm(
-        current_user,
-        data=current_user.to_json_serializeable(),
-        prefix='edit-profile-settings-form'
-    )
-    edit_privacy_settings_form = EditPrivacySettingsForm(
-        data=current_user.to_json_serializeable(),
-        prefix='edit-privacy-settings-form'
-    )
-    edit_public_profile_information_form = EditPublicProfileInformationForm(
-        data=current_user.to_json_serializeable(),
-        prefix='edit-public-profile-information-form'
-    )
-    change_password_form = ChangePasswordForm(
-        current_user,
-        prefix='change-password-form'
-    )
-    edit_notification_settings_form = EditNotificationSettingsForm(
-        data=current_user.to_json_serializeable(),
-        prefix='edit-notification-settings-form'
-    )
-    # endregion forms
-    # region handle edit profile settings form
-    if edit_profile_settings_form.validate_on_submit():
-        current_user.email = edit_profile_settings_form.email.data
-        current_user.username = edit_profile_settings_form.username.data
-        db.session.commit()
-        flash('Profile settings updated')
-        return redirect(url_for('.user', user_id=user.id))
-    # endregion handle edit profile settings form
-    # region handle edit privacy settings form
-    if edit_privacy_settings_form.submit.data and edit_privacy_settings_form.validate():
-        current_user.is_public = edit_privacy_settings_form.is_public.data
-        if edit_privacy_settings_form.show_email.data:
-            current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL)
-        else:
-            current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL)
-        if edit_privacy_settings_form.show_last_seen.data:
-            current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN)
-        else:
-            current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN)
-        if edit_privacy_settings_form.show_member_since.data:
-            current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE)
-        else:
-            current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE)
-        db.session.commit()
-        flash('Your changes have been saved')
-        return redirect(url_for('.user', user_id=user.id))
-    # endregion handle edit privacy settings form
-    # region handle edit public profile information form
-    if edit_public_profile_information_form.submit.data and edit_public_profile_information_form.validate():
-        if edit_public_profile_information_form.avatar.data:
-            try:
-                Avatar.create(edit_public_profile_information_form.avatar.data, user=current_user)
-            except (AttributeError, OSError):
-                abort(500)
-        current_user.about_me = edit_public_profile_information_form.about_me.data
-        current_user.location = edit_public_profile_information_form.location.data
-        current_user.organization = edit_public_profile_information_form.organization.data
-        current_user.website = edit_public_profile_information_form.website.data
-        current_user.full_name = edit_public_profile_information_form.full_name.data
-        db.session.commit()
-        flash('Profile settings updated')
-        return redirect(url_for('.user', user_id=user.id))
-    # endregion handle edit public profile information form
-    # region handle change_password_form POST
-    if change_password_form.submit.data and change_password_form.validate():
-        current_user.password = change_password_form.new_password.data
-        db.session.commit()
-        flash('Your changes have been saved')
-        return redirect(url_for('.edit_profile', user_id=user.id))
-    # endregion handle change_password_form POST
-    # region handle edit_notification_settings_form POST
-    if edit_notification_settings_form.submit and edit_notification_settings_form.validate():
-        current_user.setting_job_status_mail_notification_level = edit_notification_settings_form.job_status_mail_notification_level.data
-        db.session.commit()
-        flash('Your changes have been saved')
-        return redirect(url_for('.edit_profile', user_id=user.id))
-    # endregion handle edit_notification_settings_form POST
-    return render_template(
-        'users/edit_profile.html.j2',
-        edit_profile_settings_form=edit_profile_settings_form,
-        edit_privacy_settings_form=edit_privacy_settings_form,
-        edit_public_profile_information_form=edit_public_profile_information_form,
-        change_password_form=change_password_form,
-        edit_notification_settings_form=edit_notification_settings_form,
-        user=user,
-        title='Settings'
-    )