diff --git a/.github/workflows/meta.yml b/.github/workflows/meta.yml
index 5287c23..2ebc5a3 100644
--- a/.github/workflows/meta.yml
+++ b/.github/workflows/meta.yml
@@ -11,28 +11,28 @@ jobs:
         runs-on: ubuntu-latest
 
         steps:
-        - uses: actions/checkout@v3
-        - uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json
+            - uses: actions/checkout@v4
+            - uses: pnpm/action-setup@v4 # Install pnpm using packageManager key in package.json
 
-        - name: Use Node.js 18.18.2
-          uses: actions/setup-node@v3
-          with:
-              node-version: 18.18.2
+            - name: Use Node.js 20
+              uses: actions/setup-node@v4
+              with:
+                  node-version: 20
 
-        - name: Install dependencies
-          run: pnpm i
+            - name: Install dependencies
+              run: pnpm i
 
-        - name: Update metainfo
-          run: pnpm updateMeta
+            - name: Update metainfo
+              run: pnpm updateMeta
 
-        - name: Commit and merge in changes
-          run: |
-              git config user.name "github-actions[bot]"
-              git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
-              git checkout -b ci/meta-update
-              git add meta/dev.vencord.Vesktop.metainfo.xml
-              git commit -m "Insert release changes for ${{ github.event.release.tag_name }}"
-              git push origin ci/meta-update
-              gh pr create -B main -H ci/meta-update -t "Metainfo for ${{ github.event.release.tag_name }}" -b "This PR updates the metainfo for release ${{ github.event.release.tag_name }}. @lewisakura @Vendicated"
-          env:
-              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+            - name: Commit and merge in changes
+              run: |
+                  git config user.name "github-actions[bot]"
+                  git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
+                  git checkout -b ci/meta-update
+                  git add meta/dev.vencord.Vesktop.metainfo.xml
+                  git commit -m "Insert release changes for ${{ github.event.release.tag_name }}"
+                  git push origin ci/meta-update
+                  gh pr create -B main -H ci/meta-update -t "Metainfo for ${{ github.event.release.tag_name }}" -b "This PR updates the metainfo for release ${{ github.event.release.tag_name }}. @lewisakura @Vendicated"
+              env:
+                  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6968b73..9de1bc5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -22,13 +22,13 @@ jobs:
                       platform: windows
 
         steps:
-            - uses: actions/checkout@v3
-            - uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json
+            - uses: actions/checkout@v4
+            - uses: pnpm/action-setup@v4 # Install pnpm using packageManager key in package.json
 
-            - name: Use Node.js 18.18.2
-              uses: actions/setup-node@v3
+            - name: Use Node.js 20
+              uses: actions/setup-node@v4
               with:
-                  node-version: 18.18.2
+                  node-version: 20
                   cache: "pnpm"
 
             - name: Install dependencies
@@ -43,7 +43,7 @@ jobs:
                   pnpm electron-builder --${{ matrix.platform }} --publish always
               env:
                   GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-                  
+
             - name: Run Electron Builder
               if: ${{ matrix.platform == 'mac' }}
               run: |
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6d88280..daa62a5 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -11,13 +11,13 @@ jobs:
         runs-on: ubuntu-latest
 
         steps:
-            - uses: actions/checkout@v3
-            - uses: pnpm/action-setup@v2 # Install pnpm using packageManager key in package.json
+            - uses: actions/checkout@v4
+            - uses: pnpm/action-setup@v4 # Install pnpm using packageManager key in package.json
 
-            - name: Use Node.js 18.18.2
-              uses: actions/setup-node@v3
+            - name: Use Node.js 20
+              uses: actions/setup-node@v4
               with:
-                  node-version: 18.18.2
+                  node-version: 20
                   cache: "pnpm"
 
             - name: Install dependencies
diff --git a/meta/dev.vencord.Vesktop.metainfo.xml b/meta/dev.vencord.Vesktop.metainfo.xml
index 889b9fc..2c94c9e 100644
--- a/meta/dev.vencord.Vesktop.metainfo.xml
+++ b/meta/dev.vencord.Vesktop.metainfo.xml
@@ -182,7 +182,7 @@
   <url type="vcs-browser">https://github.com/Vencord/Vesktop</url>
   <categories>
     <category>InstantMessaging</category>
-    <category>AudioVideo</category>
+    <category>Network</category>
   </categories>
   <requires>
     <control>pointing</control>
@@ -208,4 +208,4 @@
     <keyword>Privacy</keyword>
     <keyword>Mod</keyword>
   </keywords>
