diff --git a/lib/mk-types/default.nix b/lib/mk-types/default.nix
index abd74e61..fc397453 100644
--- a/lib/mk-types/default.nix
+++ b/lib/mk-types/default.nix
@@ -12,7 +12,7 @@ in
     pname = "${pname}-types";
     version = "0.0.0";
 
-    npmDepsHash = "sha256-8De8tRUKzRhD1jyx0anYNPMhxZyIr2nI45HdK6nb8jI=";
+    npmDepsHash = "sha256-3ll4Xd5F8ZH/7q/gOF0jgerM6QRk71d93XIwtDssfxU=";
 
     src = ./.;
     dontNpmBuild = true;
@@ -22,8 +22,7 @@ in
           ${concatMapStringsSep "\n" (p: "-g ${p.package.dev}/share/gir-1.0 \\") withGirNames}
           -g ${ts-for-gir-src}/girs \
           --ignoreVersionConflicts \
-          --package \
-          -e gjs -o ./types
+          -o ./types
     '';
 
     installPhase = ''
diff --git a/lib/mk-types/package-lock.json b/lib/mk-types/package-lock.json
index 47c396a2..50c53818 100644
--- a/lib/mk-types/package-lock.json
+++ b/lib/mk-types/package-lock.json
@@ -1,11 +1,11 @@
 {
-    "name": "third-party-types",
+    "name": "mk-types",
     "lockfileVersion": 3,
     "requires": true,
     "packages": {
         "": {
             "dependencies": {
-                "@ts-for-gir/cli": "^3.3.0"
+                "@ts-for-gir/cli": "4.0.0-beta.16"
             }
         },
         "node_modules/@babel/code-frame": {
@@ -107,29 +107,139 @@
                 "node": ">=4"
             }
         },
+        "node_modules/@gi.ts/parser": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/@gi.ts/parser/-/parser-2.0.0.tgz",
+            "integrity": "sha512-Tz5T+3Ep+qY7rfBnYMGdVraCCUf1CKkDfxNd2fggfHLzjI7u5Th8a/piPgj0001jDs5czI+Ec3peh+6gkKPmHw==",
+            "license": "MIT",
+            "dependencies": {
+                "fast-xml-parser": "^4.3.5"
+            },
+            "engines": {
+                "node": ">=12.0.0"
+            }
+        },
         "node_modules/@inquirer/figures": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.4.tgz",
-            "integrity": "sha512-R7Gsg6elpuqdn55fBH2y9oYzrU/yKrSmIsDX4ROT51vohrECFzTf2zw9BfUbOW8xjfmM2QbVoVYdTwhrtEKWSQ==",
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.6.tgz",
+            "integrity": "sha512-yfZzps3Cso2UbM7WlxKwZQh2Hs6plrbjs1QnzQDZhK2DgyCo6D8AaHps9olkNcUFlcYERMqU3uJSp1gmy3s/qQ==",
             "license": "MIT",
             "engines": {
                 "node": ">=18"
             }
         },
