diff --git a/package.json b/package.json
index 86474dc24d124ca6cc0c75cf3dbf4fe667196a75..085cb0e94b14b8c492adf2cfe69a95e79428d54d 100644
--- a/package.json
+++ b/package.json
@@ -83,6 +83,7 @@
     "ulid": "^2.3.0",
     "use-resize-observer": "^7.0.0",
     "vite": "^2.3.7",
-    "vite-plugin-pwa": "^0.8.1"
+    "vite-plugin-pwa": "^0.8.1",
+    "workbox-precaching": "^6.1.5"
   }
 }
diff --git a/src/main.tsx b/src/main.tsx
index 5415f66af7dac497c0564d3e90728a15560bb669..99a9414d5e5b7773159e5b7d04f2ccbff4f340a3 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,9 +1,4 @@
-import { render } from "preact";
-import "./styles/index.scss";
-import { App } from "./pages/app";
-
 import { registerSW } from 'virtual:pwa-register'
-
 const updateSW = registerSW({
     onNeedRefresh() {
         // ! FIXME: temp
@@ -16,5 +11,9 @@ const updateSW = registerSW({
     },
 })
 
+import { render } from "preact";
+import "./styles/index.scss";
+import { App } from "./pages/app";
+
 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
 render(<App />, document.getElementById("app")!);
diff --git a/src/sw.ts b/src/sw.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f0f22383833fc03cd6ff265b9f169cb89e6c0959
--- /dev/null
+++ b/src/sw.ts
@@ -0,0 +1,11 @@
+/// <reference lib="webworker" />
+import { precacheAndRoute } from 'workbox-precaching'
+
+declare let self: ServiceWorkerGlobalScope
+
+self.addEventListener('message', (event) => {
+  if (event.data && event.data.type === 'SKIP_WAITING')
+    self.skipWaiting()
+})
+
+precacheAndRoute(self.__WB_MANIFEST)
diff --git a/tsconfig.json b/tsconfig.json
index cdda19f404b246fe5111e441afa82749e1350d19..8a7df58181d317e98d87f344771f24a964852d46 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,7 @@
 {
   "compilerOptions": {
     "target": "ESNext",
-    "lib": ["DOM", "DOM.Iterable", "ESNext"],
+    "lib": ["DOM", "DOM.Iterable", "ESNext", "WebWorker"],
     "allowJs": false,
     "skipLibCheck": true,
     "esModuleInterop": false,
diff --git a/vite.config.ts b/vite.config.ts
index dca74704954e7ca34a317a7cff0fbd9a5330af4e..8da84488a4093c26437151238d30ab576fce2c0e 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -23,9 +23,12 @@ export default defineConfig({
   plugins: [
     preact(),
     VitePWA({
+      srcDir: 'src',
+      filename: 'sw.ts',
+      strategies: 'injectManifest',
       manifest: {
-        name: "Revolt",
-        short_name: "Revolt",
+        name: "REVOLT",
+        short_name: "REVOLT",
         description: "User-first, privacy-focused chat platform.",
         categories: ["messaging"],
         start_url: "/",
@@ -44,8 +47,7 @@ export default defineConfig({
                 "sizes": "512x512"
             }
         ]
-      },
-      workbox: { }
+      }
     }),
     replace({
       __GIT_REVISION__: getGitRevision(),