-</component>
\ No newline at end of file
+</component>
diff --git a/package.json b/package.json
index 67571bd..7e45ce0 100644
--- a/package.json
+++ b/package.json
@@ -65,6 +65,7 @@
         "productName": "Vesktop",
         "files": [
             "!*",
+            "!node_modules",
             "dist/js",
             "static",
             "package.json",
@@ -118,8 +119,7 @@
                 {
                     "target": "default",
                     "arch": [
-                        "x64",
-                        "arm64"
+                        "universal"
                     ]
                 }
             ],
@@ -158,8 +158,20 @@
         },
         "win": {
             "target": [
-                "nsis",
-                "zip"
+                {
+                    "target": "nsis",
+                    "arch": [
+                        "x64",
+                        "arm64"
+                    ]
+                },
+                {
+                    "target": "zip",
+                    "arch": [
+                        "x64",
+                        "arm64"
+                    ]
+                }
             ]
         },
         "publish": {
diff --git a/src/main/constants.ts b/src/main/constants.ts
index 1bce303..78f9187 100644
--- a/src/main/constants.ts
+++ b/src/main/constants.ts
@@ -37,7 +37,8 @@ if (existsSync(LEGACY_DATA_DIR)) {
         console.error("Migration failed", e);
     }
 }
-app.setPath("sessionData", join(DATA_DIR, "sessionData"));
+const SESSION_DATA_DIR = join(DATA_DIR, "sessionData");
+app.setPath("sessionData", SESSION_DATA_DIR);
 
 export const VENCORD_SETTINGS_DIR = join(DATA_DIR, "settings");
 export const VENCORD_QUICKCSS_FILE = join(VENCORD_SETTINGS_DIR, "quickCss.css");
@@ -47,7 +48,8 @@ export const VENCORD_THEMES_DIR = join(DATA_DIR, "themes");
 // needs to be inline require because of circular dependency
 // as otherwise "DATA_DIR" (which is used by ./settings) will be uninitialised
 export const VENCORD_FILES_DIR =
-    (require("./settings") as typeof import("./settings")).Settings.store.vencordDir || join(DATA_DIR, "vencordDist");
+    (require("./settings") as typeof import("./settings")).State.store.vencordDir ||
+    join(SESSION_DATA_DIR, "vencordFiles");
 
 export const USER_AGENT = `Vesktop/${app.getVersion()} (https://github.com/Vencord/Vesktop)`;
 
diff --git a/src/main/ipc.ts b/src/main/ipc.ts
index 3404d34..4fa662c 100644
--- a/src/main/ipc.ts
+++ b/src/main/ipc.ts
@@ -19,7 +19,7 @@ import { setBadgeCount } from "./appBadge";
 import { autoStart } from "./autoStart";
 import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants";
 import { mainWin } from "./mainWindow";
-import { Settings } from "./settings";
+import { Settings, State } from "./settings";
 import { handle, handleSync } from "./utils/ipcWrappers";
 import { PopoutWindows } from "./utils/popout";
 import { isDeckGameMode, showGamePage } from "./utils/steamOS";
@@ -105,7 +105,14 @@ handle(IpcEvents.SPELLCHECK_ADD_TO_DICTIONARY, (e, word: string) => {
     e.sender.session.addWordToSpellCheckerDictionary(word);
 });
 
