diff --git a/src/store/modules/normalizers.js b/src/store/modules/normalizers.js
index 3499157e200a20623be1666bd65780f21133b6fd..c52d5c81df64c537618b18721b608fcbab7956b7 100644
--- a/src/store/modules/normalizers.js
+++ b/src/store/modules/normalizers.js
@@ -2,103 +2,6 @@ const nonAtomsTuples = ['replace', ':replace']
 const nonAtomsObjects = ['match_actor', ':match_actor']
 const objects = ['digest', 'pleroma_fe', 'masto_fe', 'poll_limits', 'styling']
 const objectParents = ['mascots']
-const groups = {
-  'cors_plug': [
-    'credentials',
-    'expose',
-    'headers',
-    'max_age',
-    'methods'
-  ],
-  'esshd': [
-    'enabled',
-    'handler',
-    'password_authenticator',
-    'port',
-    'priv_dir'
-  ],
-  'logger': ['backends', 'console', 'ex_syslogger'],
-  'mime': ['types'],
-  'phoenix': ['format_encoders'],
-  'pleroma': [
-    'Pleroma.Captcha',
-    'Pleroma.Captcha.Kocaptcha',
-    'Pleroma.Emails.Mailer',
-    'Pleroma.Emails.UserEmail',
-    'Pleroma.Repo',
-    'Pleroma.ScheduledActivity',
-    'Pleroma.Upload',
-    'Pleroma.Upload.Filter.AnonymizeFilename',
-    'Pleroma.Upload.Filter.Mogrify',
-    'Pleroma.Uploaders.Local',
-    'Pleroma.Uploaders.MDII',
-    'Pleroma.Uploaders.S3',
-    'Pleroma.User',
-    'Pleroma.Web.Auth.Authenticator',
-    'Pleroma.Web.Endpoint',
-    'Pleroma.Web.Federator.RetryQueue',
-    'Pleroma.Web.Metadata',
-    'activitypub',
-    'admin_token',
-    'assets',
-    'auth',
-    'auto_linker',
-    'chat',
-    'database',
-    'ecto_repos',
-    'email_notifications',
-    'emoji',
-    'env',
-    'fetch_initial_posts',
-    'frontend_configurations',
-    'gopher',
-    'hackney_pools',
-    'http',
-    'http_security',
-    'instance',
-    'ldap',
-    'markup',
-    'media_proxy',
-    'mrf_hellthread',
-    'mrf_keyword',
-    'mrf_mention',
-    'mrf_normalize_markup',
-    'mrf_rejectnonpublic',
-    'mrf_simple',
-    'mrf_subchain',
-    'mrf_user_allowlist',
-    'mrf_vocabulary',
-    'oauth2',
-    'rate_limit',
-    'rich_media',
-    'suggestions',
-    'uri_schemes',
-    'user'
-  ],
-  'pleroma_job_queue': ['queues'],
-  'quack': ['level', 'meta', 'webhook_url'],
-  'tesla': ['adapter'],
-  'ueberauth': [
-    'Ueberauth',
-    'Ueberauth.Strategy.Facebook.OAuth',
-    'Ueberauth.Strategy.Google.OAuth',
-    'Ueberauth.Strategy.Microsoft.OAuth',
-    'Ueberauth.Strategy.Twitter.OAuth'
-  ],
-  'web_push_encryption': ['vapid_details']
-}
-
-export const filterIgnored = (settings, ignored) => {
-  if (settings.enabled.value === true) {
-    return settings
-  }
-
-  return ignored.reduce((acc, name) => {
-    const { [name]: ignored, ...newAcc } = acc
-
-    return newAcc
-  }, settings)
-}
 
 // REFACTOR
 export const parseTuples = (tuples, key) => {
@@ -153,6 +56,12 @@ const parseObject = (object) => {
   }, {})
 }
 
