diff --git a/devshells/default.nix b/devshells/default.nix
index 9e9a8f4..9b0b4f1 100644
--- a/devshells/default.nix
+++ b/devshells/default.nix
@@ -1,5 +1,6 @@
 args: {
   visonum = import ./visonum.nix args;
   rwtw = import ./rwtw.nix args;
+  typst = import ./typst.nix args;
 }
 
diff --git a/devshells/typst.nix b/devshells/typst.nix
new file mode 100644
index 0000000..04002bd
--- /dev/null
+++ b/devshells/typst.nix
@@ -0,0 +1,8 @@
+# Shell for using a pinned version of typst
+{ pkgs, upkgs, inputs, ... }:
+pkgs.mkShell {
+  nativeBuildInputs = [
+    # REASON: not on nixpkgs-stable
+    upkgs.typst
+  ];
+}
diff --git a/dotfiles/neovim/README.md b/dotfiles/neovim/README.md
index 6a3a324..3f42ea4 100644
--- a/dotfiles/neovim/README.md
+++ b/dotfiles/neovim/README.md
@@ -217,6 +217,7 @@ The following keybinds are available only when running inside firenvim:
 | \<leader\>h           | Add file to harpoon                 | harpoon              |
 | C-a                   | Harpoon quick menu                  | harpoon              |
 | C-s q/w/e/r/a/s/d/f/z | Open harpoon file with index 0-9    | harpoon              |
+| <leader>lc            | Open [l]ocal [c]argo.toml           | rust-tools           |
 
 ### Undocumented
 
diff --git a/dotfiles/neovim/lazy-lock.json b/dotfiles/neovim/lazy-lock.json
index d4e1352..1d24ef2 100644
--- a/dotfiles/neovim/lazy-lock.json
+++ b/dotfiles/neovim/lazy-lock.json
@@ -64,6 +64,7 @@
   "telescope-file-browser.nvim": { "branch": "master", "commit": "e0fcb12702ad0d2873544a31730f9aaef04fd032" },
   "telescope-fzf-native.nvim": { "branch": "main", "commit": "580b6c48651cabb63455e97d7e131ed557b8c7e2" },
   "telescope.nvim": { "branch": "master", "commit": "e960efa60e97df58e089b00270f09d60f27202c8" },
+  "typst.vim": { "branch": "main", "commit": "a9bb264d29331c52ef462e42e0501e3411bc3efb" },
   "undotree": { "branch": "master", "commit": "485f01efde4e22cb1ce547b9e8c9238f36566f21" },
   "venn.nvim": { "branch": "main", "commit": "c114563960b8fb1197695d42798d1f3e7190b798" },
   "vim-abolish": { "branch": "master", "commit": "cb3dcb220262777082f63972298d57ef9e9455ec" },
diff --git a/dotfiles/neovim/lua/my/plugins/init.lua b/dotfiles/neovim/lua/my/plugins/init.lua
index 565bc2d..4cdaa41 100644
--- a/dotfiles/neovim/lua/my/plugins/init.lua
+++ b/dotfiles/neovim/lua/my/plugins/init.lua
@@ -53,6 +53,12 @@ return {
     ft = { "yml", "yaml" },
     cond = env.vscode.not_active(),
   },
+
+  {
+    "kaarmu/typst.vim",
+    ft = { "typst" },
+    cond = env.vscode.not_active(),
+  },
   --}}}
 
   {
@@ -106,8 +112,8 @@ return {
     "christoomey/vim-tmux-navigator",
     keys = { "<C-h>", "<C-j>", "<C-k>", "<C-l>" },
     cond = env.vscode.not_active()
-      and env.neovide.not_active()
-      and env.firenvim.not_active(),
+        and env.neovide.not_active()
+        and env.firenvim.not_active(),
   },
 
   {
diff --git a/dotfiles/neovim/lua/my/plugins/lspconfig.lua b/dotfiles/neovim/lua/my/plugins/lspconfig.lua
index 45ca17a..f1cafdb 100644
--- a/dotfiles/neovim/lua/my/plugins/lspconfig.lua
+++ b/dotfiles/neovim/lua/my/plugins/lspconfig.lua
@@ -172,6 +172,7 @@ local servers = {
   cssls = {},
   jsonls = {},
   dhall_lsp_server = {},
+  typst_lsp = {},
   -- pylsp = {},
   -- pyright = {},
 }
@@ -182,7 +183,7 @@ M.capabilities = function()
   local c = require("cmp_nvim_lsp").default_capabilities()
   -- Add folding capabilities
   c.textDocument.foldingRange =
-    { dynamicRegistration = false, lineFoldingOnly = true }
+  { dynamicRegistration = false, lineFoldingOnly = true }
   return c
 end
 -- }}}
