diff --git a/package.json b/package.json
index b938f52..cc8b9c8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
     "name": "VencordDesktop",
-    "version": "0.1.4",
+    "version": "0.1.3",
     "private": true,
     "description": "",
     "keywords": [],
diff --git a/src/main/index.ts b/src/main/index.ts
index 68c8972..c10ccb4 100644
--- a/src/main/index.ts
+++ b/src/main/index.ts
@@ -42,7 +42,6 @@ if (!app.requestSingleInstanceLock()) {
 
     app.whenReady().then(async () => {
         checkUpdates();
-
         if (process.platform === "win32") app.setAppUserModelId("dev.vencord.desktop");
         else if (process.platform === "darwin") app.dock.setIcon(ICON_PATH);
 
diff --git a/src/main/ipc.ts b/src/main/ipc.ts
index 81db39c..83c4d58 100644
--- a/src/main/ipc.ts
+++ b/src/main/ipc.ts
@@ -52,8 +52,12 @@ ipcMain.handle(IpcEvents.SHOW_ITEM_IN_FOLDER, (_, path) => {
     shell.showItemInFolder(path);
 });
 
-ipcMain.handle(IpcEvents.FOCUS, () => {
-    mainWin?.focus();
+ipcMain.handle(IpcEvents.FOCUS, e => {
+    e.sender.focus();
+});
+
+ipcMain.handle(IpcEvents.CLOSE, e => {
+    e.sender.close();
 });
 
 ipcMain.handle(IpcEvents.SELECT_VENCORD_DIR, async () => {
diff --git a/src/main/splash.ts b/src/main/splash.ts
index 6c21c6c..b158a58 100644
--- a/src/main/splash.ts
+++ b/src/main/splash.ts
@@ -6,18 +6,11 @@
 
 import { BrowserWindow } from "electron";
 import { join } from "path";
+import { SplashProps } from "shared/browserWinProperties";
 import { STATIC_DIR } from "shared/paths";
 
 export function createSplashWindow() {
-    const splash = new BrowserWindow({
-        transparent: true,
-        frame: false,
-        height: 350,
-        width: 300,
-        center: true,
-        resizable: false,
-        maximizable: false
-    });
+    const splash = new BrowserWindow(SplashProps);
 
     splash.loadFile(join(STATIC_DIR, "splash.html"));
 
diff --git a/src/preload/VencordDesktopNative.ts b/src/preload/VencordDesktopNative.ts
index 2daaa23..a4a23f4 100644
--- a/src/preload/VencordDesktopNative.ts
+++ b/src/preload/VencordDesktopNative.ts
@@ -4,19 +4,11 @@
  * Copyright (c) 2023 Vendicated and Vencord contributors
  */
 
-import { ipcRenderer } from "electron";
 import type { Settings } from "shared/settings";
 import type { LiteralUnion } from "type-fest";
 
 import { IpcEvents } from "../shared/IpcEvents";
-
-function invoke<T = any>(event: IpcEvents, ...args: any[]) {
-    return ipcRenderer.invoke(event, ...args) as Promise<T>;
-}
-
-function sendSync<T = any>(event: IpcEvents, ...args: any[]) {
-    return ipcRenderer.sendSync(event, ...args) as T;
-}
+import { invoke, sendSync } from "./typedIpcs";
 
 export const VencordDesktopNative = {
     app: {
diff --git a/src/preload/typedIpcs.ts b/src/preload/typedIpcs.ts
new file mode 100644
index 0000000..6522de6
--- /dev/null
+++ b/src/preload/typedIpcs.ts
@@ -0,0 +1,16 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0
+ * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience
+ * Copyright (c) 2023 Vendicated and Vencord contributors
+ */
+
+import { ipcRenderer } from "electron";
+import { IpcEvents } from "shared/IpcEvents";
+
+export function invoke<T = any>(event: IpcEvents, ...args: any[]) {
+    return ipcRenderer.invoke(event, ...args) as Promise<T>;
+}
+
+export function sendSync<T = any>(event: IpcEvents, ...args: any[]) {
+    return ipcRenderer.sendSync(event, ...args) as T;
+}
diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts
index 58bb316..efe095d 100644
--- a/src/shared/IpcEvents.ts
+++ b/src/shared/IpcEvents.ts
@@ -21,5 +21,8 @@ export const enum IpcEvents {
 
     SELECT_VENCORD_DIR = "VCD_SELECT_VENCORD_DIR",
 
-    UPDATER_GET_LATEST_VERSION = "VCD_UPDATER_GET_LATEST_VERSION"
+    UPDATER_GET_DATA = "VCD_UPDATER_GET_DATA",
+    UPDATER_DOWNLOAD = "VCD_UPDATER_DOWNLOAD",
+
+    CLOSE = "VCD_CLOSE"
 }
diff --git a/src/shared/browserWinProperties.ts b/src/shared/browserWinProperties.ts
new file mode 100644
index 0000000..a263db0
--- /dev/null
+++ b/src/shared/browserWinProperties.ts
@@ -0,0 +1,18 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0
+ * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience
+ * Copyright (c) 2023 Vendicated and Vencord contributors
+ */
+
+import type { BrowserWindowConstructorOptions } from "electron";
+
+export const SplashProps: BrowserWindowConstructorOptions = {
+    transparent: true,
+    frame: false,
+    height: 350,
+    width: 300,
+    center: true,
+    resizable: false,
+    maximizable: false,
+    alwaysOnTop: true
+};
diff --git a/src/updater/main.ts b/src/updater/main.ts
index 1a6da0e..1bed9dc 100644
--- a/src/updater/main.ts
+++ b/src/updater/main.ts
@@ -4,15 +4,39 @@
  * Copyright (c) 2023 Vendicated and Vencord contributors
  */
 
-import { app, BrowserWindow, ipcMain } from "electron";
+import { app, BrowserWindow, ipcMain, shell } from "electron";
 import { githubGet, ReleaseData } from "main/utils/vencordLoader";
 import { join } from "path";
+import { SplashProps } from "shared/browserWinProperties";
 import { IpcEvents } from "shared/IpcEvents";
 import { STATIC_DIR } from "shared/paths";
 
-let latestVersion: string;
+export interface UpdateData {
+    currentVersion: string;
+    latestVersion: string;
+    release: ReleaseData;
+}
 
-ipcMain.handle(IpcEvents.UPDATER_GET_LATEST_VERSION, () => latestVersion);
+let updateData: UpdateData;
+
+ipcMain.handle(IpcEvents.UPDATER_GET_DATA, () => updateData);
+ipcMain.handle(IpcEvents.UPDATER_DOWNLOAD, () => {
+    const { assets } = updateData.release;
+    const url = (() => {
+        switch (process.platform) {
+            case "win32":
+                return assets.find(a => a.name.endsWith(".exe"))!.browser_download_url;
+            case "darwin":
+                return assets.find(a => a.name.endsWith(".dmg"))!.browser_download_url;
+            case "linux":
+                return updateData.release.html_url;
+            default:
+                throw new Error(`Unsupported platform: ${process.platform}`);
+        }
+    })();
+
+    shell.openExternal(url);
+});
 
 function isOutdated(oldVersion: string, newVersion: string) {
     const oldParts = oldVersion.split(".");
@@ -36,15 +60,21 @@ function isOutdated(oldVersion: string, newVersion: string) {
 }
 
 export async function checkUpdates() {
-    if (IS_DEV) return;
-
+    // if (IS_DEV) return;
     try {
         const raw = await githubGet("/repos/Vencord/Desktop/releases/latest");
-        const { tag_name } = JSON.parse(raw.toString("utf-8")) as ReleaseData;
+        const data = JSON.parse(raw.toString("utf-8")) as ReleaseData;
 
         const oldVersion = app.getVersion();
-        const newVersion = (latestVersion = tag_name.replace(/^v/, ""));
-        if (isOutdated(oldVersion, newVersion)) openNewUpdateWindow();
+        const newVersion = data.tag_name.replace(/^v/, "");
+        if (isOutdated(oldVersion, newVersion)) {
+            updateData = {
+                currentVersion: oldVersion,
+                latestVersion: newVersion,
+                release: data
+            };
+            openNewUpdateWindow();
+        }
     } catch (e) {
         console.error("AppUpdater: Failed to check for updates\n", e);
     }
@@ -52,6 +82,7 @@ export async function checkUpdates() {
 
 function openNewUpdateWindow() {
     const win = new BrowserWindow({
+        ...SplashProps,
         webPreferences: {
             preload: join(__dirname, "updaterPreload.js")
         }
diff --git a/src/updater/preload.ts b/src/updater/preload.ts
index 88722d8..0b7b978 100644
--- a/src/updater/preload.ts
+++ b/src/updater/preload.ts
@@ -4,9 +4,17 @@
  * Copyright (c) 2023 Vendicated and Vencord contributors
  */
 
-import { contextBridge, ipcRenderer } from "electron";
+import { contextBridge } from "electron";
+import { invoke } from "preload/typedIpcs";
 import { IpcEvents } from "shared/IpcEvents";
 
+import type { UpdateData } from "./main";
+
 contextBridge.exposeInMainWorld("Updater", {
-    getLatestVersion: () => ipcRenderer.invoke(IpcEvents.UPDATER_GET_LATEST_VERSION)
+    getData: () => invoke<UpdateData>(IpcEvents.UPDATER_GET_DATA),
+    download: () => {
+        invoke<void>(IpcEvents.UPDATER_DOWNLOAD);
+        invoke<void>(IpcEvents.CLOSE);
+    },
+    close: () => invoke<void>(IpcEvents.CLOSE)
 });
diff --git a/static/updater.html b/static/updater.html
index 2b52a69..d574e8a 100644
--- a/static/updater.html
+++ b/static/updater.html
@@ -1,7 +1,80 @@
-<div>hi</div>
-<p></p>
+<head>
+    <style>
+        body {
+            font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell,
+                "Open Sans", "Helvetica Neue", sans-serif;
+            margin: 0;
+            padding: 0;
+            color: rgb(219, 222, 225);
+        }
+
+        .wrapper {
+            display: flex;
+            flex-direction: column;
+            justify-content: space-between;
+            box-sizing: border-box;
+            height: 100%;
+            background-color: hsl(223 6.7% 20.6%);
+            border-radius: 8px;
+            border: 1px solid hsl(220 6.5% 18%);
+            padding: 1em;
+        }
+
+        h1 {
+            text-align: center;
+        }
+
+        .buttons {
+            display: grid;
+            grid-template-columns: 1fr 1fr;
+            gap: 0.5em;
+        }
+
+        button {
+            cursor: pointer;
+            padding: 0.5em;
+            color: white;
+            border: none;
+            border-radius: 3px;
+            font-weight: bold;
+        }
+
+        button:hover,
+        button:active {
+            filter: brightness(0.9);
+        }
+
+        .green {
+            background-color: #248046;
+        }
+
+        .red {
+            background-color: #ed4245;
+        }
+    </style>
+</head>
+
+<body>
+    <div class="wrapper">
+        <section>
+            <h1>Update Available</h1>
+            <p>There's a new update for Vencord Desktop! Update now to get new fixes and features</p>
+            <p>
+                Current: <span id="current"></span>
+                <br />
+                Latest: <span id="latest"></span>
+            </p>
+        </section>
+
+        <section class="buttons">
+            <button class="green" onclick="Updater.download()">Download Update</button>
+            <button class="red" onclick="Updater.close()">Close</button>
+        </section>
+    </div>
+</body>
 
 <script type="module">
-    const version = await Updater.getLatestVersion();
-    document.querySelector("p").textContent = version;
+    const data = await Updater.getData();
+    document.getElementById("current").textContent = data.currentVersion;
+    document.getElementById("latest").textContent = data.latestVersion;
 </script>