diff --git a/app/assets/javascripts/discourse/app/components/user-nav/preferences-nav.hbs b/app/assets/javascripts/discourse/app/components/user-nav/preferences-nav.hbs
index 29e1c35c5d1..45a007b6c3f 100644
--- a/app/assets/javascripts/discourse/app/components/user-nav/preferences-nav.hbs
+++ b/app/assets/javascripts/discourse/app/components/user-nav/preferences-nav.hbs
@@ -4,58 +4,58 @@
     <span>{{i18n "user.preferences_nav.account"}}</span>
   </LinkTo>
 </li>
+
 <li class="nav-security">
   <LinkTo @route="preferences.security">
     {{d-icon "lock"}}
     <span>{{i18n "user.preferences_nav.security"}}</span>
   </LinkTo>
 </li>
+
 <li class="nav-profile">
   <LinkTo @route="preferences.profile">
     {{d-icon "user"}}
     <span>{{i18n "user.preferences_nav.profile"}}</span>
   </LinkTo>
 </li>
+
 <li class="nav-emails">
   <LinkTo @route="preferences.emails">
     {{d-icon "envelope"}}
     <span>{{i18n "user.preferences_nav.emails"}}</span>
   </LinkTo>
 </li>
+
 <li class="nav-notifications">
   <LinkTo @route="preferences.notifications">
     {{d-icon "bell"}}
     <span>{{i18n "user.preferences_nav.notifications"}}</span>
   </LinkTo>
 </li>