+        "node_modules/@isaacs/cliui": {
+            "version": "8.0.2",
+            "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+            "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+            "license": "ISC",
+            "dependencies": {
+                "string-width": "^5.1.2",
+                "string-width-cjs": "npm:string-width@^4.2.0",
+                "strip-ansi": "^7.0.1",
+                "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+                "wrap-ansi": "^8.1.0",
+                "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+            },
+            "engines": {
+                "node": ">=12"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+            "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+            "license": "MIT",
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+            "version": "6.2.1",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+            "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+            "license": "MIT",
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+            "version": "9.2.2",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+            "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+            "license": "MIT"
+        },
+        "node_modules/@isaacs/cliui/node_modules/string-width": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+            "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+            "license": "MIT",
+            "dependencies": {
+                "eastasianwidth": "^0.2.0",
+                "emoji-regex": "^9.2.2",
+                "strip-ansi": "^7.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+            "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+            "license": "MIT",
+            "dependencies": {
+                "ansi-regex": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+            }
+        },
+        "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+            "version": "8.1.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+            "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+            "license": "MIT",
+            "dependencies": {
+                "ansi-styles": "^6.1.0",
+                "string-width": "^5.0.1",
+                "strip-ansi": "^7.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+            }
+        },
         "node_modules/@ts-for-gir/cli": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/@ts-for-gir/cli/-/cli-3.3.0.tgz",
-            "integrity": "sha512-X8AhFhkEGzTakcXLbndiWxJuvdFceJrV71e+z/wy3xO5yKHL+fCqsq+Tw46RbZ8tquLqKPkh0TAUNZH6BLDR1A==",
+            "version": "4.0.0-beta.16",
+            "resolved": "https://registry.npmjs.org/@ts-for-gir/cli/-/cli-4.0.0-beta.16.tgz",
+            "integrity": "sha512-E5T6NOdmrkRw3b7SyaZco5g7udMcg8kbCNnxgASLQj7VC0cxiwxLi/z7ALYjmbB1W5xhuensauq1yh5rLUWAXA==",
             "license": "Apache-2.0",
             "dependencies": {
-                "@ts-for-gir/generator-base": "^3.3.0",
-                "@ts-for-gir/generator-html-doc": "^3.3.0",
-                "@ts-for-gir/generator-typescript": "^3.3.0",
-                "@ts-for-gir/lib": "^3.3.0",
+                "@gi.ts/parser": "^2.0.0",
+                "@ts-for-gir/generator-base": "^4.0.0-beta.16",
+                "@ts-for-gir/generator-html-doc": "^4.0.0-beta.16",
+                "@ts-for-gir/generator-typescript": "^4.0.0-beta.16",
+                "@ts-for-gir/lib": "^4.0.0-beta.16",
                 "colorette": "^2.0.20",
                 "cosmiconfig": "^9.0.0",
-                "inquirer": "^9.2.16",
-                "tiny-glob": "^0.2.9",
+                "glob": "^11.0.0",
+                "inquirer": "^9.3.6",
+                "prettier": "^3.3.3",
                 "yargs": "^17.7.2"
             },
             "bin": {
@@ -140,52 +250,55 @@
             }
         },
         "node_modules/@ts-for-gir/generator-base": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-base/-/generator-base-3.3.0.tgz",
-            "integrity": "sha512-EACUJCUcly03SE8fYa/WqToTqGNxHBrqdOLpgIjmmlRaoHkYnwYFKKcI5O0+EsFOS5r4WbtisRVRj3uMnTK9pw==",
+            "version": "4.0.0-beta.16",
+            "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-base/-/generator-base-4.0.0-beta.16.tgz",
+            "integrity": "sha512-qNahOOm2aRC5w6gqk5xjb0MvyxtYwhTFDvHwuWXEUJ+EoFeWSi95ZYkvivvowsoAiQ5W805FMXzJtt4P72O0Hw==",
             "license": "Apache-2.0",
             "dependencies": {
-                "@ts-for-gir/lib": "^3.3.0"
+                "@ts-for-gir/lib": "^4.0.0-beta.16"
             },
             "engines": {
                 "node": ">=18"
             }
         },
         "node_modules/@ts-for-gir/generator-html-doc": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-html-doc/-/generator-html-doc-3.3.0.tgz",
-            "integrity": "sha512-DAOb3mu8xHlgBqkms9soMUy2HHFqYIrv55eU3xzTej/ZJRArDmd5f8ziXYLMva+TeYgQFhZnTr9ksIvsaAhvZA==",
+            "version": "4.0.0-beta.16",
+            "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-html-doc/-/generator-html-doc-4.0.0-beta.16.tgz",
+            "integrity": "sha512-2gCEUuSsvbUEdcAcU1LKFWawC56TYg4CmHCswzDjwPeEpOrzq1tweoaW2muYTg3COcF58Jax5/TWnJ88TmFdyA==",
             "license": "Apache-2.0",
             "dependencies": {
-                "@ts-for-gir/generator-base": "^3.3.0",
-                "@ts-for-gir/lib": "^3.3.0"
+                "@ts-for-gir/generator-base": "^4.0.0-beta.16",
+                "@ts-for-gir/lib": "^4.0.0-beta.16"
             },
             "engines": {
                 "node": ">=18"
             }
         },
         "node_modules/@ts-for-gir/generator-typescript": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-typescript/-/generator-typescript-3.3.0.tgz",