-handle(IpcEvents.SELECT_VENCORD_DIR, async () => {
+handleSync(IpcEvents.GET_VENCORD_DIR, e => (e.returnValue = State.store.vencordDir));
+
+handle(IpcEvents.SELECT_VENCORD_DIR, async (_e, value?: null) => {
+    if (value === null) {
+        delete State.store.vencordDir;
+        return "ok";
+    }
+
     const res = await dialog.showOpenDialog(mainWin!, {
         properties: ["openDirectory"]
     });
@@ -114,7 +121,9 @@ handle(IpcEvents.SELECT_VENCORD_DIR, async () => {
     const dir = res.filePaths[0];
     if (!isValidVencordInstall(dir)) return "invalid";
 
-    return dir;
+    State.store.vencordDir = dir;
+
+    return "ok";
 });
 
 handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count));
diff --git a/src/main/utils/vencordLoader.ts b/src/main/utils/vencordLoader.ts
index 1bac37a..c0bac6a 100644
--- a/src/main/utils/vencordLoader.ts
+++ b/src/main/utils/vencordLoader.ts
@@ -4,7 +4,8 @@
  * Copyright (c) 2023 Vendicated and Vencord contributors
  */
 
-import { existsSync, mkdirSync } from "fs";
+import { mkdirSync } from "fs";
+import { access, constants as FsConstants } from "fs/promises";
 import { join } from "path";
 
 import { USER_AGENT, VENCORD_FILES_DIR } from "../constants";
@@ -56,12 +57,18 @@ export async function downloadVencordFiles() {
     );
 }
 
-export function isValidVencordInstall(dir: string) {
-    return FILES_TO_DOWNLOAD.every(f => existsSync(join(dir, f)));
+const existsAsync = (path: string) =>
+    access(path, FsConstants.F_OK)
+        .then(() => true)
+        .catch(() => false);
+
+export async function isValidVencordInstall(dir: string) {
+    return Promise.all(FILES_TO_DOWNLOAD.map(f => existsAsync(join(dir, f)))).then(arr => !arr.includes(false));
 }
 
 export async function ensureVencordFiles() {
-    if (isValidVencordInstall(VENCORD_FILES_DIR)) return;
+    if (await isValidVencordInstall(VENCORD_FILES_DIR)) return;
+
     mkdirSync(VENCORD_FILES_DIR, { recursive: true });
 
     await downloadVencordFiles();
diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts
index c8fc13f..7a8b977 100644
--- a/src/preload/VesktopNative.ts
+++ b/src/preload/VesktopNative.ts
@@ -7,7 +7,6 @@
 import { Node } from "@vencord/venmic";
 import { ipcRenderer } from "electron";
 import type { Settings } from "shared/settings";
-import type { LiteralUnion } from "type-fest";
 
 import { IpcEvents } from "../shared/IpcEvents";
 import { invoke, sendSync } from "./typedIpc";
@@ -34,7 +33,8 @@ export const VesktopNative = {
     },
     fileManager: {
         showItemInFolder: (path: string) => invoke<void>(IpcEvents.SHOW_ITEM_IN_FOLDER, path),
-        selectVencordDir: () => invoke<LiteralUnion<"cancelled" | "invalid", string>>(IpcEvents.SELECT_VENCORD_DIR)
+        getVencordDir: () => sendSync<string | undefined>(IpcEvents.GET_VENCORD_DIR),
+        selectVencordDir: (value?: null) => invoke<"cancelled" | "invalid" | "ok">(IpcEvents.SELECT_VENCORD_DIR, value)
     },
     settings: {
         get: () => sendSync<Settings>(IpcEvents.GET_SETTINGS),
diff --git a/src/renderer/components/ScreenSharePicker.tsx b/src/renderer/components/ScreenSharePicker.tsx
index e0cff77..c7403b9 100644
--- a/src/renderer/components/ScreenSharePicker.tsx
+++ b/src/renderer/components/ScreenSharePicker.tsx
@@ -721,7 +721,7 @@ function ModalComponent({
 
                                 const constraints = {
                                     ...track.getConstraints(),
-                                    frameRate,
+                                    frameRate: { min: frameRate, ideal: frameRate },
                                     width: { min: 640, ideal: width, max: width },
                                     height: { min: 480, ideal: height, max: height },
                                     advanced: [{ width: width, height: height }],
diff --git a/src/renderer/components/settings/VencordLocationPicker.tsx b/src/renderer/components/settings/VencordLocationPicker.tsx
index 3759ae2..9af4711 100644
--- a/src/renderer/components/settings/VencordLocationPicker.tsx
+++ b/src/renderer/components/settings/VencordLocationPicker.tsx
@@ -4,24 +4,28 @@
  * Copyright (c) 2023 Vendicated and Vencord contributors
  */
 
+import { useForceUpdater } from "@vencord/types/utils";
 import { Button, Forms, Toasts } from "@vencord/types/webpack/common";
 
 import { SettingsComponent } from "./Settings";
 
 export const VencordLocationPicker: SettingsComponent = ({ settings }) => {
+    const forceUpdate = useForceUpdater();
+    const vencordDir = VesktopNative.fileManager.getVencordDir();
+
     return (
         <>
             <Forms.FormText>
                 Vencord files are loaded from{" "}
-                {settings.vencordDir ? (
+                {vencordDir ? (
                     <a
                         href="about:blank"
                         onClick={e => {
                             e.preventDefault();
-                            VesktopNative.fileManager.showItemInFolder(settings.vencordDir!);
+                            VesktopNative.fileManager.showItemInFolder(vencordDir!);
                         }}
                     >
-                        {settings.vencordDir}
+                        {vencordDir}
                     </a>
                 ) : (
                     "the default location"
@@ -34,7 +38,14 @@ export const VencordLocationPicker: SettingsComponent = ({ settings }) => {
                         const choice = await VesktopNative.fileManager.selectVencordDir();
                         switch (choice) {
                             case "cancelled":
-                                return;
+                                break;
+                            case "ok":
+                                Toasts.show({
+                                    message: "Vencord install changed. Fully restart Vesktop to apply.",
+                                    id: Toasts.genId(),
+                                    type: Toasts.Type.SUCCESS
+                                });
+                                break;
                             case "invalid":
                                 Toasts.show({
                                     message:
@@ -42,9 +53,9 @@ export const VencordLocationPicker: SettingsComponent = ({ settings }) => {
                                     id: Toasts.genId(),
                                     type: Toasts.Type.FAILURE
                                 });
-                                return;
+                                break;
                         }
-                        settings.vencordDir = choice;
+                        forceUpdate();
                     }}
                 >
                     Change
@@ -52,7 +63,10 @@ export const VencordLocationPicker: SettingsComponent = ({ settings }) => {
                 <Button
                     size={Button.Sizes.SMALL}
                     color={Button.Colors.RED}
-                    onClick={() => (settings.vencordDir = void 0)}
+                    onClick={async () => {
+                        await VesktopNative.fileManager.selectVencordDir(null);
+                        forceUpdate();
+                    }}
                 >
                     Reset
                 </Button>
diff --git a/src/renderer/index.ts b/src/renderer/index.ts
index 99dca25..e8ad31c 100644
--- a/src/renderer/index.ts
+++ b/src/renderer/index.ts
@@ -13,7 +13,7 @@ console.log("read if cute :3");
 
 export * as Components from "./components";
 import { findByPropsLazy, onceReady } from "@vencord/types/webpack";
-import { FluxDispatcher } from "@vencord/types/webpack/common";
+import { Alerts, FluxDispatcher } from "@vencord/types/webpack/common";
 
 import SettingsUi from "./components/settings/Settings";
 import { Settings } from "./settings";
@@ -59,3 +59,19 @@ VesktopNative.arrpc.onActivity(async data => {
 
     arRPC.handleEvent(new MessageEvent("message", { data }));
 });
+
+// TODO: remove soon
+const vencordDir = "vencordDir" as keyof typeof Settings.store;
+if (Settings.store[vencordDir]) {
+    onceReady.then(() =>
+        setTimeout(
+            () =>
+                Alerts.show({
+                    title: "Custom Vencord Location",
+                    body: "Due to security hardening changes in Vesktop, your custom Vencord location had to be reset. Please configure it again in the settings.",
+                    onConfirm: () => delete Settings.store[vencordDir]
+                }),
+            5000
+        )
+    );
+}
diff --git a/src/renderer/patches/screenShareFixes.ts b/src/renderer/patches/screenShareFixes.ts
index 66e4b14..00487d3 100644
--- a/src/renderer/patches/screenShareFixes.ts
+++ b/src/renderer/patches/screenShareFixes.ts
@@ -36,7 +36,7 @@ if (isLinux) {
 
         const constraints = {
             ...track.getConstraints(),
-            frameRate,
+            frameRate: { min: frameRate, ideal: frameRate },
             width: { min: 640, ideal: width, max: width },
             height: { min: 480, ideal: height, max: height },
             advanced: [{ width: width, height: height }],
diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts
index ea632fb..51d2a28 100644
--- a/src/shared/IpcEvents.ts
+++ b/src/shared/IpcEvents.ts
@@ -23,6 +23,7 @@ export const enum IpcEvents {
     GET_SETTINGS = "VCD_GET_SETTINGS",
     SET_SETTINGS = "VCD_SET_SETTINGS",
 
+    GET_VENCORD_DIR = "VCD_GET_VENCORD_DIR",
     SELECT_VENCORD_DIR = "VCD_SELECT_VENCORD_DIR",
 
     UPDATER_GET_DATA = "VCD_UPDATER_GET_DATA",
diff --git a/src/shared/settings.d.ts b/src/shared/settings.d.ts
index 3eb96a0..ae19668 100644
--- a/src/shared/settings.d.ts
+++ b/src/shared/settings.d.ts
@@ -8,7 +8,6 @@ import type { Rectangle } from "electron";
 
 export interface Settings {
     discordBranch?: "stable" | "canary" | "ptb";
-    vencordDir?: string;
     transparencyOption?: "none" | "mica" | "tabbed" | "acrylic";
     tray?: boolean;
     minimizeToTray?: boolean;
@@ -54,4 +53,6 @@ export interface State {
     firstLaunch?: boolean;
 
     steamOSLayoutVersion?: number;
+
+    vencordDir?: string;
 }
diff --git a/src/shared/utils/SettingsStore.ts b/src/shared/utils/SettingsStore.ts
index 22dd145..6aa7771 100644
--- a/src/shared/utils/SettingsStore.ts
+++ b/src/shared/utils/SettingsStore.ts
@@ -59,6 +59,19 @@ export class SettingsStore<T extends object> {
                 self.pathListeners.get(setPath)?.forEach(cb => cb(value));
 
                 return true;
+            },
+            deleteProperty(target, key: string) {
+                if (!(key in target)) return true;
+
+                const res = Reflect.deleteProperty(target, key);
+                if (!res) return false;
+
+                const setPath = `${path}${path && "."}${key}`;
+
+                self.globalListeners.forEach(cb => cb(root, setPath));
+                self.pathListeners.get(setPath)?.forEach(cb => cb(undefined));
+
+                return res;
             }
         });
     }