+export const parseValue = (input, value, type) => {
+  if (type === 'string' || type === 'boolean' || type === 'integer') {
+    return [{ tuple: [input, value] }]
+  }
+}
+
 export const valueHasTuples = (key, value) => {
   const valueIsArrayOfNonObjects = Array.isArray(value) && value.length > 0 && typeof value[0] !== 'object'
   return key === ':meta' ||
@@ -166,42 +75,6 @@ export const valueHasTuples = (key, value) => {
     valueIsArrayOfNonObjects
 }
 
-// REFACTOR
-export const wrapConfig = settings => {
-  return Object.keys(settings).map(config => {
-    const group = getGroup(config)
-    const key = config.startsWith('Pleroma') || config.startsWith('Ueberauth') ? config : `:${config}`
-    const value = (settings[config]['value'] !== undefined)
-      ? settings[config]['value']
-      : Object.keys(settings[config]).reduce((acc, settingName) => {
-        const data = settings[config][settingName]
-        if (data === null || data === '') {
-          return acc
-        } else if (key === ':rate_limit') {
-          return [...acc, { 'tuple': [`:${settingName}`, data] }]
-        } else if (settingName === 'ip') {
-          const ip = data.split('.').map(s => parseInt(s, 10))
-          return [...acc, { 'tuple': [`:${settingName}`, { 'tuple': ip }] }]
-        } else if (Array.isArray(data) || typeof data !== 'object') {
-          return key === ':mrf_user_allowlist'
-            ? [...acc, { 'tuple': [`${settingName}`, data] }]
-            : [...acc, { 'tuple': [`:${settingName}`, data] }]
-        } else if (nonAtomsObjects.includes(settingName)) {
-          return [...acc, { 'tuple': [`:${settingName}`, wrapNonAtomsObjects(data)] }]
-        } else if (objectParents.includes(settingName)) {
-          return [...acc, { 'tuple': [`:${settingName}`, wrapNestedObjects(data)] }]
-        } else if (objects.includes(settingName)) {
-          return [...acc, { 'tuple': [`:${settingName}`, wrapObjects(data)] }]
-        } else if (nonAtomsTuples.includes(settingName)) {
-          return [...acc, { 'tuple': [`:${settingName}`, wrapNonAtomsTuples(data)] }]
-        } else {
-          return [...acc, { 'tuple': [`:${settingName}`, wrapNestedTuples(data)] }]
-        }
-      }, [])
-    return { group, key, value }
-  })
-}
-
 const wrapNestedTuples = setting => {
   return Object.keys(setting).reduce((acc, settingName) => {
     const data = setting[settingName]
@@ -249,8 +122,3 @@ const wrapObjects = setting => {
     return { ...acc, [`:${settingName}`]: setting[settingName] }
   }, {})
 }
-
-const getGroup = key => {
-  return Object.keys(groups).find(i => groups[i].includes(key))
-}
-
diff --git a/src/store/modules/settings.js b/src/store/modules/settings.js
index aff537c6875e3257af3ab9140a50e4d51a37acab..facc27d5e0be6eaae87a3f11483327d1e4908de2 100644
--- a/src/store/modules/settings.js
+++ b/src/store/modules/settings.js
@@ -1,5 +1,5 @@
 import { fetchDescription, fetchSettings, migrateToDB, updateSettings, uploadMedia } from '@/api/settings'
-import { parseTuples, valueHasTuples, wrapConfig } from './normalizers'
+import { parseTuples, parseValue, valueHasTuples } from './normalizers'
 
 const settings = {
   state: {
@@ -41,13 +41,15 @@ const settings = {
       }, state.settings)
       state.settings = newSettings
     },
-    UPDATE_SETTINGS: (state, { group, tab, data }) => {
-      const updatedState = { [tab]: { ...state.settings[group][tab], ...data }}
-      const updatedSetting = state.updatedSettings[group]
-        ? { [tab]: { ...state.updatedSettings[group][tab], ...data }}
-        : { [tab]: data }
+    UPDATE_SETTINGS: (state, { group, key, input, value, type }) => {
+      const updatedState = { [key]: { ...state.settings[group][key], ...{ [input]: value }}}
       state.settings[group] = { ...state.settings[group], ...updatedState }
-      state.updatedSettings[group] = { ...state.updatedSettings[group], ...updatedSetting }
+
+      const settingKey = `${group}/${key}/${input}`
+      state.updatedSettings = {
+        ...state.updatedSettings,
+        ...{ [settingKey]: { group, key, value: parseValue(input, value, type) }}
+      }
     }
   },
   actions: {
@@ -69,15 +71,13 @@ const settings = {
     RewriteConfig({ commit }, { tab, data }) {
       commit('REWRITE_CONFIG', { tab, data })
     },
-    async SubmitChanges({ getters, commit, state }, data) {
-      const configs = data || wrapConfig(state.updatedSettings)
+    async SubmitChanges({ getters, commit, state }) {
+      const configs = Object.values(state.updatedSettings)
       const response = await updateSettings(configs, getters.authHost, getters.token)
-      if (data) {
-        commit('SET_SETTINGS', response.data.configs)
-      }
+      commit('SET_SETTINGS', response.data.configs)
     },
-    UpdateSettings({ commit, state }, { group, tab, data }) {
-      commit('UPDATE_SETTINGS', { group, tab, data })
+    UpdateSettings({ commit }, { group, key, input, value, type }) {
+      commit('UPDATE_SETTINGS', { group, key, input, value, type })
     },
     async UploadMedia({ dispatch, getters, state }, { file, tab, inputName, childName }) {
       const response = await uploadMedia(file, getters.authHost, getters.token)
diff --git a/src/views/settings/components/Inputs.vue b/src/views/settings/components/Inputs.vue
index f67e95ff16be21dce2faa59181c20d5c0f9a6e72..95b7ac0615bdd0598f564d1bd6aa903d8cec344d 100644
--- a/src/views/settings/components/Inputs.vue
+++ b/src/views/settings/components/Inputs.vue
@@ -4,11 +4,11 @@
       v-if="setting.type === 'string'"
       :value="inputValue"
       :placeholder="setting.suggestions ? setting.suggestions[0] : null"
-      @input="updateSetting($event, settingGroup.group, settingGroup.key, setting.key)"/>
+      @input="updateSetting($event, settingGroup.group, settingGroup.key, setting.key, setting.type)"/>
     <el-switch
       v-if="setting.type === 'boolean'"
       :value="inputValue"
-      @change="updateSetting($event, settingGroup.group, settingGroup.key, setting.key)"/>
+      @change="updateSetting($event, settingGroup.group, settingGroup.key, setting.key, setting.type)"/>
     <el-input-number
       v-if="setting.type === 'integer'"
       :value="inputValue"
@@ -16,7 +16,7 @@
       :min="0"
       size="large"
       class="top-margin"
-      @change="updateSetting($event, settingGroup.group, settingGroup.key, setting.key)"/>
+      @change="updateSetting($event, settingGroup.group, settingGroup.key, setting.key, setting.type)"/>
     <el-select
       v-if="setting.type === 'module' || (setting.type.includes('atom') && setting.type.includes(false))"
       :value="inputValue"
@@ -418,8 +418,8 @@ export default {
     toggleLimits(value, input) {
       this.updateSetting(value, this.settingGroup.group, 'rate_limit', input)
     },
-    updateSetting(value, group, tab, input) {
-      this.$store.dispatch('UpdateSettings', { group, tab, data: { [input]: value }})
+    updateSetting(value, group, key, input, type) {
+      this.$store.dispatch('UpdateSettings', { group, key, input, value, type })
     }
   }
 }