diff --git a/packages/builder/src/stores/portal/oidc.js b/packages/builder/src/stores/portal/oidc.js
deleted file mode 100644
index 65d8eac04ca..00000000000
--- a/packages/builder/src/stores/portal/oidc.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { writable, get } from "svelte/store"
-import { API } from "@/api"
-import { auth } from "@/stores/portal"
-
-const OIDC_CONFIG = {
-  logo: undefined,
-  name: undefined,
-  uuid: undefined,
-}
-
-export function createOidcStore() {
-  const store = writable(OIDC_CONFIG)
-  const { set, subscribe } = store
-  return {
-    subscribe,
-    set,
-    init: async () => {
-      const tenantId = get(auth).tenantId
-      const config = await API.getOIDCConfig(tenantId)
-      if (Object.keys(config || {}).length) {
-        // Just use the first config for now.
-        // We will be support multiple logins buttons later on.
-        set(...config)
-      } else {
-        set(OIDC_CONFIG)
-      }
-    },
-  }
-}
-
-export const oidc = createOidcStore()
diff --git a/packages/builder/src/stores/portal/oidc.ts b/packages/builder/src/stores/portal/oidc.ts
new file mode 100644
index 00000000000..6c3609f9d5e
--- /dev/null
+++ b/packages/builder/src/stores/portal/oidc.ts
@@ -0,0 +1,21 @@
+import { get } from "svelte/store"
+import { API } from "@/api"
+import { auth } from "@/stores/portal"
+import { BudiStore } from "../BudiStore"
+import { PublicOIDCConfig } from "@budibase/types"
+
+class OIDCStore extends BudiStore<PublicOIDCConfig> {
+  constructor() {
+    super({})
+  }
+
+  async init() {
+    const tenantId = get(auth).tenantId
+    const configs = await API.getOIDCConfigs(tenantId)
+    // Just use the first config for now.
+    // We will be support multiple logins buttons later on.
+    this.set(configs[0] || {})
+  }
+}
+
+export const oidc = new OIDCStore()
diff --git a/packages/builder/src/stores/portal/organisation.js b/packages/builder/src/stores/portal/organisation.js
deleted file mode 100644
index 6d41620c9fd..00000000000
--- a/packages/builder/src/stores/portal/organisation.js
+++ /dev/null
@@ -1,66 +0,0 @@
-import { writable, get } from "svelte/store"
-import { API } from "@/api"
-import { auth } from "@/stores/portal"
-import _ from "lodash"
-
-const DEFAULT_CONFIG = {
-  platformUrl: "",
-  logoUrl: undefined,
-  faviconUrl: undefined,
-  emailBrandingEnabled: true,
-  testimonialsEnabled: true,
-  platformTitle: "Budibase",
-  loginHeading: undefined,
-  loginButton: undefined,
-  metaDescription: undefined,
-  metaImageUrl: undefined,
-  metaTitle: undefined,
-  docsUrl: undefined,
-  company: "Budibase",
-  oidc: undefined,
-  google: undefined,
-  googleDatasourceConfigured: undefined,
-  oidcCallbackUrl: "",
-  googleCallbackUrl: "",
-  isSSOEnforced: false,
-  loaded: false,
-}
-
-export function createOrganisationStore() {
-  const store = writable(DEFAULT_CONFIG)
-  const { subscribe, set } = store
-
-  async function init() {
-    const tenantId = get(auth).tenantId
-    const settingsConfigDoc = await API.getTenantConfig(tenantId)
-    set({ ...DEFAULT_CONFIG, ...settingsConfigDoc.config, loaded: true })
-  }
-
-  async function save(config) {
-    // Delete non-persisted fields
-    const storeConfig = _.cloneDeep(get(store))
-    delete storeConfig.oidc
-    delete storeConfig.google
-    delete storeConfig.googleDatasourceConfigured
-    delete storeConfig.oidcCallbackUrl
-    delete storeConfig.googleCallbackUrl
-
-    // delete internal store field
-    delete storeConfig.loaded
-
-    await API.saveConfig({
-      type: "settings",
-      config: { ...storeConfig, ...config },
-    })
-    await init()
-  }
-
-  return {
-    subscribe,
-    set,
-    save,
-    init,
-  }
-}
-
-export const organisation = createOrganisationStore()
diff --git a/packages/builder/src/stores/portal/organisation.ts b/packages/builder/src/stores/portal/organisation.ts
new file mode 100644
index 00000000000..219245807ac
--- /dev/null
+++ b/packages/builder/src/stores/portal/organisation.ts
@@ -0,0 +1,71 @@
+import { get } from "svelte/store"
+import { API } from "@/api"
+import { auth } from "@/stores/portal"
+import {
+  ConfigType,
+  PublicSettingsInnerConfig,
+  SettingsBrandingConfig,
+  SettingsInnerConfig,
+} from "@budibase/types"
+import { BudiStore } from "../BudiStore"
+
+interface LocalOrganisationState {
+  loaded: boolean
+}
+
+type SavedOrganisationState = SettingsInnerConfig & SettingsBrandingConfig
+type OrganisationState = SavedOrganisationState &
+  PublicSettingsInnerConfig &
+  LocalOrganisationState
+
+const DEFAULT_STATE: OrganisationState = {
+  platformUrl: "",
+  emailBrandingEnabled: true,
+  testimonialsEnabled: true,
+  platformTitle: "Budibase",
+  company: "Budibase",
+  google: false,
+  googleDatasourceConfigured: false,
+  oidc: false,
+  oidcCallbackUrl: "",
+  googleCallbackUrl: "",
+  loaded: false,
+}
+
+class OrganisationStore extends BudiStore<OrganisationState> {
+  constructor() {
+    super(DEFAULT_STATE)
+  }
+
+  async init() {
+    const tenantId = get(auth).tenantId
+    const settingsConfigDoc = await API.getTenantConfig(tenantId)
+    this.set({ ...DEFAULT_STATE, ...settingsConfigDoc.config, loaded: true })
+  }
+
+  async save(changes: Partial<SavedOrganisationState>) {
+    // Strip non persisted fields
+    const {
+      oidc,
+      google,
+      googleDatasourceConfigured,
+      oidcCallbackUrl,
+      googleCallbackUrl,
+      loaded,
+      ...config
+    } = get(this.store)
+
+    // Save new config
+    const newConfig: SavedOrganisationState = {
+      ...config,
+      ...changes,
+    }
+    await API.saveConfig({
+      type: ConfigType.SETTINGS,
+      config: newConfig,
+    })
+    await this.init()
+  }
+}
+
+export const organisation = new OrganisationStore()
diff --git a/packages/frontend-core/src/api/configs.ts b/packages/frontend-core/src/api/configs.ts
index 82f08e58a79..408180a859d 100644
--- a/packages/frontend-core/src/api/configs.ts
+++ b/packages/frontend-core/src/api/configs.ts
@@ -16,7 +16,7 @@ import { BaseAPIClient } from "./types"
 export interface ConfigEndpoints {
   getConfig: (type: ConfigType) => Promise<FindConfigResponse>
   getTenantConfig: (tentantId: string) => Promise<GetPublicSettingsResponse>
-  getOIDCConfig: (tenantId: string) => Promise<GetPublicOIDCConfigResponse>
+  getOIDCConfigs: (tenantId: string) => Promise<GetPublicOIDCConfigResponse>
   getOIDCLogos: () => Promise<Config<OIDCLogosConfig>>
   saveConfig: (config: SaveConfigRequest) => Promise<SaveConfigResponse>
   deleteConfig: (id: string, rev: string) => Promise<DeleteConfigResponse>
@@ -73,7 +73,7 @@ export const buildConfigEndpoints = (API: BaseAPIClient): ConfigEndpoints => ({
    * Gets the OIDC config for a certain tenant.
    * @param tenantId the tenant ID to get the config for
    */
-  getOIDCConfig: async tenantId => {
+  getOIDCConfigs: async tenantId => {
     return await API.get({
       url: `/api/global/configs/public/oidc?tenantId=${tenantId}`,
     })
diff --git a/packages/types/src/documents/global/config.ts b/packages/types/src/documents/global/config.ts
index d51ca9d54df..1ad20e291fd 100644
--- a/packages/types/src/documents/global/config.ts
+++ b/packages/types/src/documents/global/config.ts
@@ -26,13 +26,11 @@ export interface SMTPConfig extends Config<SMTPInnerConfig> {}
 export interface SettingsBrandingConfig {
   faviconUrl?: string
   faviconUrlEtag?: string
-
   emailBrandingEnabled?: boolean
   testimonialsEnabled?: boolean
   platformTitle?: string
   loginHeading?: string
   loginButton?: string
-
   metaDescription?: string
   metaImageUrl?: string
   metaTitle?: string
@@ -42,6 +40,7 @@ export interface SettingsInnerConfig {
   platformUrl?: string
   company?: string
   logoUrl?: string // Populated on read
+  docsUrl?: string
   logoUrlEtag?: string
   uniqueTenantId?: string
   analyticsEnabled?: boolean