-            "integrity": "sha512-kQl0eSarkb8/eWx9yA+G0ekQLXdUjBIvON1Gb6urCbGPz0EnvnqAu1CVh1nRie9E+lt2TO/YEThZj98KOzxXCg==",
+            "version": "4.0.0-beta.16",
+            "resolved": "https://registry.npmjs.org/@ts-for-gir/generator-typescript/-/generator-typescript-4.0.0-beta.16.tgz",
+            "integrity": "sha512-BHXqfaqH5yOXD9ckL6h8ZGn17U7SkajksS4/KuQCtAhURjpXT3xw7mKw5W3FObhvFSkiaonPkZwapRUgD8kZ6w==",
             "license": "Apache-2.0",
             "dependencies": {
-                "@ts-for-gir/generator-base": "^3.3.0",
-                "@ts-for-gir/lib": "^3.3.0"
+                "@ts-for-gir/generator-base": "^4.0.0-beta.16",
+                "@ts-for-gir/lib": "^4.0.0-beta.16",
+                "ejs": "^3.1.10",
+                "xml2js": "^0.6.2"
             },
             "engines": {
                 "node": ">=18"
             }
         },
         "node_modules/@ts-for-gir/lib": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/@ts-for-gir/lib/-/lib-3.3.0.tgz",
-            "integrity": "sha512-GMJmNHka/qUJTTH6eLLGTPEd1cm68gq6PjW6Qan6ohz1WIu3tj0aP++hCBkUkmzYLHSj88/oLVPdHMuO5EQmew==",
+            "version": "4.0.0-beta.16",
+            "resolved": "https://registry.npmjs.org/@ts-for-gir/lib/-/lib-4.0.0-beta.16.tgz",
+            "integrity": "sha512-6sFr4mHKoX+/4WT+dMpJ1EXnXSbx7lG6inQ2j6riVY0DkQu5y3ebaL3oUtpHi5twA54YWaOrP8NfFr3eg3Z3fA==",
             "license": "Apache-2.0",
             "dependencies": {
+                "@gi.ts/parser": "^2.0.0",
                 "colorette": "^2.0.20",
-                "ejs": "^3.1.9",
-                "fast-xml-parser": "^4.3.6",
+                "ejs": "^3.1.10",
+                "glob": "^11.0.0",
                 "lodash": "^4.17.21"
             },
             "engines": {
@@ -238,9 +351,9 @@
             "license": "Python-2.0"
         },
         "node_modules/async": {
-            "version": "3.2.5",
-            "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
-            "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==",
+            "version": "3.2.6",
+            "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+            "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
             "license": "MIT"
         },
         "node_modules/balanced-match": {
@@ -281,13 +394,12 @@
             }
         },
         "node_modules/brace-expansion": {
-            "version": "1.1.11",
-            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+            "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
             "license": "MIT",
             "dependencies": {
-                "balanced-match": "^1.0.0",
-                "concat-map": "0.0.1"
+                "balanced-match": "^1.0.0"
             }
         },
         "node_modules/buffer": {
@@ -474,6 +586,20 @@
                 }
             }
         },
+        "node_modules/cross-spawn": {
+            "version": "7.0.3",
+            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+            "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+            "license": "MIT",
+            "dependencies": {
+                "path-key": "^3.1.0",
+                "shebang-command": "^2.0.0",
+                "which": "^2.0.1"
+            },
+            "engines": {
+                "node": ">= 8"
+            }
+        },
         "node_modules/defaults": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
@@ -486,6 +612,12 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/eastasianwidth": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+            "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+            "license": "MIT"
+        },
         "node_modules/ejs": {
             "version": "3.1.10",
             "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
@@ -558,9 +690,9 @@
             }
         },
         "node_modules/fast-xml-parser": {
-            "version": "4.4.0",
-            "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.0.tgz",
-            "integrity": "sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==",
+            "version": "4.5.0",
+            "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz",
+            "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==",
             "funding": [
                 {
                     "type": "github",
@@ -588,15 +720,6 @@
                 "minimatch": "^5.0.1"
             }
         },
-        "node_modules/filelist/node_modules/brace-expansion": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-            "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-            "license": "MIT",
-            "dependencies": {
-                "balanced-match": "^1.0.0"
-            }
-        },
         "node_modules/filelist/node_modules/minimatch": {
             "version": "5.1.6",
             "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
@@ -609,6 +732,22 @@
                 "node": ">=10"
             }
         },