+
 {{#if @model.can_change_tracking_preferences}}
-  <li class="indent nav-categories">
-    <LinkTo @route="preferences.categories">
-      {{d-icon "folder"}}
-      <span>{{i18n "user.preferences_nav.categories"}}</span>
+  <li class="nav-tracking">
+    <LinkTo @route="preferences.tracking">
+      {{d-icon "plus"}}
+      <span>{{i18n "user.preferences_nav.tracking"}}</span>
     </LinkTo>
   </li>
 {{/if}}
+
 <li class="indent nav-users">
   <LinkTo @route="preferences.users">
     {{d-icon "users"}}
     <span>{{i18n "user.preferences_nav.users"}}</span>
   </LinkTo>
 </li>
-{{#if (and @model.can_change_tracking_preferences @siteSettings.tagging_enabled)}}
-  <li class="indent nav-tags">
-    <LinkTo @route="preferences.tags">
-      {{d-icon "tag"}}
-      <span>{{i18n "user.preferences_nav.tags"}}</span>
-    </LinkTo>
-  </li>
-{{/if}}
+
 <li class="nav-interface">
   <LinkTo @route="preferences.interface">
     {{d-icon "desktop"}}
     <span>{{i18n "user.preferences_nav.interface"}}</span>
   </LinkTo>
 </li>
+
 {{#if @siteSettings.enable_experimental_sidebar_hamburger}}
   <li class="indent nav-sidebar">
     <LinkTo @route="preferences.sidebar">
@@ -64,11 +64,6 @@
     </LinkTo>
   </li>
 {{/if}}
+
 <PluginOutlet @name="user-preferences-nav-under-interface" @connectorTagName="div" @args={{hash model=@model}} />
-<li class="nav-apps">
-  <LinkTo @route="preferences.apps">
-    {{d-icon "mobile-alt"}}
-    <span>{{i18n "user.preferences_nav.apps"}}</span>
-  </LinkTo>
-</li>
 <PluginOutlet @name="user-preferences-nav" @connectorTagName="li" @args={{hash model=@model}} />
diff --git a/app/assets/javascripts/discourse/app/components/user-preferences/allow-private-messages.hbs b/app/assets/javascripts/discourse/app/components/user-preferences/allow-private-messages.hbs
new file mode 100644
index 00000000000..82afce8d817
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/user-preferences/allow-private-messages.hbs
@@ -0,0 +1,6 @@
+<div class="control-group private-messages">
+  <label class="control-label">{{i18n "user.private_messages"}}</label>
+  <div class="controls">
+    <PreferenceCheckbox @labelKey="user.allow_private_messages" @checked={{@model.user_option.allow_private_messages}} />
+  </div>
+</div>
diff --git a/app/assets/javascripts/discourse/app/components/user-preferences/categories.hbs b/app/assets/javascripts/discourse/app/components/user-preferences/categories.hbs
new file mode 100644
index 00000000000..db5cb241df9
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/user-preferences/categories.hbs
@@ -0,0 +1,53 @@
+<div class="control-group category-notifications">
+  <label class="control-label">{{i18n "user.categories_settings"}}</label>
+
+  <div class="controls tracking-controls tracking-controls--watched-categories">
+    <label>{{d-icon "d-watching"}} {{i18n "user.watched_categories"}}</label>
+    {{#if @canSee}}
+      <a class="show-tracking" href={{@model.watchingTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>
+    {{/if}}
+    <CategorySelector @categories={{@model.watchedCategories}} @blockedCategories={{@selectedCategories}} @onChange={{action (mut @model.watchedCategories)}} />
+  </div>
+  <div class="instructions">{{i18n "user.watched_categories_instructions"}}</div>
+
+  <div class="controls tracking-controls tracking-controls--tracked-categories">
+    <label>{{d-icon "d-tracking"}} {{i18n "user.tracked_categories"}}</label>
+    {{#if @canSee}}
+      <a class="show-tracking" href={{@model.trackingTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>
+    {{/if}}
+    <CategorySelector @categories={{@model.trackedCategories}} @blockedCategories={{@selectedCategories}} @onChange={{action (mut @model.trackedCategories)}} />
+  </div>
+  <div class="instructions">{{i18n "user.tracked_categories_instructions"}}</div>
+
+  <div class="controls tracking-controls tracking-controls--watched-first-categories">
+    <label>{{d-icon "d-watching-first"}} {{i18n "user.watched_first_post_categories"}}</label>
+    <CategorySelector @categories={{@model.watchedFirstPostCategories}} @blockedCategories={{@selectedCategories}} @onChange={{action (mut @model.watchedFirstPostCategories)}} />
+  </div>
+  <div class="instructions">{{i18n "user.watched_first_post_categories_instructions"}}</div>
+
+  {{#if @siteSettings.mute_all_categories_by_default}}
+    <div class="controls tracking-controls tracking-controls--regular-categories">
+      <label>{{d-icon "d-regular"}} {{i18n "user.regular_categories"}}</label>
+      <CategorySelector @categories={{@model.regularCategories}} @blockedCategories={{@selectedCategories}} @onChange={{action (mut @model.regularCategories)}} />
+    </div>
+    <div class="instructions">{{i18n "user.regular_categories_instructions"}}</div>
+  {{else}}
+    <div class="controls tracking-controls tracking-controls--muted-categories">
+      <label>{{d-icon "d-muted"}} {{i18n "user.muted_categories"}}</label>
+
+      {{#if @canSee}}
+        <a class="show-tracking" href={{@model.mutedTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>
+      {{/if}}
+
+      <CategorySelector @categories={{@model.mutedCategories}} @blockedCategories={{@selectedCategories}} @onChange={{action (mut @model.mutedCategories)}} />
+    </div>
+
+    <div class="instructions">{{i18n (if @hideMutedTags "user.muted_categories_instructions" "user.muted_categories_instructions_dont_hide")}}</div>
+  {{/if}}
+</div>
+
+<PluginOutlet @name="user-preferences-categories" @tagName="span" @connectorTagName="div" @args={{hash model=@model save=@save}} />
+
+<br>
+
+<PluginOutlet @name="user-custom-controls" @tagName="span" @connectorTagName="div" @args={{hash model=@model}} />
diff --git a/app/assets/javascripts/discourse/app/components/user-preferences/tags.hbs b/app/assets/javascripts/discourse/app/components/user-preferences/tags.hbs
new file mode 100644
index 00000000000..a63a17ca4ae
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/user-preferences/tags.hbs
@@ -0,0 +1,45 @@
+{{#if @siteSettings.tagging_enabled}}
+  <div class="control-group tag-notifications">
+    <label class="control-label">{{i18n "user.tag_settings"}}</label>
+
+    <div class="controls tracking-controls">
+      <label>{{d-icon "d-watching" class="icon watching"}} {{i18n "user.watched_tags"}}</label>
+      <TagChooser @tags={{@model.watched_tags}} @blockedTags={{@selectedTags}} @everyTag={{true}} @unlimitedTagCount={{true}} @options={{hash
+          allowAny=false
+        }} />
+    </div>
+
+    <div class="instructions">{{i18n "user.watched_tags_instructions"}}</div>
+
+    <div class="controls tracking-controls">
+      <label>{{d-icon "d-tracking" class="icon tracking"}} {{i18n "user.tracked_tags"}}</label>
+      <TagChooser @tags={{@model.tracked_tags}} @blockedTags={{@selectedTags}} @everyTag={{true}} @unlimitedTagCount={{true}} @options={{hash
+          allowAny=false
+        }} />
+    </div>
+
+    <div class="instructions">{{i18n "user.tracked_tags_instructions"}}</div>
+
+    <div class="controls tracking-controls">
+      <label>{{d-icon "d-watching-first" class="icon watching-first-post"}} {{i18n "user.watched_first_post_tags"}}</label>
+      <TagChooser @tags={{@model.watching_first_post_tags}} @blockedTags={{@selectedTags}} @everyTag={{true}} @unlimitedTagCount={{true}} @options={{hash
+          allowAny=false
+        }} />
+    </div>
+
+    <div class="instructions">
+      {{i18n "user.watched_first_post_tags_instructions"}}
+    </div>
+
+    <div class="controls tracking-controls">
+      <label>{{d-icon "d-muted" class="icon muted"}} {{i18n "user.muted_tags"}}</label>
+      <TagChooser @tags={{@model.muted_tags}} @blockedTags={{@selectedTags}} @everyTag={{true}} @unlimitedTagCount={{true}} @options={{hash
+          allowAny=false
+        }} />
+    </div>
+    <div class="instructions">{{i18n "user.muted_tags_instructions"}}</div>
+  </div>
+
+  <PluginOutlet @name="user-preferences-tags" @connectorTagName="div" @args={{hash model=@model save=@save}} />
+  <PluginOutlet @name="user-custom-controls" @connectorTagName="div" @args={{hash model=@model}} />
+{{/if}}
diff --git a/app/assets/javascripts/discourse/app/components/user-preferences/topic-tracking.hbs b/app/assets/javascripts/discourse/app/components/user-preferences/topic-tracking.hbs
new file mode 100644
index 00000000000..75e772cb73c
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/user-preferences/topic-tracking.hbs
@@ -0,0 +1,16 @@
+<div class="user-preferences_tracking-topics-controls">
+  <div class="controls controls-dropdown">
+    <label>{{i18n "user.new_topic_duration.label"}}</label>
+    <ComboBox @class="duration" @valueProperty="value" @content={{@considerNewTopicOptions}} @value={{@model.user_option.new_topic_duration_minutes}} @onChange={{action (mut @model.user_option.new_topic_duration_minutes)}} />
+  </div>
+
+  <div class="controls controls-dropdown">
+    <label>{{i18n "user.auto_track_topics"}}</label>
+    <ComboBox @valueProperty="value" @content={{@autoTrackDurations}} @value={{@model.user_option.auto_track_topics_after_msecs}} @onChange={{action (mut @model.user_option.auto_track_topics_after_msecs)}} />
+  </div>
+
+  <div class="controls controls-dropdown">
+    <label>{{i18n "user.notification_level_when_replying"}}</label>
+    <ComboBox @valueProperty="value" @content={{@notificationLevelsForReplying}} @value={{@model.user_option.notification_level_when_replying}} @onChange={{action (mut @model.user_option.notification_level_when_replying)}} />
+  </div>
+</div>
diff --git a/app/assets/javascripts/discourse/app/components/user-preferences/user-api-keys.hbs b/app/assets/javascripts/discourse/app/components/user-preferences/user-api-keys.hbs
new file mode 100644
index 00000000000..96833b93a32
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/user-preferences/user-api-keys.hbs
@@ -0,0 +1,26 @@
+{{#if @model.userApiKeys}}
+  <div class="control-group apps">
+    <label class="control-label">{{i18n "user.apps"}}</label>
+    <div class="controls">
+      {{#each @model.userApiKeys as |key|}}
+        <div>
+          <span>{{key.application_name}}</span>
+          {{#if key.revoked}}
+            <DButton @action={{route-action "undoRevokeApiKey"}} @actionParam={{key}} @class="btn" @label="user.undo_revoke_access" />
+          {{else}}
+            <DButton @action={{route-action "revokeApiKey"}} @actionParam={{key}} @class="btn" @label="user.revoke_access" />
+          {{/if}}
+          <p>
+            <ul>
+              {{#each key.scopes as |scope|}}
+                <li>{{scope}}</li>
+              {{/each}}
+            </ul>
+          </p>
+          <p><span>{{i18n "user.api_approved"}}</span> {{bound-date key.created_at}}</p>
+          <p><span>{{i18n "user.api_last_used_at"}}</span> {{bound-date key.last_used_at}}</p>
+        </div>
+      {{/each}}
+    </div>
+  </div>
+{{/if}}
diff --git a/app/assets/javascripts/discourse/app/controllers/preferences/tracking.js b/app/assets/javascripts/discourse/app/controllers/preferences/tracking.js
new file mode 100644
index 00000000000..a2c76e7e3ba
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/controllers/preferences/tracking.js
@@ -0,0 +1,157 @@
+import Controller from "@ember/controller";
+import { NotificationLevels } from "discourse/lib/notification-levels";
+import I18n from "I18n";
+import { popupAjaxError } from "discourse/lib/ajax-error";
+import { action, computed } from "@ember/object";
+import { inject as service } from "@ember/service";
+import { tracked } from "@glimmer/tracking";
+
+export default class extends Controller {
+  @service currentUser;
+  @service siteSettings;
+  @tracked saved = false;
+
+  saveAttrNames = [
+    "new_topic_duration_minutes",
+    "auto_track_topics_after_msecs",
+    "notification_level_when_replying",
+    "muted_category_ids",
+    "regular_category_ids",
+    "watched_category_ids",
+    "tracked_category_ids",
+    "watched_first_post_category_ids",
+    "muted_tags",
+    "tracked_tags",
+    "watched_tags",
+    "watching_first_post_tags",
+  ];
+
+  likeNotificationFrequencies = [
+    { name: I18n.t("user.like_notification_frequency.always"), value: 0 },
+    {
+      name: I18n.t("user.like_notification_frequency.first_time_and_daily"),
+      value: 1,
+    },
+    { name: I18n.t("user.like_notification_frequency.first_time"), value: 2 },
+    { name: I18n.t("user.like_notification_frequency.never"), value: 3 },
+  ];
+
+  autoTrackDurations = [
+    { name: I18n.t("user.auto_track_options.never"), value: -1 },
+    { name: I18n.t("user.auto_track_options.immediately"), value: 0 },
+    {
+      name: I18n.t("user.auto_track_options.after_30_seconds"),
+      value: 30000,
+    },
+    { name: I18n.t("user.auto_track_options.after_1_minute"), value: 60000 },
+    {
+      name: I18n.t("user.auto_track_options.after_2_minutes"),
+      value: 120000,
+    },
+    {
+      name: I18n.t("user.auto_track_options.after_3_minutes"),
+      value: 180000,
+    },
+    {
+      name: I18n.t("user.auto_track_options.after_4_minutes"),
+      value: 240000,
+    },
+    {
+      name: I18n.t("user.auto_track_options.after_5_minutes"),
+      value: 300000,
+    },
+    {
+      name: I18n.t("user.auto_track_options.after_10_minutes"),
+      value: 600000,
+    },
+  ];
+
+  notificationLevelsForReplying = [
+    {
+      name: I18n.t("topic.notifications.watching.title"),
+      value: NotificationLevels.WATCHING,
+    },
+    {
+      name: I18n.t("topic.notifications.tracking.title"),
+      value: NotificationLevels.TRACKING,
+    },
+    {
+      name: I18n.t("topic.notifications.regular.title"),
+      value: NotificationLevels.REGULAR,
+    },
+  ];
+
+  considerNewTopicOptions = [
+    { name: I18n.t("user.new_topic_duration.not_viewed"), value: -1 },
+    { name: I18n.t("user.new_topic_duration.after_1_day"), value: 60 * 24 },
+    { name: I18n.t("user.new_topic_duration.after_2_days"), value: 60 * 48 },
+    {
+      name: I18n.t("user.new_topic_duration.after_1_week"),
+      value: 7 * 60 * 24,
+    },
+    {
+      name: I18n.t("user.new_topic_duration.after_2_weeks"),
+      value: 2 * 7 * 60 * 24,
+    },
+    { name: I18n.t("user.new_topic_duration.last_here"), value: -2 },
+  ];
+
+  get canSee() {
+    return this.currentUser.id === this.model.id;
+  }
+
+  @computed(
+    "model.watched_tags.[]",
+    "model.watching_first_post_tags.[]",
+    "model.tracked_tags.[]",
+    "model.muted_tags.[]"
+  )
+  get selectedTags() {
+    return []
+      .concat(
+        this.model.watched_tags,
+        this.model.watching_first_post_tags,
+        this.model.tracked_tags,
+        this.model.muted_tags
+      )
+      .filter((t) => t);
+  }
+
+  @computed(
+    "model.watchedCategories",
+    "model.watchedFirstPostCategories",
+    "model.trackedCategories",
+    "model.mutedCategories"
+  )
+  get selectedCategories() {
+    return []
+      .concat(
+        this.modelwatchedCategories,
+        this.model.watchedFirstPostCategories,
+        this.model.tracakedCategories,
+        this.model.mutedCategories
+      )
+      .filter((t) => t);
+  }
+
+  @computed("siteSettings.remove_muted_tags_from_latest")
+  get hideMutedTags() {
+    return this.siteSettings.remove_muted_tags_from_latest !== "never";
+  }
+
+  get canSave() {
+    return this.canSee || this.currentUser.admin;
+  }
+
+  @action
+  save() {
+    this.saved = false;
+
+    return this.model
+      .save(this.saveAttrNames)
+      .then(() => {
+        this.saved = true;
+      })
+      .catch(popupAjaxError);
+  }
+}
diff --git a/app/assets/javascripts/discourse/app/controllers/preferences/users.js b/app/assets/javascripts/discourse/app/controllers/preferences/users.js
index f47f7efec3b..81eb728d3f3 100644
--- a/app/assets/javascripts/discourse/app/controllers/preferences/users.js
+++ b/app/assets/javascripts/discourse/app/controllers/preferences/users.js
@@ -51,6 +51,7 @@ export default Controller.extend({
     this._super(...arguments);
 
     this.saveAttrNames = [
+      "allow_private_messages",
       "muted_usernames",
       "allowed_pm_usernames",
       "enable_allowed_pm_users",
@@ -72,11 +73,6 @@ export default Controller.extend({
     return !allowPrivateMessages;
   },
 
-  @discourseComputed("currentUser.can_send_private_messages")
-  showMessageSettings() {
-    return this.currentUser?.can_send_private_messages;
-  },
-
   @action
   save() {
     this.set("saved", false);
diff --git a/app/assets/javascripts/discourse/app/routes/app-route-map.js b/app/assets/javascripts/discourse/app/routes/app-route-map.js
index fd06c0b178b..452125109be 100644
--- a/app/assets/javascripts/discourse/app/routes/app-route-map.js
+++ b/app/assets/javascripts/discourse/app/routes/app-route-map.js
@@ -161,6 +161,7 @@ export default function () {
         this.route("profile");
         this.route("emails");
         this.route("notifications");
+        this.route("tracking");
         this.route("categories");
         this.route("users");
         this.route("tags");
diff --git a/app/assets/javascripts/discourse/app/routes/preferences-tracking.js b/app/assets/javascripts/discourse/app/routes/preferences-tracking.js
new file mode 100644
index 00000000000..bfec0d17c4c
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/routes/preferences-tracking.js
@@ -0,0 +1,5 @@
+import RestrictedUserRoute from "discourse/routes/restricted-user";
+
+export default RestrictedUserRoute.extend({
+  showFooter: true,
+});
diff --git a/app/assets/javascripts/discourse/app/templates/preferences.hbs b/app/assets/javascripts/discourse/app/templates/preferences.hbs
index b2aa84d5020..21758e3d4ff 100644
--- a/app/assets/javascripts/discourse/app/templates/preferences.hbs
+++ b/app/assets/javascripts/discourse/app/templates/preferences.hbs
@@ -3,8 +3,7 @@
   <div class="user-navigation user-navigation-secondary">
     <HorizontalOverflowNav>
       <UserNav::PreferencesNav
-          @user={{this.model}}
-          @viewingSelf={{this.viewingSelf}}
+          @currentUser={{this.currentUser}}
           @model={{this.model}}
           @siteSettings={{this.siteSettings}}/>
     </HorizontalOverflowNav>
@@ -79,6 +78,7 @@
           </LinkTo>
         </li>
       {{/if}}
+
       <PluginOutlet @name="user-preferences-nav" @tagName="span" @connectorTagName="li" @args={{hash model=this.model}} />
     </MobileNav>
   </DSection>
diff --git a/app/assets/javascripts/discourse/app/templates/preferences/apps.hbs b/app/assets/javascripts/discourse/app/templates/preferences/apps.hbs
index 56795452dc7..cd41f237626 100644
--- a/app/assets/javascripts/discourse/app/templates/preferences/apps.hbs
+++ b/app/assets/javascripts/discourse/app/templates/preferences/apps.hbs
@@ -1,28 +1,3 @@
-{{#if this.model.userApiKeys}}
-  <div class="control-group apps">
-    <label class="control-label">{{i18n "user.apps"}}</label>
-    <div class="controls">
-      {{#each this.model.userApiKeys as |key|}}
-        <div>
-          <span>{{key.application_name}}</span>
-          {{#if key.revoked}}
-            <DButton @action={{route-action "undoRevokeApiKey"}} @actionParam={{key}} @class="btn" @label="user.undo_revoke_access" />
-          {{else}}
-            <DButton @action={{route-action "revokeApiKey"}} @actionParam={{key}} @class="btn" @label="user.revoke_access" />
-          {{/if}}
-          <p>
-            <ul>
-              {{#each key.scopes as |scope|}}
-                <li>{{scope}}</li>
-              {{/each}}
-            </ul>
-          </p>
-          <p><span>{{i18n "user.api_approved"}}</span> {{bound-date key.created_at}}</p>
-          <p><span>{{i18n "user.api_last_used_at"}}</span> {{bound-date key.last_used_at}}</p>
-        </div>
-      {{/each}}
-    </div>
-  </div>
-{{/if}}
+<UserPreferences::UserApiKeys @model={{@model}}/>
 
 <PluginOutlet @name="user-preferences-apps" @tagName="span" @connectorTagName="div" @args={{hash model=this.model}} />
diff --git a/app/assets/javascripts/discourse/app/templates/preferences/categories.hbs b/app/assets/javascripts/discourse/app/templates/preferences/categories.hbs
index 8a0b2b716b3..813e34faf37 100644
--- a/app/assets/javascripts/discourse/app/templates/preferences/categories.hbs
+++ b/app/assets/javascripts/discourse/app/templates/preferences/categories.hbs
@@ -1,53 +1,10 @@
-<div class="control-group category-notifications">
-  <label class="control-label">{{i18n "user.categories_settings"}}</label>
-
-  <div class="controls tracking-controls tracking-controls--watched-categories">
-    <label>{{d-icon "d-watching"}} {{i18n "user.watched_categories"}}</label>
-    {{#if this.canSee}}
-      <a class="show-tracking" href={{this.model.watchingTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>
-    {{/if}}
-    <CategorySelector @categories={{this.model.watchedCategories}} @blockedCategories={{this.selectedCategories}} @onChange={{action (mut this.model.watchedCategories)}} />
-  </div>
-  <div class="instructions">{{i18n "user.watched_categories_instructions"}}</div>
-
-  <div class="controls tracking-controls tracking-controls--tracked-categories">
-    <label>{{d-icon "d-tracking"}} {{i18n "user.tracked_categories"}}</label>
-    {{#if this.canSee}}
-      <a class="show-tracking" href={{this.model.trackingTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>
-    {{/if}}
-    <CategorySelector @categories={{this.model.trackedCategories}} @blockedCategories={{this.selectedCategories}} @onChange={{action (mut this.model.trackedCategories)}} />
-  </div>
-  <div class="instructions">{{i18n "user.tracked_categories_instructions"}}</div>
-
-  <div class="controls tracking-controls tracking-controls--watched-first-categories">
-    <label>{{d-icon "d-watching-first"}} {{i18n "user.watched_first_post_categories"}}</label>
-    <CategorySelector @categories={{this.model.watchedFirstPostCategories}} @blockedCategories={{this.selectedCategories}} @onChange={{action (mut this.model.watchedFirstPostCategories)}} />
-  </div>
-  <div class="instructions">{{i18n "user.watched_first_post_categories_instructions"}}</div>
-
-  {{#if this.siteSettings.mute_all_categories_by_default}}
-    <div class="controls tracking-controls tracking-controls--regular-categories">
-      <label>{{d-icon "d-regular"}} {{i18n "user.regular_categories"}}</label>
-      <CategorySelector @categories={{this.model.regularCategories}} @blockedCategories={{this.selectedCategories}} @onChange={{action (mut this.model.regularCategories)}} />
-    </div>
-    <div class="instructions">{{i18n "user.regular_categories_instructions"}}</div>
-  {{else}}
-    <div class="controls tracking-controls tracking-controls--muted-categories">
-      <label>{{d-icon "d-muted"}} {{i18n "user.muted_categories"}}</label>
-      {{#if this.canSee}}
-        <a class="show-tracking" href={{this.model.mutedTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>
-      {{/if}}
-      <CategorySelector @categories={{this.model.mutedCategories}} @blockedCategories={{this.selectedCategories}} @onChange={{action (mut this.model.mutedCategories)}} />
-    </div>
-    <div class="instructions">{{i18n (if this.hideMutedTags "user.muted_categories_instructions" "user.muted_categories_instructions_dont_hide")}}</div>
-  {{/if}}
-</div>
-
-<PluginOutlet @name="user-preferences-categories" @tagName="span" @connectorTagName="div" @args={{hash model=this.model save=(action "save")}} />
-
-<br>
-
-<PluginOutlet @name="user-custom-controls" @tagName="span" @connectorTagName="div" @args={{hash model=this.model}} />
+<UserPreferences::Categories
+  @canSee={{this.canSee}}
+  @model={{this.model}}
+  @selectedCategories={{this.selectedCategories}}
+  @hideMutedTags={{this.hideMutedTags}}
+  @save={{action "save"}}
+  @siteSettings={{this.siteSettings}}/>
 
 {{#if this.canSave}}
   <SaveControls @model={{this.model}} @action={{action "save"}} @saved={{this.saved}} />
diff --git a/app/assets/javascripts/discourse/app/templates/preferences/notifications.hbs b/app/assets/javascripts/discourse/app/templates/preferences/notifications.hbs
index 6f142e25a1c..62135b8560a 100644
--- a/app/assets/javascripts/discourse/app/templates/preferences/notifications.hbs
+++ b/app/assets/javascripts/discourse/app/templates/preferences/notifications.hbs
@@ -1,20 +1,13 @@
 <div class="control-group notifications">
   <label class="control-label">{{i18n "user.notifications"}}</label>
 
-  <div class="controls controls-dropdown">
-    <label>{{i18n "user.new_topic_duration.label"}}</label>
-    <ComboBox @class="duration" @valueProperty="value" @content={{this.considerNewTopicOptions}} @value={{this.model.user_option.new_topic_duration_minutes}} @onChange={{action (mut this.model.user_option.new_topic_duration_minutes)}} />
-  </div>
-
-  <div class="controls controls-dropdown">
-    <label>{{i18n "user.auto_track_topics"}}</label>
-    <ComboBox @valueProperty="value" @content={{this.autoTrackDurations}} @value={{this.model.user_option.auto_track_topics_after_msecs}} @onChange={{action (mut this.model.user_option.auto_track_topics_after_msecs)}} />
-  </div>
-
-  <div class="controls controls-dropdown">
-    <label>{{i18n "user.notification_level_when_replying"}}</label>
-    <ComboBox @valueProperty="value" @content={{this.notificationLevelsForReplying}} @value={{this.model.user_option.notification_level_when_replying}} @onChange={{action (mut this.model.user_option.notification_level_when_replying)}} />
-  </div>
+  {{#unless this.currentUser.redesigned_user_page_nav_enabled}}
+    <UserPreferences::TopicTracking
+      @considerNewTopicOptions={{this.considerNewTopicOptions}}
+      @model={{this.model}}
+      @autoTrackDurations={{this.autoTrackDurations}}
+      @notificationLevelsForReplying={{this.notificationLevelsForReplying}} />
+  {{/unless}}
 
   <div class="controls controls-dropdown">
     <label>{{i18n "user.like_notification_frequency.title"}}</label>
@@ -34,13 +27,9 @@
 <UserNotificationSchedule @model={{this.model}} />
 
 {{#if this.showMessageSettings}}
-  <div class="control-group private-messages">
-    <label class="control-label">{{i18n "user.private_messages"}}</label>
-
-    <div class="controls">
-      <PreferenceCheckbox @labelKey="user.allow_private_messages" @checked={{this.model.user_option.allow_private_messages}} />
-    </div>
-  </div>
+  {{#unless this.currentUser.redesigned_user_page_nav_enabled}}
+    <UserPreferences::AllowPrivateMessages @model={{this.model}} />
+  {{/unless}}
 {{/if}}
 
 <PluginOutlet @name="user-preferences-notifications" @tagName="span" @connectorTagName="div" @args={{hash model=this.model save=(action "save")}} />
diff --git a/app/assets/javascripts/discourse/app/templates/preferences/security.hbs b/app/assets/javascripts/discourse/app/templates/preferences/security.hbs
index 78459f73e73..54a517cf807 100644
--- a/app/assets/javascripts/discourse/app/templates/preferences/security.hbs
+++ b/app/assets/javascripts/discourse/app/templates/preferences/security.hbs
@@ -71,6 +71,10 @@
   </div>
 {{/if}}
 
+{{#if this.currentUser.redesigned_user_page_nav_enabled}}
+  <UserPreferences::UserApiKeys @model={{@model}}/>
+{{/if}}
+
 <PluginOutlet @name="user-preferences-security" @tagName="span" @connectorTagName="div" @args={{hash model=this.model save=(action "save")}} />
 
 <br>
diff --git a/app/assets/javascripts/discourse/app/templates/preferences/tags.hbs b/app/assets/javascripts/discourse/app/templates/preferences/tags.hbs
index 6ef089fc766..71b18e61ddd 100644
--- a/app/assets/javascripts/discourse/app/templates/preferences/tags.hbs
+++ b/app/assets/javascripts/discourse/app/templates/preferences/tags.hbs
@@ -1,50 +1,7 @@
-{{#if this.siteSettings.tagging_enabled}}
-  <div class="control-group tag-notifications">
-    <label class="control-label">{{i18n "user.tag_settings"}}</label>
+<UserPreferences::Tags
+  @model={{this.model}}
+  @selectedTags={{this.selectedTags}}
+  @save={{action "save"}}
+  @siteSettings={{this.siteSettings}}/>
 
-    <div class="controls tracking-controls">
-      <label>{{d-icon "d-watching" class="icon watching"}} {{i18n "user.watched_tags"}}</label>
-      <TagChooser @tags={{this.model.watched_tags}} @blockedTags={{this.selectedTags}} @everyTag={{true}} @unlimitedTagCount={{true}} @options={{hash
-          allowAny=false
-        }} />
-    </div>
-
-    <div class="instructions">{{i18n "user.watched_tags_instructions"}}</div>
-
-    <div class="controls tracking-controls">
-      <label>{{d-icon "d-tracking" class="icon tracking"}} {{i18n "user.tracked_tags"}}</label>
-      <TagChooser @tags={{this.model.tracked_tags}} @blockedTags={{this.selectedTags}} @everyTag={{true}} @unlimitedTagCount={{true}} @options={{hash
-          allowAny=false
-        }} />
-    </div>
-
-    <div class="instructions">{{i18n "user.tracked_tags_instructions"}}</div>
-
-    <div class="controls tracking-controls">
-      <label>{{d-icon "d-watching-first" class="icon watching-first-post"}} {{i18n "user.watched_first_post_tags"}}</label>
-      <TagChooser @tags={{this.model.watching_first_post_tags}} @blockedTags={{this.selectedTags}} @everyTag={{true}} @unlimitedTagCount={{true}} @options={{hash
-          allowAny=false
-        }} />
-    </div>
-
-    <div class="instructions">
-      {{i18n "user.watched_first_post_tags_instructions"}}
-    </div>
-
-    <div class="controls tracking-controls">
-      <label>{{d-icon "d-muted" class="icon muted"}} {{i18n "user.muted_tags"}}</label>
-      <TagChooser @tags={{this.model.muted_tags}} @blockedTags={{this.selectedTags}} @everyTag={{true}} @unlimitedTagCount={{true}} @options={{hash
-          allowAny=false
-        }} />
-    </div>
-    <div class="instructions">{{i18n "user.muted_tags_instructions"}}</div>
-  </div>
-
-  <PluginOutlet @name="user-preferences-tags" @tagName="span" @connectorTagName="div" @args={{hash model=this.model save=(action "save")}} />
-
-  <br>
-
-  <PluginOutlet @name="user-custom-controls" @tagName="span" @connectorTagName="div" @args={{hash model=this.model}} />
-
-  <SaveControls @model={{this.model}} @action={{action "save"}} @saved={{this.saved}} />
-{{/if}}
+<SaveControls @model={{this.model}} @action={{action "save"}} @saved={{this.saved}} />
diff --git a/app/assets/javascripts/discourse/app/templates/preferences/tracking.hbs b/app/assets/javascripts/discourse/app/templates/preferences/tracking.hbs
new file mode 100644
index 00000000000..c12f05eeb91
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/templates/preferences/tracking.hbs
@@ -0,0 +1,29 @@
+<DSection @pageClass="user-preferences-tracking" />
+
+<div class="user-preferences_tracking-topics-wrapper">
+  <label class="control-label">{{i18n "user.topics_settings"}}</label>
+  <UserPreferences::TopicTracking
+    @considerNewTopicOptions={{this.considerNewTopicOptions}}
+    @model={{this.model}}
+    @autoTrackDurations={{this.autoTrackDurations}}
+    @notificationLevelsForReplying={{this.notificationLevelsForReplying}} />
+</div>
+
+<div class="user-preferences_tracking-categories-tags-wrapper">
+  <UserPreferences::Categories
+    @canSee={{this.canSee}}
+    @model={{this.model}}
+    @selectedCategories={{this.selectedCategories}}
+    @hideMutedTags={{this.hideMutedTags}}
+    @siteSettings={{this.siteSettings}} />
+
+  <UserPreferences::Tags
+    @model={{this.model}}
+    @selectedTags={{this.selectedTags}}
+    @save={{this.save}}
+    @siteSettings={{this.siteSettings}} />
+</div>
+
+{{#if this.canSave}}
+  <SaveControls @model={{this.model}} @action={{this.save}} @saved={{this.saved}} />
+{{/if}}
diff --git a/app/assets/javascripts/discourse/app/templates/preferences/users.hbs b/app/assets/javascripts/discourse/app/templates/preferences/users.hbs
index 5589f14d47e..69c15a274ec 100644
--- a/app/assets/javascripts/discourse/app/templates/preferences/users.hbs
+++ b/app/assets/javascripts/discourse/app/templates/preferences/users.hbs
@@ -21,7 +21,11 @@
   <div class="instructions">{{i18n "user.muted_users_instructions"}}</div>
 </div>
 
-{{#if this.showMessageSettings}}
+{{#if this.currentUser.can_send_private_messages}}
+  {{#if this.currentUser.redesigned_user_page_nav_enabled}}
+    <UserPreferences::AllowPrivateMessages @model={{this.model}} />
+  {{/if}}
+
   <div class="control-group user-allow-pm">
     <div class="controls">
       <PreferenceCheckbox @labelKey="user.allow_private_messages_from_specific_users" @checked={{this.model.user_option.enable_allowed_pm_users}} @disabled={{this.disableAllowPmUsersSetting}} />
diff --git a/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js b/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js
index 38891cc8e94..f0499b3984d 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js
@@ -91,6 +91,7 @@ acceptance("User Preferences", function (needs) {
       "/u/eviltrout/preferences/account",
       "defaults to account tab"
     );
+
     assert.ok(exists(".user-preferences"), "it shows the preferences");
 
     const savePreferences = async () => {
@@ -112,25 +113,32 @@ acceptance("User Preferences", function (needs) {
     await savePreferences();
 
     await click(".preferences-nav .nav-notifications a");
+
     await selectKit(
       ".control-group.notifications .combo-box.duration"
     ).expand();
+
     await selectKit(
       ".control-group.notifications .combo-box.duration"
     ).selectRowByValue(1440);
+
     await savePreferences();
 
     await click(".preferences-nav .nav-categories a");
+
     const categorySelector = selectKit(
       ".tracking-controls .category-selector "
     );
+
     await categorySelector.expand();
     await categorySelector.fillInFilter("faq");
     await savePreferences();
 
     this.siteSettings.tagging_enabled = false;
+
     await visit("/");
     await visit("/u/eviltrout/preferences");
+
     assert.ok(
       !exists(".preferences-nav .nav-tags a"),
       "tags tab isn't there when tags are disabled"
@@ -564,7 +572,7 @@ acceptance("Ignored users", function (needs) {
   });
 });
 
-acceptance("Security", function (needs) {
+acceptance("User Preferences - Security", function (needs) {
   needs.user();
   needs.pretender(preferencesPretender);
 
diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-preferences-new-menu-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-new-menu-test.js
new file mode 100644
index 00000000000..64fc8f8f836
--- /dev/null
+++ b/app/assets/javascripts/discourse/tests/acceptance/user-preferences-new-menu-test.js
@@ -0,0 +1,60 @@
+import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers";
+import { click, visit } from "@ember/test-helpers";
+import { test } from "qunit";
+import selectKit from "discourse/tests/helpers/select-kit-helper";
+
+acceptance(
+  "New User Menu - Horizontal nav and preferences relocation",
+  function (needs) {
+    needs.user({
+      redesigned_user_page_nav_enabled: true,
+      user_api_keys: [
+        {
+          id: 1,
+          application_name: "Discourse Hub",
+          scopes: ["Read and clear notifications"],
+          created_at: "2020-11-14T00:57:09.093Z",
+          last_used_at: "2022-09-22T18:55:41.672Z",
+        },
+      ],
+    });
+
+    test("Horizontal user nav exists", async function (assert) {
+      await visit("/u/eviltrout/preferences");
+      assert.ok(exists(".horizontal-overflow-nav"), "horizontal nav exists");
+    });
+
+    test("User Tracking page exists", async function (assert) {
+      await visit("/u/eviltrout/preferences");
+      assert.ok(exists(".nav-tracking"), "the new tracking page link exists");
+    });
+
+    test("User Categories page no longer exists", async function (assert) {
+      await visit("/u/eviltrout/preferences");
+      assert.ok(!exists(".nav-categories"), "Categories tab no longer exists");
+    });
+
+    test("Can save category tracking preferences", async function (assert) {
+      await visit("/u/eviltrout/preferences/tracking");
+
+      const categorySelector = selectKit(
+        ".tracking-controls .category-selector"
+      );
+
+      const savePreferences = async () => {
+        assert.notOk(exists(".saved"), "it hasn't been saved yet");
+        await click(".save-changes");
+        assert.ok(exists(".saved"), "it displays the saved message");
+      };
+
+      await categorySelector.expand();
+      await categorySelector.fillInFilter("faq");
+      await savePreferences();
+    });
+
+    test("Can view user api keys on security page", async function (assert) {
+      await visit("/u/eviltrout/preferences/security");
+      assert.ok(exists(".control-group.apps"), "User can see apps section");
+    });
+  }
+);
diff --git a/app/assets/stylesheets/common/base/new-user.scss b/app/assets/stylesheets/common/base/new-user.scss
index 3b6374ab199..ff1fb59dd45 100644
--- a/app/assets/stylesheets/common/base/new-user.scss
+++ b/app/assets/stylesheets/common/base/new-user.scss
@@ -184,3 +184,26 @@
     margin: 1em 0;
   }
 }
+
+.user-preferences-tracking-page {
+  .user-preferences .form-vertical {
+    width: 100%;
+  }
+}
+
+.user-preferences_tracking-topics-wrapper {
+  margin-bottom: 3em;
+  .control-label {
+    margin-bottom: 1em;
+  }
+}
+
+.user-preferences_tracking-categories-tags-wrapper {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(16em, 1fr));
+  gap: 2em;
+  .control-group {
+    width: 100%;
+    min-width: 16em;
+  }
+}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index ebd5a1519d3..df210f42a95 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -1326,6 +1326,7 @@ en:
         profile: "Profile"
         emails: "Emails"
         notifications: "Notifications"
+        tracking: "Tracking"
         categories: "Categories"
         users: "Users"
         tags: "Tags"
@@ -1604,6 +1605,7 @@ en:
 
       other_settings: "Other"
       categories_settings: "Categories"
+      topics_settings: "Topics"
 
       new_topic_duration:
         label: "Consider topics new when"
diff --git a/config/routes.rb b/config/routes.rb
index 22e73895078..3b36ba31d88 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -494,6 +494,7 @@ Discourse::Application.routes.draw do
       put "#{root_path}/:username/preferences/primary-email" => "users#update_primary_email", format: :json, constraints: { username: RouteFormat.username }
       delete "#{root_path}/:username/preferences/email" => "users#destroy_email", constraints: { username: RouteFormat.username }
       get "#{root_path}/:username/preferences/notifications" => "users#preferences", constraints: { username: RouteFormat.username }
+      get "#{root_path}/:username/preferences/tracking" => "users#preferences", constraints: { username: RouteFormat.username }
       get "#{root_path}/:username/preferences/categories" => "users#preferences", constraints: { username: RouteFormat.username }
       get "#{root_path}/:username/preferences/users" => "users#preferences", constraints: { username: RouteFormat.username }
       get "#{root_path}/:username/preferences/tags" => "users#preferences", constraints: { username: RouteFormat.username }