diff --git a/src/views/settings/components/Authentication.vue b/src/views/settings/components/Authentication.vue
index d8004db5e182aef9c03a523b31d4cbb7d4722f1f..0ac3214dedacf946e307cfa9e28623c3b1b3fa7a 100644
--- a/src/views/settings/components/Authentication.vue
+++ b/src/views/settings/components/Authentication.vue
@@ -35,10 +35,6 @@ export default {
       'ldapData',
       'authData',
       'oauth2Data'
-      // 'facebook',
-      // 'google',
-      // 'twitter',
-      // 'microsoft'
     ]),
     auth() {
       return this.$store.state.settings.description.find(setting => setting.key === ':auth')
diff --git a/src/views/settings/components/Endpoint.vue b/src/views/settings/components/Endpoint.vue
index aa1f661a3b39bd051ece01bb85a5e86ff315c24f..3cefc4106fe36317bd17df31ded091a33c8a2021 100644
--- a/src/views/settings/components/Endpoint.vue
+++ b/src/views/settings/components/Endpoint.vue
@@ -1,160 +1,6 @@
 <template>
-  <el-form v-if="!loading" ref="endpoint" :model="endpoint" :label-width="labelWidth">
-    <el-form-item label="Instrumenters">
-      <el-select :value="endpoint.instrumenters || []" multiple filterable allow-create @change="updateSetting($event, 'Pleroma.Web.Endpoint', 'instrumenters')">
-        <el-option
-          v-for="item in instrumentersOptions"
-          :label="item.label"
-          :key="item.value"
-          :value="item.value"/>
-      </el-select>
-    </el-form-item>
-    <div class="line"/>
-    <el-form-item label="Compile-time configuration:"/>
-    <el-form-item label="Code reloader">
-      <el-switch :value="endpoint.code_reloader" @change="updateSetting($event, 'Pleroma.Web.Endpoint', 'code_reloader')"/>
-      <p class="expl">Enables code reloading functionality</p>
-    </el-form-item>
-    <el-form-item label="Debug errors">
-      <el-switch :value="endpoint.debug_errors" @change="updateSetting($event, 'Pleroma.Web.Endpoint', 'debug_errors')"/>
-      <p class="expl">Enables using <span class="code">Plug.Debugger</span> functionality for debugging failures in the application.
-      Recommended to be set to true only in development as it allows listing of the application source code during debugging. Defaults to false.</p>
-    </el-form-item>
-    <el-form-item label="Render errors:"/>
-    <el-form-item label="View">
-      <el-input :value="endpoint.render_errors.view" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'render_errors', 'view')"/>
-    </el-form-item>
-    <el-form-item label="Accepts">
-      <el-select :value="endpoint.render_errors.accepts || []" multiple filterable allow-create @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'render_errors', 'accepts')"/>
-    </el-form-item>
-    <el-form-item label="Layout">
-      <el-switch :value="endpoint.render_errors.layout" @change="processNestedData($event, 'Pleroma.Web.Endpoint', 'render_errors', 'layout')"/>
-    </el-form-item>
-    <div class="line"/>
-    <el-form-item label="Runtime configuration:"/>
-    <el-form-item label="Cache static manifest">
-      <el-input :value="endpoint.cache_static_manifest" @input="updateSetting($event, 'Pleroma.Web.Endpoint', 'cache_static_manifest')"/>
-      <p class="expl">A path to a json manifest file that contains static files and their digested version.
-      This is typically set to <span class="code">'priv/static/cache_manifest.json'</span>
-        which is the file automatically generated by <span class="code">mix phx.digest</span></p>
-    </el-form-item>
-    <div class="line"/>
-    <el-form-item label="HTTP:"/>
-    <el-form-item label="Configure HTTP server">
-      <el-switch :value="configureHttp" @change="showServerConfig($event, 'http')"/>
-    </el-form-item>
-    <div v-if="configureHttp">
-      <el-form-item label="Dispatch">
-        <editor v-model="editorContentHttp" height="150" width="100%" lang="elixir" theme="chrome"/>
-        <p class="expl">You can type in Elixir code here</p>
-      </el-form-item>
-      <el-form-item label="Port">
-        <el-input :value="endpointHttp.port" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'http', 'port')"/>
-        <p class="expl">The port to run the server. Defaults to 4000 (http) and 4040 (https).</p>
-      </el-form-item>
-      <el-form-item label="IP">
-        <el-input :value="endpointHttp.ip" placeholder="xxx.xxx.xxx.xx" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'http', 'ip')"/>
-        <p class="expl">The ip to bind the server to</p>
-      </el-form-item>
-      <el-form-item label="Reference name">
-        <el-input :value="endpointHttp.ref" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'http', 'ref')"/>
-        <p class="expl">The reference name to be used. Defaults to <span class="code">plug.HTTP</span> (http) and
-        <span class="code">plug.HTTPS</span> (https). This is the value that needs to be given on shutdown.</p>
-      </el-form-item>
-      <el-form-item label="Compress">
-        <el-switch :value="endpointHttp.compress" @change="processNestedData($event, 'Pleroma.Web.Endpoint', 'http', 'compress')"/>
-        <p class="expl">Cowboy will attempt to compress the response body. Defaults to false.</p>
-      </el-form-item>
-      <el-form-item label="Timeout in s">
-        <el-input-number :value="endpointHttp.timeout / 1000" :step="1" :min="0" size="large" @input="processNestedData($event * 1000, 'Pleroma.Web.Endpoint', 'http', 'timeout')"/>
-        <p class="expl">Time in s with no requests before Cowboy closes the connection. Defaults to 5 s.</p>
-      </el-form-item>
-      <div class="line"/>
-    </div>
-    <el-form-item label="HTTPS:"/>
-    <el-form-item label="Configure HTTPS server">
-      <el-switch :value="configureHttps" @change="showServerConfig($event, 'https')"/>
-    </el-form-item>
-    <div v-if="configureHttps">
-      <el-form-item label="Dispatch">
-        <editor v-model="editorContentHttps" height="150" width="100%" lang="elixir" theme="chrome"/>
-        <p class="expl">You can type in Elixir code here</p>
-      </el-form-item>
-      <el-form-item label="Port">
-        <el-input :value="endpointHttps.port" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'https', 'port')"/>
-        <p class="expl">The port to run the server. Defaults to 4000 (http) and 4040 (https).</p>
-      </el-form-item>
-      <el-form-item label="IP">
-        <el-input :value="endpointHttps.ip" placeholder="xxx.xxx.xxx.xx" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'https', 'ip')"/>
-        <p class="expl">The ip to bind the server to</p>
-      </el-form-item>
-      <el-form-item label="Reference name">
-        <el-input :value="endpointHttps.ref" @input="updateSetting($event, 'Pleroma.Web.Endpoint', 'https', 'ref')"/>
-        <p class="expl">The reference name to be used. Defaults to <span class="code">plug.HTTP</span> (http) and
-        <span class="code">plug.HTTPS</span> (https). This is the value that needs to be given on shutdown.</p>
-      </el-form-item>
-      <el-form-item label="Compress">
-        <el-switch :value="endpointHttps.compress" @change="processNestedData($event, 'Pleroma.Web.Endpoint', 'https', 'compress')"/>
-        <p class="expl">Cowboy will attempt to compress the response body. Defaults to false.</p>
-      </el-form-item>
-      <el-form-item label="Timeout in s">
-        <el-input-number :value="endpointHttps.timeout / 1000" :step="1" :min="0" size="large" @input="processNestedData($event * 1000, 'Pleroma.Web.Endpoint', 'https', 'timeout')"/>
-        <p class="expl">Time in s with no requests before Cowboy closes the connection. Defaults to 5 s.</p>
-      </el-form-item>
-      <div class="line"/>
-    </div>
-    <el-form-item label="Secret key base">
-      <el-input :value="endpoint.secret_key_base" @input="updateSetting($event, 'Pleroma.Web.Endpoint', 'secret_key_base')"/>
-      <p class="expl">A secret key used as a base to generate secrets for encrypting and signing data. For example, cookies and tokens are signed by default, but they may also be encrypted if desired. Defaults to nil as it must be set per application</p>
-    </el-form-item>
-    <el-form-item label="Server">
-      <el-switch :value="endpoint.server" @change="updateSetting($event, 'Pleroma.Web.Endpoint', 'server')"/>
-      <p class="expl">When true, starts the web server when the endpoint supervision tree starts. Defaults to false. The <span class="code">mix phx.server</span> task automatically sets this to true.</p>
-    </el-form-item>
-    <div class="line"/>
-    <el-form-item label="URL:"/>
-    <el-form-item label="Host">
-      <el-input :value="endpoint.url.host" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'url', 'host')"/>
-      <p class="expl">The host without the scheme and a post (e.g <span class="code">example.com</span>, not <span class="code">https://example.com:2020</span>)</p>
-    </el-form-item>
-    <el-form-item label="Scheme">
-      <el-input :value="endpoint.url.scheme" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'url', 'scheme')"/>
-      <p class="expl">e.g http, https</p>
-    </el-form-item>
-    <el-form-item label="Port">
-      <el-input :value="endpoint.url.port" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'url', 'port')"/>
-    </el-form-item>
-    <el-form-item label="Path">
-      <el-input :value="endpoint.url.path" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'url', 'path')"/>
-    </el-form-item>
-    <div class="line"/>
-    <el-form-item label="Protocol">
-      <el-input :value="endpoint.protocol" @input="updateSetting($event, 'Pleroma.Web.Endpoint', 'protocol')"/>
-    </el-form-item>
-    <el-form-item label="Signing salt">
-      <el-input :value="endpoint.signing_salt" @input="updateSetting($event, 'Pleroma.Web.Endpoint', 'signing_salt')"/>
-    </el-form-item>
-    <div class="line"/>
-    <el-form-item label="PubSub:"/>
-    <el-form-item label="Name">
-      <el-input :value="endpoint.pubsub.name" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'pubsub', 'name')"/>
-    </el-form-item>
-    <el-form-item label="Adapter">
-      <el-input :value="endpoint.pubsub.adapter" @input="processNestedData($event, 'Pleroma.Web.Endpoint', 'pubsub', 'adapter')"/>
-    </el-form-item>
-    <div class="line"/>
-    <el-form-item label="Secure cookie flag">
-      <el-switch :value="endpoint.secure_cookie_flag" @change="updateSetting($event, 'Pleroma.Web.Endpoint', 'secure_cookie_flag')"/>
-    </el-form-item>
-    <el-form-item label="Extra cookie attrs">
-      <el-select :value="endpoint.extra_cookie_attrs || []" multiple filterable allow-create @change="updateSetting($event, 'Pleroma.Web.Endpoint', 'extra_cookie_attrs')">
-        <el-option
-          v-for="item in extraCookieAttrsOptions"
-          :label="item.label"
-          :key="item.value"
-          :value="item.value"/>
-      </el-select>
-    </el-form-item>
+  <el-form ref="endpointData" :model="endpointData" :label-width="labelWidth">
+    <setting :settings-group="endpoint" :data="endpointData"/>
     <div class="line"/>
     <el-form-item class="options-paragraph-container">
       <p class="options-paragraph">Only common options are listed here. You can add more (all configuration options can be viewed
@@ -173,79 +19,28 @@
 <script>
 import { mapGetters } from 'vuex'
 import i18n from '@/lang'
-import { options } from './options'
-import AceEditor from 'vue2-ace-editor'
-import 'brace/mode/elixir'
-import 'default-passive-events'
+import Setting from './Setting'
 
 export default {
   name: 'Endpoint',
   components: {
-    editor: AceEditor
+    Setting
   },
   computed: {
     ...mapGetters([
-      'endpoint'
+      'endpointData'
     ]),
-    editorContentHttp: {
-      get: function() {
-        return this.endpoint.http.dispatch ? this.endpoint.http.dispatch[0] : ''
-      },
-      set: function(value) {
-        this.processNestedData([value], 'Pleroma.Web.Endpoint', 'http', 'dispatch')
-      }
-    },
-    editorContentHttps: {
-      get: function() {
-        return this.endpoint.https.dispatch ? this.endpoint.https.dispatch[0] : ''
-      },
-      set: function(value) {
-        this.processNestedData([value], 'Pleroma.Web.Endpoint', 'https', 'dispatch')
-      }
-    },
-    configureHttp() {
-      return !this.endpoint.http === false
-    },
-    configureHttps() {
-      return !this.endpoint.https === false
-    },
-    endpointHttp() {
-      return this.endpoint.http || {}
-    },
-    endpointHttps() {
-      return this.endpoint.https || {}
-    },
-    extraCookieAttrsOptions() {
-      return options.extraCookieAttrsOptions
-    },
-    instrumentersOptions() {
-      return options.instrumentersOptions
+    endpoint() {
+      return this.$store.state.settings.description.find(setting => setting.key === 'Pleroma.Web.Endpoint')
     },
     isMobile() {
       return this.$store.state.app.device === 'mobile'
     },
     labelWidth() {
       return this.isMobile ? '100px' : '210px'
-    },
-    loading() {
-      return this.$store.state.settings.loading
     }
   },
   methods: {
-    processNestedData(value, tab, inputName, childName) {
-      const updatedValue = { ...this.$store.state.settings.settings[tab][inputName], ...{ [childName]: value }}
-      this.updateSetting(updatedValue, tab, inputName)
-    },
-    showServerConfig(value, protocol) {
-      if (value) {
-        this.updateSetting({}, 'Pleroma.Web.Endpoint', protocol)
-      } else {
-        this.updateSetting(value, 'Pleroma.Web.Endpoint', protocol)
-      }
-    },
-    updateSetting(value, tab, input) {
-      this.$store.dispatch('UpdateSettings', { tab, data: { [input]: value }})
-    },
     async onSubmit() {
       try {
         await this.$store.dispatch('SubmitChanges')
diff --git a/src/views/settings/components/Inputs.vue b/src/views/settings/components/Inputs.vue
index c59d3fdae335c360f65522d438227511864edf31..8a4a726819457ff9b5522854eeda1cbf5386aac5 100644
--- a/src/views/settings/components/Inputs.vue
+++ b/src/views/settings/components/Inputs.vue
@@ -51,11 +51,16 @@
         && setting.type.includes('list')
         && (setting.type.includes('tuple')
       )"
-      v-model="editorContentHttp"
+      v-model="editorContent"
       height="150"
       width="100%"
       lang="elixir"
       theme="chrome"/>
+    <el-input
+      v-if="setting.type === 'tuple'"
+      :placeholder="setting.key === 'ip' ? 'xxx.xxx.xxx.xx' : setting.suggestions[0]"
+      :value="data[setting.key]"
+      @input="updateSetting($event, settingsGroup.key, setting.key)"/>
     <p class="expl">{{ setting.description }}</p>
   </el-form-item>
 </template>
@@ -91,24 +96,21 @@ export default {
     }
   },
   computed: {
-    // editorContentHttp: {
-    //   get: function() {
-    //     return this.endpoint.http.dispatch ? this.endpoint.http.dispatch[0] : ''
-    //   },
-    //   set: function(value) {
-    //     this.processNestedData([value], 'Pleroma.Web.Endpoint', 'http', 'dispatch')
-    //   }
-    // },
-    // editorContentHttps: {
-    //   get: function() {
-    //     return this.endpoint.https.dispatch ? this.endpoint.https.dispatch[0] : ''
-    //   },
-    //   set: function(value) {
-    //     this.processNestedData([value], 'Pleroma.Web.Endpoint', 'https', 'dispatch')
-    //   }
-    // }
+    editorContent: {
+      get: function() {
+        return ''
+        // return data[setting.key] ? data[setting.key][0] : ''
+      },
+      set: function(value) {
+        this.processNestedData([value], this.settingsGroup.key, this.setting.key, this.data[this.setting.key])
+      }
+    }
   },
   methods: {
+    processNestedData(value, tab, inputName, childName) {
+      const updatedValue = { ...this.$store.state.settings.settings[tab][inputName], ...{ [childName]: value }}
+      this.updateSetting(updatedValue, tab, inputName)
+    },
     updateSetting(value, tab, input) {
       this.$store.dispatch('UpdateSettings', { tab, data: { [input]: value }})
     }
diff --git a/src/views/settings/components/Setting.vue b/src/views/settings/components/Setting.vue
index ad35b3ecb19d1c43bbac0edd7f9c999588de3c3a..e157b9b0e236b20ad9455187abca12106bcf9a81 100644
--- a/src/views/settings/components/Setting.vue
+++ b/src/views/settings/components/Setting.vue
@@ -51,7 +51,7 @@ export default {
   },
   methods: {
     compound(type) {
-      return ['map'].includes(type)
+      return ['map', 'keyword'].includes(type)
     },
     updateSetting(value, tab, input) {
       this.$store.dispatch('UpdateSettings', { tab, data: { [input]: value }})