@@ -218,7 +219,7 @@ function lspconfig.config()
 
     require("lspconfig")[lsp].setup({
       on_attach = details.on_attach,
-      settings = details.settings, -- Specific per-language settings
+      settings = details.settings,   -- Specific per-language settings
       flags = {
         debounce_text_changes = 150, -- This will be the default in neovim 0.7+
       },
diff --git a/dotfiles/neovim/lua/my/plugins/rust-tools.lua b/dotfiles/neovim/lua/my/plugins/rust-tools.lua
index d08be39..9b7597a 100644
--- a/dotfiles/neovim/lua/my/plugins/rust-tools.lua
+++ b/dotfiles/neovim/lua/my/plugins/rust-tools.lua
@@ -6,17 +6,19 @@ local M = {
   config = function()
     require("rust-tools").setup({
       server = {
-        on_attach = lspconfig.on_attach,
+        on_attach = function(client, bufnr)
+          K.nmap(
+            "<leader>lc",
+            "<cmd>RustOpenCargo<cr>",
+            "Open [c]argo.toml",
+            true,
+            true
+          )
+
+          lspconfig.on_attach(client, bufnr)
+        end,
       },
     })
-
-    K.nmap(
-      "<leader>lc",
-      "<cmd>RustOpenCargo<cr>",
-      "Open [c]argo.toml",
-      true,
-      true
-    )
   end,
 }
 
diff --git a/flake.lock b/flake.lock
index 3ea04c9..ee148fd 100644
--- a/flake.lock
+++ b/flake.lock
@@ -310,11 +310,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1682493015,
-        "narHash": "sha256-KiMOAe8u83QDF40Z25kWMkZbqr9U+mvjvEJy5Qvw0nw=",
+        "lastModified": 1684171562,
+        "narHash": "sha256-BMUWjVWAUdyMWKk0ATMC9H0Bv4qAV/TXwwPUvTiC5IQ=",
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "60c0f762658916a4a5b5a36b3e06486f8301daf4",
+        "rev": "55af203d468a6f5032a519cba4f41acf5a74b638",
         "type": "github"
       },
       "original": {
@@ -326,11 +326,11 @@
     },
     "nixpkgs-unstable": {
       "locked": {
-        "lastModified": 1681737997,
-        "narHash": "sha256-pHhjgsIkRMu80LmVe8QoKIZB6VZGRRxFmIvsC5S89k4=",
+        "lastModified": 1683408522,
+        "narHash": "sha256-9kcPh6Uxo17a3kK3XCHhcWiV1Yu1kYj22RHiymUhMkU=",
         "owner": "nixos",
         "repo": "nixpkgs",
-        "rev": "f00994e78cd39e6fc966f0c4103f908e63284780",
+        "rev": "897876e4c484f1e8f92009fd11b7d988a121a4e7",
         "type": "github"
       },
       "original": {
diff --git a/flake.nix b/flake.nix
index c97c20f..e25f110 100644
--- a/flake.nix
+++ b/flake.nix
@@ -42,7 +42,7 @@
     rosepine-base16.url = github:edunfelt/base16-rose-pine-scheme;
     rosepine-base16.flake = false;
 
-    # Impermanence 
+    # Impermanence
     impermanence.url = "github:nix-community/impermanence";
 
     # Slambda
diff --git a/home/adrielus/features/desktop/common/firefox/default.nix b/home/adrielus/features/desktop/common/firefox/default.nix
index 5286056..66e49d7 100644
--- a/home/adrielus/features/desktop/common/firefox/default.nix
+++ b/home/adrielus/features/desktop/common/firefox/default.nix
@@ -1,7 +1,29 @@
 { pkgs, inputs, ... }:
+let
+  # {{{ Global extensions
+  extensions = with inputs.firefox-addons.packages.${pkgs.system}; [
+    buster-captcha-solver
+    bypass-paywalls-clean
+    clearurls # removes ugly args from urls
+    don-t-fuck-with-paste # disallows certain websites from disabling pasting
+    gesturefy # mouse gestures
+    i-dont-care-about-cookies
+    localcdn # caches libraries locally
+    privacy-badger # blocks some trackers
+    privacy-pass # captcha stuff
+    skip-redirect # attempts to skip to the final reddirect for certain urls
+    terms-of-service-didnt-read
+    translate-web-pages
+    ublock-origin
+    unpaywall
+    user-agent-string-switcher
+  ];
+  # }}}
+in
 {
   programs.firefox = {
     enable = true;
+
     profiles.adrielus = {
       # {{{ High level user settings
       # Unique user id
@@ -20,30 +42,15 @@
       userContent = builtins.readFile ./userContent.css;
       # }}}
       # {{{ Extensions
-      extensions = with inputs.firefox-addons.packages.${pkgs.system}; [
-        buster-captcha-solver
-        bypass-paywalls-clean
-        clearurls # removes ugly args from urls
-        don-t-fuck-with-paste # disallows certain websites from disabling pasting
+      extensions = with inputs.firefox-addons.packages.${pkgs.system}; extensions ++ [
         firenvim # summon a nvim instance inside the browser
-        gesturefy # mouse gestures
-        i-dont-care-about-cookies
-        localcdn # caches libraries locally
         lovely-forks # displays forks on github
         octolinker # github import to link thingy
         octotree # github file tree
-        privacy-badger # blocks some trackers
-        privacy-pass # captcha stuff
         refined-github # a bunch of github modifications
         return-youtube-dislikes
         steam-database # adds info from steamdb on storepages
         sponsorblock # skip youtube sponsors
-        skip-redirect # attempts to skip to the final reddirect for certain urls
-        terms-of-service-didnt-read
-        translate-web-pages
-        ublock-origin
-        unpaywall
-        user-agent-string-switcher
         vimium-c # vim keybinds
         youtube-shorts-block
       ];
@@ -156,7 +163,8 @@
     };
 
     # {{{ Standalone "apps" which actually run inside a browser.
-    apps = {
+    apps.extensions = extensions;
+    apps.app = {
       # {{{ Job stuff
       asana = {
         url = "https://app.asana.com/";
@@ -171,7 +179,6 @@
         displayName = "Clockodo";
         id = 2;
       };
-
       # }}}
 
       gitlab = {
@@ -187,6 +194,13 @@
         displayName = "Desmos";
         id = 4;
       };
+
+      monkey-type = {
+        url = "https://monkeytype.com/";
+        icon = ./icons/monkeytype.png;
+        displayName = "Monkeytype";
+        id = 5;
+      };
     };
     # }}}
   };
@@ -203,6 +217,7 @@
   # Tell apps firefox is the default browser using an env var.
   home.sessionVariables.BROWSER = "firefox";
   # }}}
+
   # {{{ Persistence
   home.persistence."/persist/home/adrielus".directories = [
     ".cache/mozilla/firefox" # Non important cache
diff --git a/home/adrielus/features/desktop/common/firefox/icons/monkeytype.png b/home/adrielus/features/desktop/common/firefox/icons/monkeytype.png
new file mode 100644
index 0000000..dbe0c6b
Binary files /dev/null and b/home/adrielus/features/desktop/common/firefox/icons/monkeytype.png differ
diff --git a/home/adrielus/features/desktop/common/wezterm/wezterm.lua b/home/adrielus/features/desktop/common/wezterm/wezterm.lua
index 1d7cbd2..35158c9 100644
--- a/home/adrielus/features/desktop/common/wezterm/wezterm.lua
+++ b/home/adrielus/features/desktop/common/wezterm/wezterm.lua
@@ -57,6 +57,11 @@ config.adjust_window_size_when_changing_font_size = false -- Makes it work with
 config.automatically_reload_config = true
 config.font_size = font_size
 config.use_fancy_tab_bar = false
+config.disable_default_key_bindings = true
+-- config.enable_kitty_keyboard = true -- Let's apps recognise more distinct keys
+config.enable_csi_u_key_encoding = true -- For some reason I need this for all keybinds to work inside neovim.
+-- }}}
+-- {{{ Keybinds
 -- }}}
 
 -- and finally, return the configuration to wezterm
diff --git a/home/adrielus/features/neovim/default.nix b/home/adrielus/features/neovim/default.nix
index dfb4a99..405a5c0 100644
--- a/home/adrielus/features/neovim/default.nix
+++ b/home/adrielus/features/neovim/default.nix
@@ -14,10 +14,11 @@ let
     dhall-lsp-server # dhall
     tectonic # something related to latex (?)
     texlab # latex
-    nodePackages_latest.vscode-langservers-extracted # Web stuff
-    python310Packages.python-lsp-server # Python
-    pyright # Python
+    nodePackages_latest.vscode-langservers-extracted # web stuff
+    python310Packages.python-lsp-server # python
+    pyright # python
     rust-analyzer # rust
+    upkgs.typst-lsp # typst
 
     # Formatters
     luaformatter # Lua
@@ -29,6 +30,7 @@ let
     nodePackages_latest.purs-tidy # Purescript
     nodePackages_latest.prettier # Js & friends
     nodePackages_latest.prettier_d_slim # Js & friends
+    upkgs.typst-fmt # Typst
 
     # Linters
     ruff # Python linter
@@ -52,10 +54,11 @@ let
     # Preview
     zathura # Pdf reader
     xdotool # For zathura reverse search or whatever it's called
-    glow #Mmd preview in terminal
+    glow # Md preview in terminal
     pandoc # Md processing
-    libsForQt5.falkon # Aparently needed for md preview
+    libsForQt5.falkon # Needed for one of the md preview plugins I tried
 
+    # Latex setup
     texlive.combined.scheme-full # Latex stuff
     python38Packages.pygments # required for latex syntax highlighting
     sage
diff --git a/home/adrielus/tethys.nix b/home/adrielus/tethys.nix
index f6787c1..997e387 100644
--- a/home/adrielus/tethys.nix
+++ b/home/adrielus/tethys.nix
@@ -53,7 +53,10 @@
 
 
   # Temp stuff
-  xsession.initExtra = ''
-    command -v dbus-update-activation-environment >/dev/null 2>&1 && dbus-update-activation-environment --systemd XDG_SESSION_CLASS XDG_CONFIG_DIRS XDG_DATA_DIRS XDG_SESSION_DESKTOP XDG_CURRENT_DESKTOP XDG_SESSION_TYPE DCONF_PROFILE XDG_DESKTOP_PORTAL_DIR DISPLAY WAYLAND_DISPLAY SWAYSOCK XMODIFIERS XCURSOR_SIZE XCURSOR_THEME GDK_PIXBUF_MODULE_FILE GIO_EXTRA_MODULES GTK_IM_MODULE QT_PLUGIN_PATH QT_QPA_PLATFORMTHEME QT_STYLE_OVERRIDE QT_IM_MODULE NIXOS_OZONE_WL || systemctl --user import-environment XDG_SESSION_CLASS XDG_CONFIG_DIRS XDG_DATA_DIRS XDG_SESSION_DESKTOP XDG_CURRENT_DESKTOP XDG_SESSION_TYPE DCONF_PROFILE XDG_DESKTOP_PORTAL_DIR DISPLAY WAYLAND_DISPLAY SWAYSOCK XMODIFIERS XCURSOR_SIZE XCURSOR_THEME GDK_PIXBUF_MODULE_FILE GIO_EXTRA_MODULES GTK_IM_MODULE QT_PLUGIN_PATH QT_QPA_PLATFORMTHEME QT_STYLE_OVERRIDE QT_IM_MODULE NIXOS_OZONE_WL
-  '';
+  # systemd.servinces.dbus-update-activation-environment = {
+  #   script = lib.escapeShellArgs "${pkgs.dbu}/bin/dbus-update-activation-environment --systemd --all";
+  #   serviceConfig.Restart = "no";
+  #   serviceConfig.User = config.home.user;
+  # };
+  xsession.initExtra = "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd --all";
 }
diff --git a/hosts/nixos/common/optional/xdg-portal.nix b/hosts/nixos/common/optional/xdg-portal.nix
index b51721d..a251f8e 100644
--- a/hosts/nixos/common/optional/xdg-portal.nix
+++ b/hosts/nixos/common/optional/xdg-portal.nix
@@ -7,4 +7,6 @@
 
   # HACK: copied from @lily on discord.
   systemd.user.services.xdg-desktop-portal.path = lib.mkAfter [ "/run/current-system/sw" ];
+
+  services.gnome.at-spi2-core.enable = true;
 }
diff --git a/modules/home-manager/firefox/default.nix b/modules/home-manager/firefox/default.nix
index c4c2567..9f04202 100644
--- a/modules/home-manager/firefox/default.nix
+++ b/modules/home-manager/firefox/default.nix
@@ -1,43 +1,58 @@
+# Allows installing web apps as desktop apps
 { lib, pkgs, config, ... }:
 let cfg = config.programs.firefox.apps;
 in
 {
-  options.programs.firefox.apps = lib.mkOption {
-    type = lib.types.attrsOf
-      (lib.types.submodule ({ name, ... }: {
-        options = {
-          name = lib.mkOption {
-            type = lib.types.str;
-            description = "The name of the app";
-            default = name;
-          };
+  options.programs.firefox.apps = {
+    extensions = lib.mkOption {
+      type = lib.types.listOf lib.types.package;
+      description = "Extensions to install for all apps";
+      default = [ ];
+    };
 
-          id = lib.mkOption {
-            type = lib.types.int;
-            description = "The id of the firefox profile for the app";
-            example = 3;
-          };
+    app = lib.mkOption {
+      type = lib.types.attrsOf
+        (lib.types.submodule ({ name, ... }: {
+          options = {
+            name = lib.mkOption {
+              type = lib.types.str;
+              description = "The name of the app";
+              default = name;
+            };
 
-          displayName = lib.mkOption {
-            type = lib.types.str;
-            description = "The name of the app in stuff like menus";
-            default = name;
-          };
+            id = lib.mkOption {
+              type = lib.types.int;
+              description = "The id of the firefox profile for the app";
+              example = 3;
+            };
 
-          url = lib.mkOption {
-            type = lib.types.str;
-            description = "The url the app should point to";
-            example = "https://example.com";
-          };
+            displayName = lib.mkOption {
+              type = lib.types.str;
+              description = "The name of the app in stuff like menus";
+              default = name;
+            };
 
-          icon = lib.mkOption {
-            type = lib.types.path;
-            description = "The icon to use for the app";
-          };
-        };
-      }));
+            url = lib.mkOption {
+              type = lib.types.str;
+              description = "The url the app should point to";
+              example = "https://example.com";
+            };
 
-    description = "Attr set of firefox web apps to install as desktop apps";
+            icon = lib.mkOption {
+              type = lib.types.path;
+              description = "The icon to use for the app";
+            };
+
+            extensions = lib.mkOption {
+              type = lib.types.listOf lib.types.package;
+              description = "Extensions to install for this app";
+              default = [ ];
+            };
+          };
+        }));
+
+      description = "Attr set of firefox web apps to install as desktop apps";
+    };
   };
 
   config =
@@ -52,7 +67,7 @@ in
         };
 
         userChrome = builtins.readFile ./theme.css;
-
+        extensions = cfg.extensions ++ app.extensions;
         isDefault = false;
         id = app.id;
       };
@@ -66,7 +81,7 @@ in
       };
     in
     {
-      programs.firefox.profiles = lib.mapAttrs (_: mkProfile) cfg;
-      xdg.desktopEntries = lib.mapAttrs (_: mkDesktopEntry) cfg;
+      programs.firefox.profiles = lib.mapAttrs (_: mkProfile) cfg.app;
+      xdg.desktopEntries = lib.mapAttrs (_: mkDesktopEntry) cfg.app;
     };
 }