+        "node_modules/foreground-child": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+            "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+            "license": "ISC",
+            "dependencies": {
+                "cross-spawn": "^7.0.0",
+                "signal-exit": "^4.0.1"
+            },
+            "engines": {
+                "node": ">=14"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/get-caller-file": {
             "version": "2.0.5",
             "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -618,17 +757,28 @@
                 "node": "6.* || 8.* || >= 10.*"
             }
         },
-        "node_modules/globalyzer": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
-            "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
-            "license": "MIT"
-        },
-        "node_modules/globrex": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
-            "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
-            "license": "MIT"
+        "node_modules/glob": {
+            "version": "11.0.0",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
+            "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
+            "license": "ISC",
+            "dependencies": {
+                "foreground-child": "^3.1.0",
+                "jackspeak": "^4.0.1",
+                "minimatch": "^10.0.0",
+                "minipass": "^7.1.2",
+                "package-json-from-dist": "^1.0.0",
+                "path-scurry": "^2.0.0"
+            },
+            "bin": {
+                "glob": "dist/esm/bin.mjs"
+            },
+            "engines": {
+                "node": "20 || >=22"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
         },
         "node_modules/has-flag": {
             "version": "4.0.0",
@@ -694,9 +844,9 @@
             "license": "ISC"
         },
         "node_modules/inquirer": {
-            "version": "9.3.5",
-            "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.5.tgz",
-            "integrity": "sha512-SVRCRovA7KaT6nqWB2mCNpTvU4cuZ0hOXo5KPyiyOcNNUIZwq/JKtvXuDJNaxfuJKabBYRu1ecHze0YEwDYoRQ==",
+            "version": "9.3.7",
+            "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.7.tgz",
+            "integrity": "sha512-LJKFHCSeIRq9hanN14IlOtPSTe3lNES7TYDTE2xxdAy1LS5rYphajK1qtwvj3YmQXvvk0U2Vbmcni8P9EIQW9w==",
             "license": "MIT",
             "dependencies": {
                 "@inquirer/figures": "^1.0.3",
@@ -752,10 +902,31 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/isexe": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+            "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+            "license": "ISC"
+        },
+        "node_modules/jackspeak": {
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
+            "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
+            "license": "BlueOak-1.0.0",
+            "dependencies": {
+                "@isaacs/cliui": "^8.0.2"
+            },
+            "engines": {
+                "node": "20 || >=22"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/jake": {
-            "version": "10.9.1",
-            "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.1.tgz",
-            "integrity": "sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==",
+            "version": "10.9.2",
+            "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
+            "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
             "license": "Apache-2.0",
             "dependencies": {
                 "async": "^3.2.3",
@@ -770,6 +941,28 @@
                 "node": ">=10"
             }
         },
+        "node_modules/jake/node_modules/brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "license": "MIT",
+            "dependencies": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "node_modules/jake/node_modules/minimatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+            "license": "ISC",
+            "dependencies": {
+                "brace-expansion": "^1.1.7"
+            },
+            "engines": {
+                "node": "*"
+            }
+        },
         "node_modules/js-tokens": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -822,6 +1015,15 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/lru-cache": {
+            "version": "11.0.1",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz",
+            "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==",
+            "license": "ISC",
+            "engines": {
+                "node": "20 || >=22"
+            }
+        },
         "node_modules/mimic-fn": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
@@ -832,15 +1034,27 @@
             }
         },
         "node_modules/minimatch": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+            "version": "10.0.1",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
