diff --git a/package.json b/package.json
index 3c7113141d0d61f47f3209a36f0e55d5b169bf96..6878f1e8e52ef95eba50e3f0ba5364afbd79aa2b 100644
--- a/package.json
+++ b/package.json
@@ -77,7 +77,7 @@
     "react-scroll": "^1.8.2",
     "react-tippy": "^1.4.0",
     "redux": "^4.1.0",
-    "revolt.js": "4.3.3-alpha.1",
+    "revolt.js": "4.3.3-alpha.2",
     "rimraf": "^3.0.2",
     "sass": "^1.35.1",
     "shade-blend-color": "^1.0.0",
diff --git a/src/components/navigation/left/ServerSidebar.tsx b/src/components/navigation/left/ServerSidebar.tsx
index d987af1eef083561a8dc40347e2636a6ab098d47..2b8bcb77876b9ea90f02b85a13abb4cbc8d6b431 100644
--- a/src/components/navigation/left/ServerSidebar.tsx
+++ b/src/components/navigation/left/ServerSidebar.tsx
@@ -1,14 +1,10 @@
-import { Link } from "react-router-dom";
-import { Settings } from "@styled-icons/feather";
 import { Redirect, useParams } from "react-router";
 import { ChannelButton } from "../items/ButtonItem";
 import { Channels } from "revolt.js/dist/api/objects";
-import { ServerPermission } from "revolt.js/dist/api/permissions";
 import { Unreads } from "../../../redux/reducers/unreads";
 import { WithDispatcher } from "../../../redux/reducers";
-import { useChannels, useForceUpdate, useServer, useServerPermission } from "../../../context/revoltjs/hooks";
+import { useChannels, useForceUpdate, useServer } from "../../../context/revoltjs/hooks";
 import { mapChannelWithUnread, useUnreads } from "./common";
-import Header from '../../ui/Header';
 import ConnectionStatus from '../items/ConnectionStatus';
 import { connectState } from "../../../redux/connector";
 import PaintCounter from "../../../lib/PaintCounter";
@@ -16,6 +12,7 @@ import styled from "styled-components";
 import { attachContextMenu } from 'preact-context-menu';
 import ServerHeader from "../../common/ServerHeader";
 import { useEffect } from "preact/hooks";
+import Category from "../../ui/Category";
 import ConditionalLink from "../../../lib/ConditionalLink";
 
 interface Props {
@@ -66,26 +63,48 @@ function ServerSidebar(props: Props & WithDispatcher) {
         });
     }, [ channel_id ]);
 
+    let uncategorised = new Set(server.channels);
+    let elements = [];
+    function addChannel(id: string) {
+        const entry = channels.find(x => x._id === id);
+        if (!entry) return;
+
+        const active = channel?._id === entry._id;
+
+        return (
+            <ConditionalLink active={active} to={`/server/${server!._id}/channel/${entry._id}`}>
+                <ChannelButton
+                    key={entry._id}
+                    channel={entry}
+                    active={active}
+                    alert={entry.unread}
+                    compact
+                />
+            </ConditionalLink>
+        );
+    }
+
+    if (server.categories) {
+        for (let category of server.categories) {
+            elements.push(<Category text={category.title} />);
+
+            for (let id of category.channels) {
+                uncategorised.delete(id);
+                elements.push(addChannel(id));
+            }
+        }
+    }
+
+    for (let id of uncategorised) {
+        elements.unshift(addChannel(id));
+    }
+
     return (
         <ServerBase>
             <ServerHeader server={server} ctx={ctx} />
             <ConnectionStatus />
             <ServerList onContextMenu={attachContextMenu('Menu', { server_list: server._id })}>
-                {channels.map(entry => {
-                    const active = channel?._id === entry._id;
-
-                    return (
-                        <ConditionalLink active={active} to={`/server/${server._id}/channel/${entry._id}`}>
-                            <ChannelButton
-                                key={entry._id}
-                                channel={entry}
-                                active={active}
-                                alert={entry.unread}
-                                compact
-                            />
-                        </ConditionalLink>
-                    );
-                })}
+                { elements }
             </ServerList>
             <PaintCounter small />
         </ServerBase>
diff --git a/yarn.lock b/yarn.lock
index 595a23ce5fe72c1019ed08c5c9680ea70b4f888c..fbe2cb2a8956c2452884215bb840d77015627e5d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3412,10 +3412,10 @@ reusify@^1.0.4:
   resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
   integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
 
-revolt.js@4.3.3-alpha.1:
-  version "4.3.3-alpha.1"
-  resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.1.tgz#b60a18e5cbe9f2c569e7f46974450931826e10d4"
-  integrity sha512-MxjTOWqg83cLYdpuqLCl3nOTD+jFxSSjrnvczuijam1YjeZ3IB27C6G4Qar3BwMn7B+zH8MgEDecW3YBmKBpIw==
+revolt.js@4.3.3-alpha.2:
+  version "4.3.3-alpha.2"
+  resolved "https://registry.yarnpkg.com/revolt.js/-/revolt.js-4.3.3-alpha.2.tgz#1fb876205d74712c45e5f022624ac8d176ab01a1"
+  integrity sha512-/irTDDtBj63yQtpBk1asnqCNacc+HQXcz0jBOBk1VaOeDsjE6lTO2tGue6wFAG76AL89z9bziQbHIa6cQmWIjg==
   dependencies:
     "@insertish/mutable" "1.1.0"
     axios "^0.19.2"