diff --git a/loader/include/Geode/ui/MDTextArea.hpp b/loader/include/Geode/ui/MDTextArea.hpp
index 82b62697..86937af3 100644
--- a/loader/include/Geode/ui/MDTextArea.hpp
+++ b/loader/include/Geode/ui/MDTextArea.hpp
@@ -26,7 +26,7 @@ namespace geode {
      *  - Lists
      * 
      * Note that links also have some special protocols.
-     * Use `user:<id>` or `user:<name>` to link to a GD
+     * Use `user:<accountID>` to link to a GD
      * account; `level:<id>` to link to a GD level and
      * `mod:<id>` to link to another Geode mod.
      */
@@ -48,6 +48,8 @@ namespace geode {
 
         void onLink(CCObject*);
         void onGDProfile(CCObject*);
+        void onGDLevel(CCObject*);
+        void onGeodeMod(CCObject*);
         void FLAlert_Clicked(FLAlertLayer*, bool btn) override;
 
         friend struct ::MDParser;
diff --git a/loader/src/ui/internal/GeodeUI.cpp b/loader/src/ui/internal/GeodeUI.cpp
index a0cd1ccf..ad584ca4 100644
--- a/loader/src/ui/internal/GeodeUI.cpp
+++ b/loader/src/ui/internal/GeodeUI.cpp
@@ -1,4 +1,3 @@
-
 #include "info/ModInfoPopup.hpp"
 #include "list/ModListLayer.hpp"
 #include "settings/ModSettingsPopup.hpp"
diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp
index 8e9740e1..131620c6 100644
--- a/loader/src/ui/internal/info/ModInfoPopup.cpp
+++ b/loader/src/ui/internal/info/ModInfoPopup.cpp
@@ -606,7 +606,8 @@ IndexItemInfoPopup::IndexItemInfoPopup()
 
 bool IndexItemInfoPopup::init(IndexItemHandle item, ModListLayer* list) {
     m_item = item;
-    m_installListener.setFilter(m_item->getMetadata().getID());
+    auto metadata = m_item->getMetadata();
+    m_installListener.setFilter(metadata.getID());
 
     auto winSize = CCDirector::sharedDirector()->getWinSize();
 
diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp
index 1d9228c2..e2470daf 100644
--- a/loader/src/ui/nodes/MDTextArea.cpp
+++ b/loader/src/ui/nodes/MDTextArea.cpp
@@ -1,6 +1,10 @@
 #include <Geode/binding/ProfilePage.hpp>
+#include <Geode/binding/LevelTools.hpp>
+#include <Geode/binding/LevelInfoLayer.hpp>
 #include <Geode/binding/CCContentLayer.hpp>
 #include <Geode/loader/Mod.hpp>
+#include <Geode/loader/Loader.hpp>
+#include <Geode/loader/Index.hpp>
 #include <Geode/ui/MDTextArea.hpp>
 #include <Geode/utils/casts.hpp>
 #include <Geode/utils/cocos.hpp>
@@ -10,6 +14,7 @@
 #include <md4c.h>
 #include <charconv>
 #include <Geode/loader/Log.hpp>
+#include "../internal/info/ModInfoPopup.hpp"
 
 using namespace geode::prelude;
 
@@ -192,7 +197,7 @@ void MDTextArea::onGDProfile(CCObject* pSender) {
             "Error",
             "Invalid profile ID: <cr>" + profile +
                 "</c>. This is "
-                "probably the modder's fault, report the bug to them.",
+                "probably the mod developer's fault, report the bug to them.",
             "OK"
         )
             ->show();
@@ -201,6 +206,67 @@ void MDTextArea::onGDProfile(CCObject* pSender) {
     ProfilePage::create(id, false)->show();
 }
 
+void MDTextArea::onGDLevel(CCObject* pSender) {
+    auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject());
+    auto level = std::string(href->getCString());
+    level = level.substr(level.find(":") + 1);
+    int id = 0;
+    auto res = std::from_chars(level.data(), level.data() + level.size(), id);
+    if (res.ec != std::errc()) {
+        FLAlertLayer::create(
+            "Error",
+            "Invalid level ID: <cr>" + level +
+                "</c>. This is "
+                "probably the mod developers's fault, report the bug to them.",
+            "OK"
+        )
+            ->show();
+        return;
+    }
+    auto searchObject = GJSearchObject::create(SearchType::Type19, fmt::format("{}&gameVersion=22", id));
+    auto scene = LevelBrowserLayer::scene(searchObject);
+    CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.5f, scene));
+}
+
+void MDTextArea::onGeodeMod(CCObject* pSender) {
+    auto href = as<CCString*>(as<CCNode*>(pSender)->getUserObject());
+    auto modString = std::string(href->getCString());
+    modString = modString.substr(modString.find(":") + 1);
+    auto loader = Loader::get();
+    auto index = Index::get();
+    Mod* mod;
+    bool success = false;
+    IndexItemHandle indexItem;
+    bool isIndexMod = !loader->isModInstalled(modString);
+
+    if (isIndexMod) {
+        auto indexSearch = index->getItemsByModID(modString);
+        if (indexSearch.size() != 0) {
+            indexItem = indexSearch.back();
+            Mod mod2 = Mod(indexItem->getMetadata());
+            mod = &mod2;
+            auto item = Index::get()->getItem(mod);
+            IndexItemInfoPopup::create(item, nullptr)->show();
+            success = true;
+        }
+    } else {
+        mod = loader->getLoadedMod(modString);
+        LocalModInfoPopup::create(mod, nullptr)->show();
+        success = true;
+    }
+
+    if (!success) {
+        FLAlertLayer::create(
+            "Error",
+            "Invalid mod ID: <cr>" + modString +
+                "</c>. This is "
+                "probably the mod developers's fault, report the bug to them.",
+            "OK"
+        )
+            ->show();
+    }
+}
+
 void MDTextArea::FLAlert_Clicked(FLAlertLayer* layer, bool btn) {
     if (btn) {
         web::openLinkInBrowser(as<CCString*>(layer->getUserObject())->getCString());
@@ -256,7 +322,11 @@ struct MDParser {
                             text, textarea,
                             utils::string::startsWith(s_lastLink, "user:")
                                 ? menu_selector(MDTextArea::onGDProfile)
-                                : menu_selector(MDTextArea::onLink)
+                                : utils::string::startsWith(s_lastLink, "level:")
+                                    ? menu_selector(MDTextArea::onGDLevel)
+                                    : utils::string::startsWith(s_lastLink, "mod:")
+                                        ? menu_selector(MDTextArea::onGeodeMod)
+                                        : menu_selector(MDTextArea::onLink)
                         );
                         for (auto const& label : rendered) {
                             label.m_node->setUserObject(CCString::create(s_lastLink));