+            "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
             "license": "ISC",
             "dependencies": {
-                "brace-expansion": "^1.1.7"
+                "brace-expansion": "^2.0.1"
             },
             "engines": {
-                "node": "*"
+                "node": "20 || >=22"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
+        "node_modules/minipass": {
+            "version": "7.1.2",
+            "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+            "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+            "license": "ISC",
+            "engines": {
+                "node": ">=16 || 14 >=14.17"
             }
         },
         "node_modules/mute-stream": {
@@ -899,6 +1113,12 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/package-json-from-dist": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+            "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+            "license": "BlueOak-1.0.0"
+        },
         "node_modules/parent-module": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -929,12 +1149,52 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/path-key": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+            "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+            "license": "MIT",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/path-scurry": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
+            "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
+            "license": "BlueOak-1.0.0",
+            "dependencies": {
+                "lru-cache": "^11.0.0",
+                "minipass": "^7.1.2"
+            },
+            "engines": {
+                "node": "20 || >=22"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/picocolors": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
             "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
             "license": "ISC"
         },
+        "node_modules/prettier": {
+            "version": "3.3.3",
+            "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+            "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
+            "license": "MIT",
+            "bin": {
+                "prettier": "bin/prettier.cjs"
+            },
+            "engines": {
+                "node": ">=14"
+            },
+            "funding": {
+                "url": "https://github.com/prettier/prettier?sponsor=1"
+            }
+        },
         "node_modules/readable-stream": {
             "version": "3.6.2",
             "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@@ -980,6 +1240,12 @@
                 "node": ">=8"
             }
         },
+        "node_modules/restore-cursor/node_modules/signal-exit": {
+            "version": "3.0.7",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+            "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+            "license": "ISC"
+        },
         "node_modules/run-async": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
@@ -1024,12 +1290,45 @@
             "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
             "license": "MIT"
         },
-        "node_modules/signal-exit": {
-            "version": "3.0.7",
-            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
-            "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+        "node_modules/sax": {
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
+            "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
             "license": "ISC"
         },
+        "node_modules/shebang-command": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+            "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+            "license": "MIT",
+            "dependencies": {
+                "shebang-regex": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/shebang-regex": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+            "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+            "license": "MIT",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/signal-exit": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+            "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+            "license": "ISC",
+            "engines": {
+                "node": ">=14"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
+            }
+        },
         "node_modules/string_decoder": {
             "version": "1.3.0",
             "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -1053,6 +1352,21 @@
                 "node": ">=8"
             }
         },
+        "node_modules/string-width-cjs": {
+            "name": "string-width",
+            "version": "4.2.3",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+            "license": "MIT",
+            "dependencies": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/strip-ansi": {
             "version": "6.0.1",
             "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -1065,6 +1379,19 @@
                 "node": ">=8"
             }
         },
+        "node_modules/strip-ansi-cjs": {
+            "name": "strip-ansi",
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "license": "MIT",
+            "dependencies": {
+                "ansi-regex": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/strnum": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
@@ -1083,16 +1410,6 @@
                 "node": ">=8"
             }
         },
-        "node_modules/tiny-glob": {
-            "version": "0.2.9",
-            "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
-            "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
-            "license": "MIT",
-            "dependencies": {
-                "globalyzer": "0.1.0",
-                "globrex": "^0.1.2"
-            }
-        },
         "node_modules/tmp": {
             "version": "0.0.33",
             "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -1106,9 +1423,9 @@
             }
         },
         "node_modules/tslib": {
-            "version": "2.6.3",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
-            "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+            "version": "2.7.0",
+            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+            "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
             "license": "0BSD"
         },
         "node_modules/type-fest": {
@@ -1138,6 +1455,21 @@
                 "defaults": "^1.0.3"
             }
         },
+        "node_modules/which": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+            "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+            "license": "ISC",
+            "dependencies": {
+                "isexe": "^2.0.0"
+            },
+            "bin": {
+                "node-which": "bin/node-which"
+            },
+            "engines": {
+                "node": ">= 8"
+            }
+        },
         "node_modules/wrap-ansi": {
             "version": "6.2.0",
             "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
@@ -1152,6 +1484,46 @@
                 "node": ">=8"
             }
         },
