diff --git a/.config/nvim b/.config/nvim
deleted file mode 160000
index aaf8fd6b..00000000
--- a/.config/nvim
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit aaf8fd6be6829b81f5456c741cf987bd2ab10a2c
diff --git a/.config/nvim/.neoconf.json b/.config/nvim/.neoconf.json
new file mode 100644
index 00000000..7c480874
--- /dev/null
+++ b/.config/nvim/.neoconf.json
@@ -0,0 +1,15 @@
+{
+  "neodev": {
+    "library": {
+      "enabled": true,
+      "plugins": true
+    }
+  },
+  "neoconf": {
+    "plugins": {
+      "lua_ls": {
+        "enabled": true
+      }
+    }
+  }
+}
diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua
new file mode 100644
index 00000000..ed2ca840
--- /dev/null
+++ b/.config/nvim/init.lua
@@ -0,0 +1,4 @@
+_G.Config = require("config")
+_G.Lib = require("lib")
+
+require("config.lazy")
diff --git a/.config/nvim/lua/config/autocmds.lua b/.config/nvim/lua/config/autocmds.lua
new file mode 100644
index 00000000..583330dc
--- /dev/null
+++ b/.config/nvim/lua/config/autocmds.lua
@@ -0,0 +1,57 @@
+-- Autocmds are automatically loaded on the VeryLazy event
+-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua
+-- Add any additional autocmds here
+
+local autocmds = {
+    { -- Automatically change line numeration
+        { "BufEnter", "FocusGained", "InsertLeave", "WinEnter" },
+        {
+            group = "auto_number",
+            command = 'if &nu && mode() != "i" | set rnu | endif',
+            -- callback = function()
+            --     if vim.opt.number and vim.fn.mode() ~= "i" then
+            --         vim.opt.relativenumber = true
+            --     end
+            -- end,
+        },
+    },
+    { -- Automatically change line numeration
+        { "BufLeave", "FocusLost", "InsertEnter", "WinLeave" },
+        {
+            group = "auto_number",
+            command = "if &nu | set nornu | endif",
+            -- callback = function()
+            --     if vim.opt.number then
+            --         vim.opt.relativenumber = false
+            --     end
+            -- end,
+        },
+    },
+    { -- Trigger shortcuts script
+        "BufWritePost",
+        {
+            pattern = { "directories", "files" },
+            command = "silent!!shortcuts",
+        },
+    },
+    { -- Trigger xrdb
+        "BufWritePost",
+        {
+            pattern = { "xresources" },
+            command = "silent!!xrdb %",
+        },
+    },
+}
+
+vim.api.nvim_create_augroup("user_config", { clear = true })
+for _, entry in ipairs(autocmds) do
+    local event = entry[1]
+    local opts = entry[2]
+    if type(opts.group) == "string" and opts.group ~= "" then
+        local exists, _ = pcall(vim.api.nvim_get_autocmds, { group = opts.group })
+        if not exists then
+            vim.api.nvim_create_augroup(opts.group, {})
+        end
+    end
+    vim.api.nvim_create_autocmd(event, opts)
+end
diff --git a/.config/nvim/lua/config/init.lua b/.config/nvim/lua/config/init.lua
new file mode 100644
index 00000000..959bf006
--- /dev/null
+++ b/.config/nvim/lua/config/init.lua
@@ -0,0 +1,17 @@
+---@class config
+---@field ui config.ui
+---@field language config.language
+---@field shortcuts config.shortcuts
+---@field secrets? config.secrets
+local M = {}
+
+setmetatable(M, {
+    __index = function(_, k)
+        local ok, mod = pcall(require, "config." .. k)
+        if ok then
+            return mod
+        end
+    end,
+})
+
+return M
diff --git a/.config/nvim/lua/config/keymaps.lua b/.config/nvim/lua/config/keymaps.lua
new file mode 100644
index 00000000..3fe8206f
--- /dev/null
+++ b/.config/nvim/lua/config/keymaps.lua
@@ -0,0 +1,8 @@
+-- Keymaps are automatically loaded on the VeryLazy event
+-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
+-- Add any additional keymaps here
+
+local unmap = vim.api.nvim_del_keymap
+
+unmap("n", "<Leader>uL")
+unmap("n", "<Leader>ul")
diff --git a/.config/nvim/lua/config/language.lua b/.config/nvim/lua/config/language.lua
new file mode 100644
index 00000000..0aa04646
--- /dev/null
+++ b/.config/nvim/lua/config/language.lua
@@ -0,0 +1,205 @@
+---@diagnostic disable: missing-fields
+---@class config.language
+local M = {}
+
+---@type table<string, conform.FormatterUnit>
+M.formatters_by_ft = {
+    css = { "prettier" },
+    scss = { "prettier" },
+    lua = { "stylua" },
+    python = { "black" },
+    sh = { "shfmt" },
+}
+
+---@type table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride>
+M.formatters = {
+    injected = { options = { ignore_errors = true } },
+    shfmt = { prepend_args = { "-i", "4", "-ci" } },
+}
+
+---@type table<string,table>
+M.linters_by_ft = {
+    dockerfile = { "hadolint" },
+    markdown = { "markdownlint" },
+}
+
+---@type table<string,table>
+M.linters = {}
+
+---@type Array<string>
+M.mason_install = {
+    "ansible-lint",
+    "ansible-language-server",
+    "basedpyright",
+    "bash-language-server",
+    "codelldb",
+    "debugpy",
+    "dockerfile-language-server",
+    "docker-compose-language-service",
+    "helm-ls",
+    "json-lsp",
+    "lua-language-server",
+    "hadolint",
+    "marksman",
+    "markdownlint",
+    "prettier",
+    "ruff-lsp",
+    "rust-analyzer",
+    "yaml-language-server",
+}
+
+---@type Array<string>
+M.treesitter_install = {
+    "bash",
+    "c",
+    "diff",
+    "dockerfile",
+    "helm",
+    "html",
+    "json",
+    "jsonc",
+    "json5",
+    "lua",
+    "luadoc",
+    "luap",
+    "markdown",
+    "markdown_inline",
+    "ninja",
+    "python",
+    "query",
+    "regex",
+    "ron",
+    "rst",
+    "rust",
+    "toml",
+    "vim",
+    "vimdoc",
+    "xml",
+    "yaml",
+}
+
+---@type lspconfig.options
+M.lsp = {
+    intelephense = {
+        init_options = {
+            storagePath = os.getenv("XDG_CACHE_HOME") .. "/intelephense",
+            globalStoragePath = os.getenv("XDG_CONFIG_HOME") .. "/intelephense",
+            licenceKey = require("lib").get_secret("intelephense")
+        },
+    },
+    jsonls = {
+        on_new_config = function(new_config)
+            new_config.settings.json.schemas = new_config.settings.json.schemas or {}
+            vim.list_extend(new_config.settings.json.schemas, require("schemastore").json.schemas())
+        end,
+        settings = {
+            json = {
+                format = {
+                    enable = true,
+                },
+                validate = { enable = true },
+            },
+        },
+    },
+    lua_ls = {
+        settings = {
+            Lua = {
+                workspace = {
+                    checkThirdParty = false,
+                },
+                codeLens = {
+                    enable = true,
+                },
+                completion = {
+                    callSnippet = "Replace",
+                },
+            },
+        },
+    },
+    ruff_lsp = {
+        keys = {
+            {
+                "<leader>co",
+                function()
+                    vim.lsp.buf.code_action({
+                        apply = true,
+                        context = {
+                            only = { "source.organizeImports" },
+                            diagnostics = {},
+                        },
+                    })
+                end,
+                desc = "Organize Imports",
+            },
+        },
+    },
+    yamlls = {
+        capabilities = {
+            textDocument = {
+                foldingRange = {
+                    dynamicRegistration = false,
+                    lineFoldingOnly = true,
+                },
+            },
+        },
+        on_new_config = function(new_config)
+            new_config.settings.yaml.schemas = vim.tbl_deep_extend(
+                "force",
+                new_config.settings.yaml.schemas or {},
+                require("schemastore").yaml.schemas()
+            )
+        end,
+        settings = {
+            redhat = { telemetry = { enabled = false } },
+            yaml = {
+                keyOrdering = false,
+                format = {
+                    enable = true,
+                },
+                validate = true,
+                schemaStore = {
+                    enable = false,
+                    url = "",
+                },
+            },
+        },
+    },
+}
+
+---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
+M.lsp_setup = {
+    ruff_lsp = function()
+        LazyVim.lsp.on_attach(function(client, _)
+            if client.name == "ruff_lsp" then
+                client.server_capabilities.hoverProvider = false
+                client.server_capabilities.renameProvider = false
+            end
+        end)
+    end,
+    rust_analyzer = function()
+        return true
+    end,
+    ["*"] = function(server, opts)
+        local base = vim.lsp.protocol.make_client_capabilities()
+        local cmp = require("cmp_nvim_lsp").default_capabilities()
+        vim.tbl_deep_extend("force", opts.capabilities, base)
+        vim.tbl_deep_extend("force", opts.capabilities, cmp)
+        require("lspconfig")[server].setup(opts)
+    end,
+}
+
+setmetatable(M, {
+    __index = function(_, k)
+        if k == "lsp" then
+            for l, _ in pairs(M.lsp) do
+                M.lsp[l].mason = false
+                return M.lsp
+            end
+        end
+        return require("custom." .. k)
+    end,
+})
+
+M.dap = {}
+
+return M
diff --git a/.config/nvim/lua/config/lazy.lua b/.config/nvim/lua/config/lazy.lua
new file mode 100644
index 00000000..afd12ea2
--- /dev/null
+++ b/.config/nvim/lua/config/lazy.lua
@@ -0,0 +1,51 @@
+local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
+
+if not (vim.uv or vim.loop).fs_stat(lazypath) then
+    vim.fn.system({
+        "git",
+        "clone",
+        "--filter=blob:none",
+        "https://github.com/folke/lazy.nvim.git",
+        "--branch=stable",
+        lazypath,
+    })
+end
+vim.opt.rtp:prepend(vim.env.LAZY or lazypath)
+
+require("lazy").setup({
+    spec = {
+        {
+            "LazyVim/LazyVim",
+            import = "lazyvim.plugins",
+        },
+        { import = "lazyvim.plugins.extras.coding.yanky" },
+        { import = "lazyvim.plugins.extras.coding.copilot" },
+        { import = "lazyvim.plugins.extras.ui.mini-indentscope" },
+        { import = "lazyvim.plugins.extras.dap.core" },
+        -- { import = "lazyvim.plugins.extras.ui.edgy" },
+        { import = "lazyvim.plugins.extras.editor.aerial" },
+        { import = "lazyvim.plugins.extras.editor.leap" },
+        { import = "lazyvim.plugins.extras.test.core" },
+        { import = "plugins" },
+    },
+    defaults = {
+        lazy = true,
+        version = false,
+    },
+    install = { colorscheme = { "tokyonight" } },
+    checker = { enabled = true },
+    performance = {
+        rtp = {
+            disabled_plugins = {
+                "gzip",
+                -- "matchit",
+                "matchparen",
+                "netrwPlugin",
+                "tarPlugin",
+                "tohtml",
+                "tutor",
+                "zipPlugin",
+            },
+        },
+    },
+})
diff --git a/.config/nvim/lua/config/options.lua b/.config/nvim/lua/config/options.lua
new file mode 100644
index 00000000..ae8f5528
--- /dev/null
+++ b/.config/nvim/lua/config/options.lua
@@ -0,0 +1,16 @@
+-- Options are automatically loaded before lazy.nvim startup
+-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
+-- Add any additional options here
+
+local o = vim.opt
+local g = vim.g
+
+o.shiftwidth = 4
+o.tabstop = 4
+o.scrolloff = 8
+o.conceallevel = 0
+
+g.loaded_node_provider = 0
+g.loaded_perl_provider = 0
+g.loaded_python3_provider = 0
+g.loaded_ruby_provider = 0
diff --git a/.config/nvim/lua/config/shortcuts.lua b/.config/nvim/lua/config/shortcuts.lua
new file mode 100644
index 00000000..471ba0d9
--- /dev/null
+++ b/.config/nvim/lua/config/shortcuts.lua
@@ -0,0 +1,22 @@
+-- NOTE: Managed by shortcuts script
+---@class config.shortcuts
+return {
+    gh = "/home/luca",
+    gch = "/home/luca/.cache",
+    gcf = "/home/luca/.config",
+    gdt = "/home/luca/.local/share",
+    gst = "/home/luca/.local/state",
+    gsc = "/home/luca/.local/bin",
+    gle = "/home/luca/.local/libexec",
+    gmn = "/mnt",
+    gco = "/home/luca/Documents/dev",
+    gdl = "/home/luca/Downloads",
+    gdm = "/home/luca/Documents",
+    gdk = "/home/luca/Desktop",
+    gms = "/home/luca/Music",
+    gpc = "/home/luca/Pictures",
+    gvd = "/home/luca/Videos",
+    gds = "/home/luca/.local/share/stow/dots",
+    glg = "/home/luca/.local/log",
+    gsv = "/home/luca/.local/sv",
+}
diff --git a/.config/nvim/lua/config/ui.lua b/.config/nvim/lua/config/ui.lua
new file mode 100644
index 00000000..5d1abc13
--- /dev/null
+++ b/.config/nvim/lua/config/ui.lua
@@ -0,0 +1,121 @@
+---@class config.ui
+local M = {}
+
+---@type Array<string>
+M.banners = {
+    [[
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣶⣿⣿⣿⣷⣶⣤⡀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀
+⠀⣀⣴⣶⣶⣶⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀
+⣰⣿⣿⠿⠛⠿⢿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀
+⣿⣿⡇⠀⠀⠀⠀⠈⠛⢿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀
+⠹⣿⣧⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⡿⠛⠉⠀⢀⣿⣿⣿⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀
+⠀⠙⢿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣷⣶⣶⣶⣶⣶⣿⣿⣿⣿⣿⣿⣿⣿⣷⣤⣤⣶⣿⣿⣿⣿⣿⡿⠟⠁⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠉⠻⠷⡄⠀⠀⠀⠀⠀⠀⠀⠈⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⠉⠀⢀⣠⣤⣤⣄⡀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠋⠁⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣷⡀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⡀⠀⠀⠀⠀⣿⠟⠉⠉⠙⢿⣿⣿⣷
+⠀⠀⠀⣀⣠⣤⣤⣤⣶⣶⣶⣤⣤⠀⣴⣿⣿⣿⡿⠟⠛⠛⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠉⠀⠀⠀⢀⣼⣿⣿⡿
+⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠛⠻⠏⣼⣿⣿⡿⣋⣀⣤⣤⣴⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣄⣀⣠⣴⣾⣿⣿⡿⠁
+⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⡿⠋⠘⠿⠟⠛⠛⢻⣿⣿⣿⠋⠁⠈⠉⢿⣿⣿⣧⠀⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠉⠀⠀
+⠙⣷⣤⣀⠀⠀⠀⢀⣀⣤⣶⣿⡿⠋⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡟⠀⠀⠀⢠⣿⣿⣿⡟⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀
+⠀⠈⠛⠿⢿⣿⣿⣿⠿⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⡀⠀⢠⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⣷⣶⣶⣶⣶⣦⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣙⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⢶⣦⣤⣶⣾⣿⣿⡶⠈⠉⠛⠿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣤⣶⡿⠿⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+]],
+    [[
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡠⠤⠤⠤⠤⠤⠤⠤⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠤⠒⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⢀⡤⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠓⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⢀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⡴⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠳⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⢀⡞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢦⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⢀⡞⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢇⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⡾⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡆⠀⠀⠀⠀⠀⠀
+⠀⢸⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⡀⠀⠀⠀⠀⠀
+⠀⣾⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⡇⠀⠀⠀⠀⠀
+⢠⣯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⠀⠀⠀⠀⠀
+⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⠿⠟⠁⠀⠀⠀⠀⠀⠀⠘⢿⣿⣿⣿⠀⠀⠀⠀⠀
+⣸⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⣀⣀⣀⡀⠀⠀⢉⣿⣿⠀⠀⠀⠀⠀
+⣿⣿⣿⣿⣶⣦⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠻⠿⠿⠿⠟⠀⠀⣼⣿⡏⠀⠀⠀⠀⠀
+⠈⢻⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣤⣤⣀⡀⠀⠀⢀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡀⢀⣴⣿⣿⡇⠀⠀⠀⠀⠀
+⠀⠘⣿⣿⣿⣯⡉⠙⠛⠻⠿⢿⣿⣿⣿⣿⣿⣶⣿⣿⣿⣿⣶⣦⣄⣀⡀⠀⠀⠀⣀⣀⣠⣤⣾⣿⣿⣿⣿⣿⡟⠁⠀⠀⠀⠀⠀
+⠀⠀⠸⣿⣿⣿⣷⣤⠀⠀⠀⠀⠀⠉⠙⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠙⣿⣿⣿⣿⣿⣶⣀⠀⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠘⢿⣿⣿⣿⣿⣿⣿⣶⣶⣤⣄⠀⢀⠀⠉⢿⣿⣿⣿⣿⣿⣿⣿⣿⠉⠀⠈⠙⠛⠻⠿⠿⠿⠀⢀⣠⣴⣶⣦⡀⠀⠀
+⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣾⣿⣿⣿⣿⣿⣿⣿⣷⡀⢀⠀⠀⠀⠀⠀⠀⡀⢠⣿⠟⠉⠀⠀⠁⣀⡀
+⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣷⣤⣦⣀⣤⣿⣿⣿⡀⠀⢀⣠⣾⣿⣿
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠃
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠛⠻⠿⠿⠿⣿⡿⠿⠿⠿⠛⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀
+]],
+    [[
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢒⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢘⡈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢣⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡌⡦⢠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡐⣸⠂⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠸⡢⡀⠀⠀⠀⠀⠀⠔⣰⠏⡌⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⢖⡠⣨⠊⠒⠠⣀⢀⠊⣠⠃⡰⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠠⠀⠀⠠⠠⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⢰⠑⠚⠀⠀⠀⡉⠀⢇⡰⠀⠀⠀⠀⠀⢀⠠⠐⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠐⠤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠈⡄⠀⠀⠀⠀⠘⠠⠐⡇⠀⠀⠀⠠⠐⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⢃⠀⠀⠀⠀⠀⠀⢀⠁⠀⢀⠌⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠀⠀⠼⢄⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⢸⠀⠀⠀⠀⠀⠀⢸⠀⢠⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠎⠀⠀⠀⠀⠀⠈⠢⠄⠀⠀⠀⠀
+⠀⠀⢸⠀⠀⠀⠀⠀⠀⠸⠀⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠎⠀⠀⠀⠀⠀⠀⡠⠀⠈⢆⠀⠀⠀
+⠀⠀⠨⠀⠀⠀⠀⠀⠀⠀⢆⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠀⠀⠀⠀⠀⠀⡌⠀⠀⢎⠨⡄⠀⠀
+⠀⠀⠀⡂⠀⠀⠀⠀⠀⠀⠈⢎⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠇⠀⠀⠀⠀⠀⠸⠀⠀⢸⠸⢀⠇⠀⠀
+⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠡⢕⠠⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠀⠀⠀⠀⠀⠀⢐⠀⠀⠈⠢⠥⠀⠀⠀
+⠀⠀⠀⢱⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⡉⠒⠠⣀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠰⡀⠀⠀⡰⠁⠀⠀⠀
+⠀⠀⠀⠀⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠑⠠⢄⠈⠑⠒⠤⡀⠀⢐⠅⠀⠀⠀⠀⠀⠀⠀⡁⡂⠉⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠈⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠂⠤⢀⠓⠈⠢⢀⢀⠠⠤⠐⠀⡉⠌⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠰⠐⠪⠤⢀⢀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⠀⠀⠀⠈⠁⠢⠄⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠂⠒⡠⠄
+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠀⠂⠐⠐⠐⠂⠂⠠⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠄⠐⠂⠂⠀⠉⠀⠀⠀
+]],
+}
+
+---@type Array<table>
+M.buttons = {
+    -- {
+    --     action = LazyVim.telescope("files"),
+    --     desc = " Find File" .. string.rep(" ", 33),
+    --     icon = " ",
+    --     key = "f",
+    -- },
+    {
+        action = "enew",
+        desc = " New File" .. string.rep(" ", 34),
+        icon = " ",
+        key = "n",
+    },
+    -- {
+    --     action = "Telescope live_grep",
+    --     desc = " Find Text" .. string.rep(" ", 33),
+    --     icon = " ",
+    --     key = "g",
+    -- },
+    -- {
+    --     action = "TodoTelescope",
+    --     desc = " Find Todo" .. string.rep(" ", 33),
+    --     icon = "󰱒 ",
+    --     key = "t",
+    -- },
+    {
+        action = 'lua require("persistence").load()',
+        desc = " Restore Session" .. string.rep(" ", 27),
+        icon = " ",
+        key = "s",
+    },
+    {
+        action = "qa",
+        desc = " Quit" .. string.rep(" ", 38),
+        icon = " ",
+        key = "q",
+    },
+}
+
+return M
diff --git a/.config/nvim/lua/lib.lua b/.config/nvim/lua/lib.lua
new file mode 100644
index 00000000..c3224134
--- /dev/null
+++ b/.config/nvim/lua/lib.lua
@@ -0,0 +1,25 @@
+local M = {}
+
+---@return table<string, function>
+function M.generate_shortcut_maps()
+    local shortcuts = Config.shortcuts
+    local fs = require("neo-tree.sources.filesystem")
+    local maps = {}
+    for map, path in pairs(shortcuts) do
+        maps[map] = function(state)
+            fs._navigate_internal(state, path, nil, nil, false)
+        end
+    end
+    return maps
+end
+
+---@param key string
+---@return string?
+function M.get_secret(key)
+    local ok, keys = pcall(require, "config.secrets")
+    if ok then
+        return keys[key]
+    end
+end
+
+return M
diff --git a/.config/nvim/lua/plugins/coding.lua b/.config/nvim/lua/plugins/coding.lua
new file mode 100644
index 00000000..7ee8847d
--- /dev/null
+++ b/.config/nvim/lua/plugins/coding.lua
@@ -0,0 +1,23 @@
+return {
+    {
+        "echasnovski/mini.surround",
+        opts = {
+            custom_surroundings = {
+                B = {
+                    input = { "{{ ().*() }}" },
+                    output = { left = "{{ ", right = " }}" },
+                },
+            },
+        },
+    },
+    {
+        "echasnovski/mini.ai",
+        opts = {
+            custom_textobjects = {
+                B = {
+                    require("mini.ai").gen_spec.pair("{{ ", " }}"),
+                },
+            },
+        },
+    },
+}
diff --git a/.config/nvim/lua/plugins/editor.lua b/.config/nvim/lua/plugins/editor.lua
new file mode 100644
index 00000000..10c30115
--- /dev/null
+++ b/.config/nvim/lua/plugins/editor.lua
@@ -0,0 +1,308 @@
+---@type LazySpec
+return {
+    {
+        "ggandor/flit.nvim",
+        enabled = false,
+    },
+    {
+        "NvChad/nvim-colorizer.lua",
+        cmd = { "ColorizerToggle", "ColorizerAttachToBuffer", "ColorizerDetachFromBuffer", "ColorizerReloadAllBuffers" },
+        opts = { user_default_options = { names = false } },
+        keys = { { "<leader>uH", "<cmd>ColorizerToggle<cr>", desc = "Toggle Colorizer" } },
+    },
+    {
+        "CopilotC-Nvim/CopilotChat.nvim",
+        dependencies = {
+            { "zbirenbaum/copilot.lua" },
+            { "nvim-lua/plenary.nvim" },
+            {
+                "folke/which-key.nvim",
+                optional = true,
+                opts = { defaults = { ["<leader>a"] = { name = "+ai" }, ["<leader>ac"] = { name = "+copilot" } } },
+            },
+        },
+        keys = {
+            { "<leader>acc", "<cmd>CopilotChatToggle<cr>", desc = "Toggle Chat", mode = { "n", "v" } },
+            { "<leader>acx", "<cmd>CopilotChatReset<cr>", desc = "Reset Chat", mode = { "n", "v" } },
+            { "<leader>acf", "<cmd>CopilotChatFix<cr>", desc = "Fix Selection", mode = { "v" } },
+            { "<leader>ace", "<cmd>CopilotChatExplain<cr>", desc = "Explain Selection", mode = { "v" } },
+            { "<leader>acr", "<cmd>CopilotChatExplain<cr>", desc = "Review Selection", mode = { "v" } },
+            { "<leader>aco", "<cmd>CopilotChatOptimize<cr>", desc = "Optimize Selection", mode = { "v" } },
+            { "<leader>acd", "<cmd>CopilotChatDocs<cr>", desc = "Document Selection", mode = { "v" } },
+            { "<leader>act", "<cmd>CopilotChatTests<cr>", desc = "Unittest Selection", mode = { "v" } },
+        },
+        opts = {
+            window = {
+                layout = "float",
+                width = 0.9,
+                height = 0.8,
+            },
+            mappings = {
+                complete = {
+                    detail = "Use @<Tab> or /<Tab> for options.",
+                    insert = "<Tab>",
+                },
+                close = {
+                    normal = "q",
+                    insert = "<C-c>",
+                },
+                reset = {
+                    normal = "<C-l>",
+                    insert = "<C-l>",
+                },
+                submit_prompt = {
+                    normal = "<CR>",
+                    insert = "<C-CR>",
+                },
+                accept_diff = {
+                    normal = "<C-y>",
+                    insert = "<C-y>",
+                },
+                yank_diff = {
+                    normal = "gy",
+                },
+                show_diff = {
+                    normal = "gd",
+                },
+                show_system_prompt = {
+                    normal = "gp",
+                },
+                show_user_selection = {
+                    normal = "gs",
+                },
+            },
+        },
+    },
+    {
+        "jackMort/ChatGPT.nvim",
+        cmd = { "ChatGPT", "ChatGPTActAs", "ChatGPTEditWithInstructions", "ChatGPTRun" },
+        dependencies = {
+            "MunifTanjim/nui.nvim",
+            "nvim-lua/plenary.nvim",
+            "folke/trouble.nvim",
+            "nvim-telescope/telescope.nvim",
+            {
+                "folke/which-key.nvim",
+                optional = true,
+                opts = {
+                    defaults = {
+                        ["<leader>a"] = { name = "+ai" },
+                        ["<leader>ag"] = { name = "+chatgpt" },
+                        ["<leader>agt"] = { name = "+translate" },
+                    },
+                },
+            },
+        },
+        config = function(_, opts)
+            local key = Lib.get_secret("openai")
+            if key then
+                require("chatgpt.api").OPENAI_API_KEY = key
+                require("chatgpt.api").AUTHORIZATION_HEADER = "Authorization: Bearer " .. key
+                require("chatgpt").setup(opts)
+            end
+        end,
+        --stylua: ignore
+        keys = {
+            { "<leader>agc",  function() require("chatgpt").openChat() end,                                              desc = "Toggle Chat" },
+            { "<leader>age",  function() require("chatgpt").edit_with_instructions() end,                                desc = "Edit with instruction",     mode = { "n", "v" } },
+            { "<leader>agg",  function() require("chatgpt").run_action("grammar_correction") end,                        desc = "Grammar Correction",        mode = { "n", "v" } },
+            { "<leader>agtg", function() require("chatgpt").run_action({ fargs = { "translate", "german" } }) end,       desc = "German",                    mode = { "n", "v" } },
+            { "<leader>agte", function() require("chatgpt").run_action({ fargs = { "translate", "english" } }) end,      desc = "English",                   mode = { "n", "v" } },
+            { "<leader>agtf", function() require("chatgpt").run_action({ fargs = { "translate", "french" } }) end,       desc = "French",                    mode = { "n", "v" } },
+            { "<leader>agtr", function() require("chatgpt").run_action({ fargs = { "translate", "russian" } }) end,      desc = "Russian",                   mode = { "n", "v" } },
+            { "<leader>agk",  function() require("chatgpt").run_action({ fargs = { "keywords" } }) end,                  desc = "Keywords",                  mode = { "n", "v" } },
+            { "<leader>agd",  function() require("chatgpt").run_action({ fargs = { "docstring" } }) end,                 desc = "Docstring",                 mode = { "n", "v" } },
+            { "<leader>aga",  function() require("chatgpt").run_action({ fargs = { "add_tests" } }) end,                 desc = "Add Tests",                 mode = { "n", "v" } },
+            { "<leader>ago",  function() require("chatgpt").run_action({ fargs = { "optimize_code" } }) end,             desc = "Optimize Code",             mode = { "n", "v" } },
+            { "<leader>ags",  function() require("chatgpt").run_action({ fargs = { "summarize" } }) end,                 desc = "Summarize",                 mode = { "n", "v" } },
+            { "<leader>agf",  function() require("chatgpt").run_action({ fargs = { "fix_bugs" } }) end,                  desc = "Fix Bugs",                  mode = { "n", "v" } },
+            { "<leader>agx",  function() require("chatgpt").run_action({ fargs = { "explain_code" } }) end,              desc = "Explain Code",              mode = { "n", "v" } },
+            { "<leader>agr",  function() require("chatgpt").run_action({ fargs = { "roxygen_edit" } }) end,              desc = "Roxygen Edit",              mode = { "n", "v" } },
+            { "<leader>agl",  function() require("chatgpt").run_action({ fargs = { "code_readability_analysis" } }) end, desc = "Code Readability Analysis", mode = { "n", "v" } },
+        },
+        opts = {
+            edit_with_instructions = {
+                keymaps = {
+                    close = "<C-c>",
+                    accept = "<C-y>",
+                    toggle_diff = "<C-d>",
+                    toggle_settings = "<C-o>",
+                    toggle_help = "<C-.>",
+                    cycle_windows = "<Tab>",
+                    use_output_as_input = "<C-,>",
+                },
+            },
+            chat = {
+                question_sign = "",
+                answer_sign = "󰚩",
+                sessions_window = {
+                    active_sign = " 󰭹 ",
+                    inactive_sign = " 󰻞 ",
+                    current_line_sign = "",
+                    border = {
+                        style = "single",
+                    },
+                    win_options = {
+                        winhighlight = "Normal:NormalFloat,FloatBorder:FloatBorder",
+                    },
+                },
+                keymaps = {
+                    close = "<C-c>",
+                    yank_last = "<C-y>",
+                    yank_last_code = "<C-p>",
+                    scroll_up = "<C-u>",
+                    scroll_down = "<C-d>",
+                    new_session = "<C-g>",
+                    cycle_windows = "<Tab>",
+                    cycle_modes = "<C-f>",
+                    next_message = "<C-n>",
+                    prev_message = "<C-p>",
+                    select_session = "<Space>",
+                    rename_session = "r",
+                    delete_session = "d",
+                    draft_message = "<C-r>",
+                    edit_message = "e",
+                    delete_message = "d",
+                    toggle_settings = "<C-o>",
+                    toggle_sessions = "<C-s>",
+                    toggle_help = "<C-.>",
+                    toggle_message_role = "<C-,>",
+                    toggle_system_role_open = "<C-'>",
+                    stop_generating = "<C-x>",
+                },
+            },
+            popup_layout = {
+                default = "center",
+                center = {
+                    width = "90%",
+                    height = "80%",
+                },
+                right = {
+                    width = "30%",
+                    width_settings_open = "50%",
+                },
+            },
+            popup_window = {
+                border = {
+                    style = "single",
+                },
+                win_options = {
+                    winhighlight = "Normal:NormalFloat,FloatBorder:FloatBorder",
+                },
+            },
+            system_window = {
+                border = {
+                    style = "single",
+                },
+                win_options = {
+                    winhighlight = "Normal:NormalFloat,FloatBorder:FloatBorder",
+                },
+            },
+            popup_input = {
+                border = {
+                    style = "single",
+                },
+                win_options = {
+                    winhighlight = "Normal:NormalFloat,FloatBorder:FloatBorder",
+                },
+                submit = "<C-Enter>",
+                submit_n = "<Enter>",
+            },
+            settings_window = {
+                border = {
+                    style = "single",
+                },
+                win_options = {
+                    winhighlight = "Normal:NormalFloat,FloatBorder:FloatBorder",
+                },
+            },
+            help_window = {
+                border = {
+                    style = "single",
+                },
+                win_options = {
+                    winhighlight = "Normal:NormalFloat,FloatBorder:FloatBorder",
+                },
+            },
+            openai_params = {
+                -- model = "gpt-3.5-turbo",
+                model = "gpt-4-turbo",
+            },
+            openai_edit_params = {
+                -- model = "gpt-3.5-turbo",
+                model = "gpt-4-turbo",
+            },
+        },
+    },
+    {
+        "nvim-neo-tree/neo-tree.nvim",
+        opts = {
+            filesystem = {
+                window = {
+                    mappings = Lib.generate_shortcut_maps(),
+                },
+            },
+        },
+    },
+    {
+        "folke/todo-comments.nvim",
+        opts = {
+            highlight = {
+                multiline = false,
+            },
+        },
+    },
+    {
+        "zk-org/zk-nvim",
+        ft = { "markdown" },
+        main = "zk",
+        dependencies = {
+            {
+                "folke/which-key.nvim",
+                optional = true,
+                opts = { defaults = { ["<leader>z"] = { name = "+zk" } } },
+            },
+        },
+        opts = {
+            picker = "telescope",
+            lsp = {
+                cmd = { "zk", "lsp" },
+                name = "zk",
+                config = {
+                    on_attach = function(client)
+                        if client.name == "zk" then
+                            require("zk").cd()
+                        end
+                    end,
+                },
+                auto_attach = {
+                    enabled = true,
+                    filetypes = { "markdown" },
+                },
+            },
+        },
+        --stylua: ignore
+        keys = {
+            { "<leader>zn",  function() require("zk.commands").get("ZkNew")({ title = vim.fn.input('Title: ') }) end, desc = "New Note",             mode = { "n", "v" } },
+            { "<leader>znt", function() require("zk.commands").get("ZkNewFromTitleSelection")() end,                  desc = "Title from selection", mode = { "v" } },
+            {
+                "<leader>znc",
+                function()
+                    require("zk.commands").get("ZkNewFromContentSelection")({
+                        title = vim.fn.input(
+                            'Title: ')
+                    })
+                end,
+                desc = "Content from selection",
+                mode = { "v" }
+            },
+            { "<leader>zb", function() require("zk.commands").get("ZkBacklinks")() end,                      desc = "Links" },
+            { "<leader>zl", function() require("zk.commands").get("ZkLinks")() end,                          desc = "Backlinks" },
+            { "<leader>zx", function() require("zk.commands").get("ZkIndex")() end,                          desc = "Index" },
+            { "<leader>zf", function() require("zk.commands").get("ZkNotes")({ sort = { 'modified' } }) end, desc = "Find Notes" },
+            { "<leader>zt", function() require("zk.commands").get("ZkTags")() end,                           desc = "Find Note Tags" },
+            { "<leader>zf", function() require("zk.commands").get("ZkMatch")() end,                          desc = "Find Notes (Match Selection)", mode = { "v" } },
+            { "<leader>zi", function() require("zk.commands").get("ZkInsertLinkAtSelection")() end,          desc = "Insert Link",                  mode = { "n", "v" } },
+        },
+    },
+}
diff --git a/.config/nvim/lua/plugins/language.lua b/.config/nvim/lua/plugins/language.lua
new file mode 100644
index 00000000..b196f7af
--- /dev/null
+++ b/.config/nvim/lua/plugins/language.lua
@@ -0,0 +1,232 @@
+---@type LazySpec
+return {
+    {
+        "nvim-treesitter/nvim-treesitter",
+        opts = {
+            auto_install = true,
+            ensure_installed = Config.language.treesitter_install,
+            highlight = {
+                additional_vim_regex_highlighting = { "markdown" },
+            },
+        },
+    },
+    {
+        "stevearc/conform.nvim",
+        opts = {
+            formatters_by_ft = Config.language.formatters_by_ft,
+            formatters = Config.language.formatters,
+        },
+    },
+    {
+        "neovim/nvim-lspconfig",
+        opts = {
+            servers = Config.language.lsp,
+            setup = Config.language.lsp_setup,
+        },
+    },
+    {
+        "mfussenegger/nvim-lint",
+        opts = {
+            linters_by_ft = Config.language.linters_by_ft,
+            linters = Config.language.linters,
+        },
+    },
+    {
+        "williamboman/mason.nvim",
+        opts = {
+            ensure_installed = Config.language.mason_install,
+        },
+    },
+    {
+        "hrsh7th/nvim-cmp",
+        opts = function(_, opts)
+            table.insert(opts.auto_brackets, "python")
+
+            table.insert(opts.sources, { name = "crates" })
+
+            opts.experimental = {
+                ghost_text = false,
+            }
+
+            -- local cmp = require("cmp")
+            -- local luasnip = require("luasnip")
+            --
+            -- opts.preselect = cmp.PreselectMode.None
+            -- opts.snippet = {
+            --     expand = function(args)
+            --         require("luasnip").lsp_expand(args.body)
+            --     end,
+            -- }
+            -- opts.mapping = {
+            --     ["<Up>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
+            --     ["<Down>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
+            --     ["<C-Space>"] = cmp.mapping(function(fallback)
+            --         if cmp.visible() then
+            --             if luasnip.expandable() then
+            --                 luasnip.expand()
+            --             else
+            --                 cmp.confirm({
+            --                     select = true,
+            --                 })
+            --             end
+            --         else
+            --             fallback()
+            --         end
+            --     end),
+            --
+            --     ["<Tab>"] = cmp.mapping(function(fallback)
+            --         if cmp.visible() then
+            --             cmp.select_next_item()
+            --         elseif luasnip.locally_jumpable(1) then
+            --             luasnip.jump(1)
+            --         else
+            --             fallback()
+            --         end
+            --     end, { "i", "s" }),
+            --
+            --     ["<S-Tab>"] = cmp.mapping(function(fallback)
+            --         if cmp.visible() then
+            --             cmp.select_prev_item()
+            --         elseif luasnip.locally_jumpable(-1) then
+            --             luasnip.jump(-1)
+            --         else
+            --             fallback()
+            --         end
+            --     end, { "i", "s" }),
+            -- }
+        end,
+    },
+    {
+        "towolf/vim-helm",
+        ft = "helm",
+    },
+    {
+        "mfussenegger/nvim-ansible",
+        keys = {
+            {
+                "<leader>tr",
+                function()
+                    require("ansible").run()
+                end,
+                silent = true,
+            },
+        },
+        {
+            "b0o/SchemaStore.nvim",
+            lazy = true,
+            version = false,
+        },
+    },
+    {
+        "iamcco/markdown-preview.nvim",
+        cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" },
+        build = function()
+            vim.fn["mkdp#util#install"]()
+        end,
+        keys = {
+            {
+                "<leader>cp",
+                ft = "markdown",
+                "<cmd>MarkdownPreviewToggle<cr>",
+                desc = "Markdown Preview",
+            },
+        },
+        config = function()
+            vim.cmd([[do FileType]])
+        end,
+    },
+    {
+        "nvim-neotest/neotest",
+        dependencies = {
+            "nvim-neotest/neotest-python",
+        },
+        opts = function(_, opts)
+            local _, rt = pcall(require, "rustaceanvim.neotest")
+            opts.adapters = vim.tbl_deep_extend("force", opts.adapters, {
+                ["neotest-python"] = {},
+                rt,
+            })
+        end,
+    },
+    {
+        "mfussenegger/nvim-dap-python",
+        -- stylua: ignore
+        keys = {
+            { "<leader>dPt", function() require("dap-python").test_method() end, desc = "Debug Method", ft = "python" },
+            { "<leader>dPc", function() require("dap-python").test_class() end,  desc = "Debug Class",  ft = "python" },
+        },
+        config = function()
+            local path = require("mason-registry").get_package("debugpy"):get_install_path()
+            require("dap-python").setup(path .. "/venv/bin/python")
+        end,
+    },
+    {
+        "linux-cultist/venv-selector.nvim",
+        cmd = "VenvSelect",
+        opts = function(_, opts)
+            if LazyVim.has("nvim-dap-python") then
+                opts.dap_enabled = true
+            end
+            return vim.tbl_deep_extend("force", opts, {
+                name = {
+                    "venv",
+                    ".venv",
+                    "env",
+                    ".env",
+                },
+            })
+        end,
+        keys = { { "<leader>cv", "<cmd>:VenvSelect<cr>", desc = "Select VirtualEnv" } },
+    },
+    {
+        "Saecki/crates.nvim",
+        event = { "BufRead Cargo.toml" },
+        opts = {
+            src = {
+                cmp = { enabled = true },
+            },
+        },
+    },
+    {
+        "mrcjkb/rustaceanvim",
+        version = "^4",
+        ft = { "rust" },
+        opts = {
+            server = {
+                on_attach = function(_, bufnr)
+                    vim.keymap.set("n", "<leader>cR", function()
+                        vim.cmd.RustLsp("codeAction")
+                    end, { desc = "Code Action", buffer = bufnr })
+                    vim.keymap.set("n", "<leader>dr", function()
+                        vim.cmd.RustLsp("debuggables")
+                    end, { desc = "Rust Debuggables", buffer = bufnr })
+                end,
+                default_settings = {
+                    ["rust-analyzer"] = {
+                        cargo = {
+                            allFeatures = true,
+                            loadOutDirsFromCheck = true,
+                            runBuildScripts = true,
+                        },
+                        checkOnSave = {
+                            allFeatures = true,
+                            command = "clippy",
+                            extraArgs = { "--no-deps" },
+                        },
+                        procMacro = {
+                            enable = true,
+                            ignored = {
+                                ["async-trait"] = { "async_trait" },
+                                ["napi-derive"] = { "napi" },
+                                ["async-recursion"] = { "async_recursion" },
+                            },
+                        },
+                    },
+                },
+            },
+        },
+        config = function(_, opts)
+            vim.g.rustaceanvim = vim.tbl_deep_extend("keep", vim.g.rustaceanvim or {}, opts or {})
+        end,
+    },
+}
diff --git a/.config/nvim/lua/plugins/ui.lua b/.config/nvim/lua/plugins/ui.lua
new file mode 100644
index 00000000..43679800
--- /dev/null
+++ b/.config/nvim/lua/plugins/ui.lua
@@ -0,0 +1,84 @@
+---@type LazySpec
+return {
+    {
+        "folke/tokyonight.nvim",
+        lazy = true,
+        opts = {
+            style = "night",
+            on_colors = function(c)
+                c.border = c.bg_highlight
+                c.border_highlight = c.blue
+            end,
+            on_highlights = function(hl, _)
+                hl.CurSearch = nil
+            end,
+        },
+    },
+    {
+        "folke/noice.nvim",
+        opts = {
+            cmdline = {
+                view = "cmdline",
+                presets = {
+                    command_palette = false,
+                },
+            },
+        },
+    },
+    {
+        "nvimdev/dashboard-nvim",
+        opts = function(_, opts)
+            local center = Config.ui.buttons
+            local banners = Config.ui.banners
+            for _, button in ipairs(center) do
+                button.desc = button.desc .. string.rep(" ", 43 - #button.desc)
+                button.key_format = "  %s"
+            end
+            math.randomseed(os.time())
+            local banner = "\n" .. banners[math.random(#banners)] .. "\n"
+            opts.config.header = vim.split(banner, "\n")
+            opts.config.center = center
+            opts.config.footer = function()
+                local stats = require("lazy").stats()
+                local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100)
+                return { "Behold: a Snail's Vim | " .. stats.count .. "  " .. ms .. "ms" }
+            end
+        end,
+    },
+    {
+        "echasnovski/mini.indentscope",
+        opts = {
+            draw = {
+                animation = require("mini.indentscope").gen_animation.none(),
+            },
+        },
+    },
+    {
+        "nvim-lualine/lualine.nvim",
+        opts = {
+            sections = {
+                lualine_y = {
+                    {
+                        function()
+                            --stylua: ignore
+                            local chars = { "", "", "", "", "", "", "", "", "", "", "", "", "" }
+                            return chars[math.ceil(vim.fn.line(".") / vim.fn.line("$") * #chars)]
+                        end,
+                        separator = " ",
+                        padding = { left = 1, right = 0 },
+                    },
+                    { "location", padding = { left = 0, right = 1 } },
+                },
+                lualine_z = {
+                    {
+                        "o:encoding",
+                        fmt = string.upper,
+                        separator = " ",
+                        padding = { left = 1, right = 0 },
+                    },
+                    { "fileformat", padding = { left = 0, right = 1 } },
+                },
+            },
+        },
+    },
+}
diff --git a/.config/nvim/spell/en.utf-8.add b/.config/nvim/spell/en.utf-8.add
new file mode 100644
index 00000000..8cbb1484
--- /dev/null
+++ b/.config/nvim/spell/en.utf-8.add
@@ -0,0 +1,10 @@
+ansible
+submodules
+roundcube
+postgres
+binpkgs
+hostdir
+config
+wireguard
+Webchecks
+fail2ban
diff --git a/.config/nvim/stylua.toml b/.config/nvim/stylua.toml
new file mode 100644
index 00000000..e55efd51
--- /dev/null
+++ b/.config/nvim/stylua.toml
@@ -0,0 +1,3 @@
+indent_type = "Spaces"
+indent_width = 4
+column_width = 120