diff --git a/dotfiles/neovim/lua/my/helpers/env.lua b/dotfiles/neovim/lua/my/helpers/env.lua
index 2d94302..ba3756f 100644
--- a/dotfiles/neovim/lua/my/helpers/env.lua
+++ b/dotfiles/neovim/lua/my/helpers/env.lua
@@ -28,7 +28,7 @@ return {
     return vim.g.neovide ~= nil or require("nix.env") == "neovide"
   end),
   firenvim = makeEnv(function()
-    return vim.g.started_by_firenvim ~= nil
+    return vim.g.started_by_firenvim ~= nil or require("nix.env") == "firenvim"
   end),
   _and = function(a, b)
     return makeEnv(function()
diff --git a/dotfiles/neovim/lua/my/plugins/firenvim.lua b/dotfiles/neovim/lua/my/plugins/firenvim.lua
index a505839..6286cea 100644
--- a/dotfiles/neovim/lua/my/plugins/firenvim.lua
+++ b/dotfiles/neovim/lua/my/plugins/firenvim.lua
@@ -4,9 +4,14 @@ local K = require("my.keymaps")
 local M = {
   "glacambre/firenvim", -- vim inside chrome
   lazy = false,
-  cond = env.firenvim.active(),
+  -- cond = env.firenvim.active(),
+  cond = true
 }
 
+function M.blacklist(url)
+  vim.g.firenvim_config.localSettings[url] = { takeover = "never" }
+end
+
 function M.config()
   vim.g.firenvim_config = {
     localSettings = {
@@ -33,6 +38,16 @@ function M.config()
   -- {{{ Disable status line
   vim.opt.laststatus = 0
   -- }}}
+  -- {{{ Blacklist websites
+  local blacklisted = {
+    "https?://web.whatsapp\\.com/.*",
+    "https?://twitter\\.com/",
+  }
+
+  for _, url in ipairs(blacklisted) do
+    M.blacklist(url)
+  end
+  -- }}}
 end
 
 return M
diff --git a/home/adrielus/features/neovim/default.nix b/home/adrielus/features/neovim/default.nix
index 7920ffe..225baf1 100644
--- a/home/adrielus/features/neovim/default.nix
+++ b/home/adrielus/features/neovim/default.nix
@@ -1,5 +1,6 @@
 { pkgs, lib, config, paths, ... }:
 let
+  # {{{ extraPackages
   extraPackages = with pkgs; [
     # Language servers
     nodePackages.typescript-language-server # typescript
@@ -41,8 +42,8 @@ let
     # python310Packages.pynvim
     # python310Packages.jupyter
   ];
-in
-let
+  # }}}
+  # {{{ extraRuntime
   extraRuntime = env: [
     # Snippets
     (config.satellite-dev.path "dotfiles/vscode-snippets")
@@ -63,34 +64,46 @@ let
       "return '${env}'"
     )
   ];
-
+  # }}}
+  # {{{ Client wrapper
   # Wraps a neovim client, providing the dependencies
   # and setting some flags:
   #
   # - NVIM_EXTRA_RUNTIME provides extra directories to add to the runtimepath. 
   #   I cannot just install those dirs using the builtin package support because 
   #   my package manager (lazy.nvim) disables those.
-  wrapClient = { base, name, extraArgs ? "" }:
+  wrapClient = { base, name, binName ? name, extraArgs ? "" }:
     pkgs.symlinkJoin {
       inherit (base) name meta;
       paths = [ base ];
       nativeBuildInputs = [ pkgs.makeWrapper ];
       postBuild = ''
-        wrapProgram $out/bin/${name} \
+        wrapProgram $out/bin/${binName} \
           --prefix PATH : ${lib.makeBinPath extraPackages} \
           --set NVIM_EXTRA_RUNTIME ${lib.strings.concatStringsSep "," (extraRuntime name)} \
           ${extraArgs}
       '';
     };
-
+  # }}}
+  # {{{ Clients
   neovim = wrapClient { base = pkgs.neovim-nightly; name = "nvim"; };
+
   neovide = wrapClient {
     base = pkgs.neovide;
     name = "neovide";
     extraArgs = "--set NEOVIDE_MULTIGRID true";
   };
+
+  firenvim = wrapClient {
+    base = pkgs.neovim-nightly;
+    name = "firenvim";
+    binName = "nvim";
+    extraArgs = "--set GIT_DISCOVERY_ACROSS_FILESYSTEM 1";
+  };
+  # }}}
 in
 {
+  # {{{ Basic config
   # Do not manage neovim via nix
   programs.neovim.enable = false;
 
@@ -101,4 +114,51 @@ in
     neovim
     neovide
   ];
+  # }}}
+  # {{{ Firenvim
+  home.file.".mozilla/native-messaging-hosts/firenvim.json".text =
+    let
+      # God knows what this does
+      # https://github.com/glacambre/firenvim/blob/87c9f70d3e6aa2790982aafef3c696dbe962d35b/autoload/firenvim.vim#L592
+      firenvim_init = pkgs.writeText "firenvim_init.vim" ''
+        let g:firenvim_i=[]
+        let g:firenvim_o=[]
+        let g:Firenvim_oi={i,d,e->add(g:firenvim_i,d)}
+        let g:Firenvim_oo={t->[chansend(2,t)]+add(g:firenvim_o,t)}
+        let g:firenvim_c=stdioopen({'on_stdin':{i,d,e->g:Firenvim_oi(i,d,e)},'on_print':{t->g:Firenvim_oo(t)}})
+        let g:started_by_firenvim = v:true
+      '';
+
+      firenvim_file_loaded = pkgs.writeText "firenvim_file_loaded.vim"
+        ''
+          try
+            call firenvim#run()
+          catch /Unknown function/
+            call chansend(g:firenvim_c,["f\n\n\n"..json_encode({"messages":["Your plugin manager did not load the Firenvim plugin for neovim."],"version":"0.0.0"})])
+            call chansend(2,["Firenvim not in runtime path. &rtp="..&rtp])
+            qall!
+          catch
+            call chansend(g:firenvim_c,["l\n\n\n"..json_encode({"messages": ["Something went wrong when running firenvim. See troubleshooting guide."],"version":"0.0.0"})])
+            call chansend(2,[v:exception])
+            qall!
+          endtry
+        '';
+    in
+    builtins.toJSON
+      {
+        name = "firenvim";
+        description = "Turn your browser into a Neovim GUI.";
+        type = "stdio";
+        allowed_extensions = [ "firenvim@lacamb.re" ];
+        path = pkgs.writeShellScript "firenvim.sh" ''
+          mkdir -p /run/user/$UID/firenvim
+          chmod 700 /run/user/$UID/firenvim
+          cd /run/user/$UID/firenvim
+
+          exec '${firenvim}/bin/nvim' --headless \
+            --cmd 'source "${firenvim_init}"' \
+            -S    '${firenvim_file_loaded}'
+        '';
+      };
+  # }}}
 }