+        "node_modules/wrap-ansi-cjs": {
+            "name": "wrap-ansi",
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+            "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+            "license": "MIT",
+            "dependencies": {
+                "ansi-styles": "^4.0.0",
+                "string-width": "^4.1.0",
+                "strip-ansi": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+            }
+        },
+        "node_modules/xml2js": {
+            "version": "0.6.2",
+            "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
+            "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
+            "license": "MIT",
+            "dependencies": {
+                "sax": ">=0.6.0",
+                "xmlbuilder": "~11.0.0"
+            },
+            "engines": {
+                "node": ">=4.0.0"
+            }
+        },
+        "node_modules/xmlbuilder": {
+            "version": "11.0.1",
+            "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+            "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+            "license": "MIT",
+            "engines": {
+                "node": ">=4.0"
+            }
+        },
         "node_modules/y18n": {
             "version": "5.0.8",
             "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
diff --git a/lib/mk-types/package.json b/lib/mk-types/package.json
index 3aaa4533..5027ded4 100644
--- a/lib/mk-types/package.json
+++ b/lib/mk-types/package.json
@@ -1,5 +1,5 @@
 {
     "dependencies": {
-        "@ts-for-gir/cli": "^3.3.0"
+        "@ts-for-gir/cli": "4.0.0-beta.16"
     }
 }
diff --git a/nixosModules/ags/v2/widgets/bar/fullscreen.tsx b/nixosModules/ags/v2/widgets/bar/fullscreen.tsx
index 9ae89b65..a73603ca 100644
--- a/nixosModules/ags/v2/widgets/bar/fullscreen.tsx
+++ b/nixosModules/ags/v2/widgets/bar/fullscreen.tsx
@@ -51,7 +51,10 @@ export default ({
     gdkmonitor = Gdk.Display.get_default()?.get_monitor(0) as Gdk.Monitor,
     child,
     ...rest
-}: Widget.WindowProps) => {
+}: {
+    anchor: Astal.WindowAnchor
+    gdkmonitor?: Gdk.Monitor
+} & Widget.WindowProps) => {
     const monitor = get_hyprland_monitor_desc(gdkmonitor);
     const BarVisible = Variable(true);
 
@@ -143,7 +146,6 @@ export default ({
             name={`bar-${monitor}`}
             layer={Astal.Layer.OVERLAY}
             gdkmonitor={gdkmonitor}
-            margins={[-1, -1, -1, -1]}
             anchor={anchor}
             {...rest}
         >
diff --git a/nixosModules/ags/v2/widgets/bar/items/battery.tsx b/nixosModules/ags/v2/widgets/bar/items/battery.tsx
index 2b8c84c8..883ca22d 100644
--- a/nixosModules/ags/v2/widgets/bar/items/battery.tsx
+++ b/nixosModules/ags/v2/widgets/bar/items/battery.tsx
@@ -1,4 +1,4 @@
-import { bind, Widget } from 'astal';
+import { bind } from 'astal';
 
 import AstalBattery from 'gi://AstalBattery';
 const Battery = AstalBattery.get_default();
@@ -7,12 +7,11 @@ import Separator from '../../misc/separator';
 
 
 const LOW_BATT = 20;
-const SPACING = 8;
 
 export default () => (
     <box className="bar-item battery">
         <icon
-            setup={(self: Widget.Icon) => {
+            setup={(self) => {
                 const update = () => {
                     const percent = Math.round(Battery.get_percentage() * 100);
                     const level = Math.floor(percent / 10) * 10;
@@ -37,7 +36,7 @@ export default () => (
             }}
         />
 
-        <Separator size={SPACING} />
+        <Separator size={8} />
 
         <label label={bind(Battery, 'percentage').as((v) => `${Math.round(v * 100)}%`)} />
     </box>
diff --git a/nixosModules/ags/v2/widgets/bar/items/current-client.tsx b/nixosModules/ags/v2/widgets/bar/items/current-client.tsx
index e355bee0..b25b6f45 100644
--- a/nixosModules/ags/v2/widgets/bar/items/current-client.tsx
+++ b/nixosModules/ags/v2/widgets/bar/items/current-client.tsx
@@ -1,6 +1,4 @@
-import { bind, Widget } from 'astal';
-
-import Pango from 'gi://Pango?version=1.0';
+import { bind } from 'astal';
 
 import AstalApps from 'gi://AstalApps?version=0.1';
 const Applications = AstalApps.Apps.new();
@@ -11,8 +9,6 @@ const Hyprland = AstalHyprland.get_default();
 import Separator from '../../misc/separator';
 
 
-const SPACING = 8;
-
 export default () => {
     const focused = bind(Hyprland, 'focusedClient');
 
@@ -23,10 +19,10 @@ export default () => {
         >
             <icon
                 css="font-size: 32px;"
-                setup={(self: Widget.Icon) => {
+                setup={(self) => {
                     self.hook(Hyprland, 'notify::focused-client', () => {
                         const app = Applications.query(
-                            Hyprland.get_focused_client().get_class(),
+                            Hyprland.get_focused_client()?.get_class() ?? '',
                             false,
                         )[0];
 
@@ -35,12 +31,12 @@ export default () => {
                 }}
             />
 
-            <Separator size={SPACING} />
+            <Separator size={8} />
 
             {focused.as((client) => (client && (
                 <label
                     label={bind(client, 'title').as(String)}
-                    truncate={Pango.EllipsizeMode.END}
+                    truncate
                 />
             )))}
         </box>
diff --git a/nixosModules/ags/v2/widgets/bar/items/workspaces.tsx b/nixosModules/ags/v2/widgets/bar/items/workspaces.tsx
new file mode 100644
index 00000000..bc836908
--- /dev/null
+++ b/nixosModules/ags/v2/widgets/bar/items/workspaces.tsx
@@ -0,0 +1,167 @@
+import { Gtk, idle, timeout, Widget } from 'astal';
+
+import AstalHyprland from 'gi://AstalHyprland?version=0.1';
+const Hyprland = AstalHyprland.get_default();
+
+
+const URGENT_DURATION = 1000;
+
+const Workspace = ({ id = 0 }) => (
+    <revealer
+        name={id.toString()}
+        transitionType={Gtk.RevealerTransitionType.SLIDE_RIGHT}
+    >
+        <eventbox
+            cursor="pointer"
+            tooltip_text={id.toString()}
+
+            onClickRelease={() => {
+                Hyprland.message_async(`dispatch workspace ${id}`, () => { /**/ });
+            }}
+        >
+            <box
+                valign={Gtk.Align.CENTER}
+                className="button"
+
+                setup={(self) => idle(() => {
+                    const update = (
+                        _: Widget.Box,
+                        addr?: string,
+                    ) => {
+                        const workspace = Hyprland.get_workspace(id);
+                        const occupied = workspace && workspace.get_clients().length > 0;
+
+                        self.toggleClassName('occupied', occupied);
+
+                        if (!addr) {
+                            return;
+                        }
+
+                        // Deal with urgent windows
+                        const client = Hyprland.get_client(addr);
+                        const isThisUrgent = client &&
+                          client.workspace.id === id;
+
+                        if (isThisUrgent) {
+                            self.toggleClassName('urgent', true);
+
+                            // Only show for a sec when urgent is current workspace
+                            if (Hyprland.get_focused_workspace().get_id() === id) {
+                                timeout(URGENT_DURATION, () => {
+                                    self.toggleClassName('urgent', false);
+                                });
+                            }
+                        }
+                    };
+
+                    self
+                        .hook(Hyprland, 'event', update)
+
+                        // Deal with urgent windows
+                        .hook(Hyprland, 'urgent', update)
+
+                        .hook(Hyprland, 'notify::focused-workspace', () => {
+                            if (Hyprland.get_focused_workspace().get_id() === id) {
+                                self.toggleClassName('urgent', false);
+                            }
+                        });
+                })}
+            />
+        </eventbox>
+    </revealer>
+);
+
+export default () => {
+    const L_PADDING = 2;
+    const WS_WIDTH = 30;
+
+    const updateHighlight = (self: Widget.Box) => {
+        const currentId = Hyprland.get_focused_workspace().get_id().toString();
+
+        const indicators = ((self.get_parent() as Widget.Overlay)
+            .child as Widget.Box)
+            .children as Widget.Revealer[];
+
+        const currentIndex = indicators.findIndex((w) => w.name === currentId);
+
+        if (currentIndex >= 0) {
+            self.css = `margin-left: ${L_PADDING + (currentIndex * WS_WIDTH)}px`;
+        }
+    };
+
+    const highlight = (
+        <box
+            className="button active"
+
+            valign={Gtk.Align.CENTER}
+            halign={Gtk.Align.START}
+
+            setup={(self) => {
+                self.hook(Hyprland, 'notify::focused-workspace', updateHighlight);
+            }}
+        />
+    ) as Widget.Box;
+
+    let workspaces: Widget.Revealer[] = [];
+
+    return (
+        <box
+            className="bar-item"
+        >
+            <overlay
+                className="workspaces"
+                passThrough
+                overlay={highlight}
+            >
+                <box
+                    setup={(self) => {
+                        const refresh = () => {
+                            (self.children as Widget.Revealer[]).forEach((rev) => {
+                                rev.reveal_child = false;
+                            });
+
+                            workspaces.forEach((ws) => {
+                                ws.reveal_child = true;
+                            });
+                        };
+
+                        const updateWorkspaces = () => {
+                            Hyprland.get_workspaces().forEach((ws) => {
+                                const currentWs = (self.children as Widget.Revealer[])
+                                    .find((ch) => ch.name === ws.id.toString());
+
+                                if (!currentWs && ws.id > 0) {
+                                    self.add(Workspace({ id: ws.id }));
+                                }
+                            });
+
+                            // Make sure the order is correct
+                            workspaces.forEach((workspace, i) => {
+                                (workspace.get_parent() as Widget.Box)
+                                    .reorder_child(workspace, i);
+                            });
+                        };
+
+                        self.hook(Hyprland, 'event', () => {
+                            workspaces = (self.children as Widget.Revealer[])
+                                .filter((ch) => {
+                                    return Hyprland.get_workspaces().find((ws) => {
+                                        return ws.id.toString() === ch.name;
+                                    });
+                                })
+                                .sort((a, b) => parseInt(a.name ?? '0') - parseInt(b.name ?? '0'));
+
+                            updateWorkspaces();
+                            refresh();
+
+                            // Make sure the highlight doesn't go too far
+                            const TEMP_TIMEOUT = 100;
+
+                            timeout(TEMP_TIMEOUT, () => updateHighlight(highlight));
+                        });
+                    }}
+                />
+            </overlay>
+        </box>
+    );
+};
diff --git a/nixosModules/ags/v2/widgets/bar/style.scss b/nixosModules/ags/v2/widgets/bar/style.scss
index 1c243a1b..59cb985e 100644
--- a/nixosModules/ags/v2/widgets/bar/style.scss
+++ b/nixosModules/ags/v2/widgets/bar/style.scss
@@ -4,7 +4,7 @@
         border-radius: 7px;
         background-color: darken($window_bg_color, 3%);
         font-size: 20px;
-        min-height: 30px;
+        min-height: 35px;
 
         .battery icon {
             &.charging {
@@ -15,5 +15,32 @@
                 color: red;
             }
         }
+
+        .workspaces {
+            .button {
+                margin: 0 2.5px;
+                min-height: 22px;
+                min-width: 22px;
+                border-radius: 100%;
+                border: 2px solid transparent;
+            }
+
+            .occupied {
+                border: 2px solid $window_bg_color;
+                background: $accent_color;
+                transition: background-color 0.6s ease-in-out;
+            }
+
+            .urgent {
+                border: 2px solid $window_bg_color;
+                background: red;
+                transition: background-color 0.6s ease-in-out;
+            }
+
+            .active {
+                border: 2px solid #50fa7b;
+                transition: margin-left 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
+            }
+        }
     }
 }
diff --git a/nixosModules/ags/v2/widgets/bar/wim.tsx b/nixosModules/ags/v2/widgets/bar/wim.tsx
index 75d79b27..2ad3c8b6 100644
--- a/nixosModules/ags/v2/widgets/bar/wim.tsx
+++ b/nixosModules/ags/v2/widgets/bar/wim.tsx
@@ -3,6 +3,7 @@ import { Astal, Gtk } from 'astal';
 import Battery from './items/battery';
 import Clock from './items/clock';
 import CurrentClient from './items/current-client';
+import Workspaces from './items/workspaces';
 
 import BarRevealer from './fullscreen';
 import Separator from '../misc/separator';
@@ -20,6 +21,10 @@ export default () => (
 
         <centerbox className="bar widget">
             <box hexpand halign={Gtk.Align.START}>
+                <Workspaces />
+
+                <Separator size={8} />
+
                 <CurrentClient />
             </box>