return {
	{
		'https://github.com/MeanderingProgrammer/render-markdown.nvim',
		ft = { 'markdown', 'codecompanion', 'gitcommit' },
		opts = function(_, opts)
			return vim.tbl_deep_extend('force', opts or {}, {
				preset = 'obsidian',
				render_modes = true,
				win_options = {
					-- disable ability to conceal text
					conceallevel = { rendered = 0 },
					concealcursor = { rendered = 'nvic' },
				},
				anti_conceal = {
					enabled = true,
					above = 1000,
					below = 1000,
					ignore = {
						head_icon = false,
						head_background = true,
						head_border = true,
						code_language = true,
						code_background = true,
						code_border = true,
						dash = true,
						bullet = true,
						check_icon = true,
						check_scope = true,
						quote = true,
						table_border = true,
						callout = true,
						link = true,
						sign = false,
					},
				},
				completions = {
					lsp = {
						enabled = true,
					},
					blink = {
						enabled = true,
					},
				},
				sign = { enabled = false },
				heading = {
					position = 'inline',
					icons = { '󰉫  ', '󰉬  ', '󰉭  ', '󰉮  ', '󰉯  ', '󰉰  ' },
					border = true,
					border_virtual = true,
				},
				code = {
					width = 'block',
					min_width = 45,
					border = 'thick',
					left_pad = 2,
					right_pad = 2,
				},
				link = {
					image = '󰥶  ',
					email = '󰀓  ',
					hyperlink = '󰌹  ',
					wiki = {
						icon = '󱗖  ',
					},
					custom = {
						web = { pattern = '^http', icon = '󰖟  ' },
						discord = { pattern = 'discord%.com', icon = '󰙯  ' },
						github = {
							pattern = 'github%.com',
							icon = require('mini.icons').get('directory', '.github') .. '  ',
						},
						gitlab = { pattern = 'gitlab%.com', icon = '󰮠  ' },
						google = { pattern = 'google%.com', icon = '󰊭  ' },
						neovim = { pattern = 'neovim%.io', icon = '  ' },
						reddit = { pattern = 'reddit%.com', icon = '󰑍  ' },
						stackoverflow = { pattern = 'stackoverflow%.com', icon = '󰓌  ' },
						wikipedia = { pattern = 'wikipedia%.org', icon = '󰖬  ' },
						youtube = { pattern = 'youtube%.com', icon = '󰗃  ' },
						file = {
							pattern = '^file:',
							icon = '  ',
						},
						miro = {
							pattern = 'miro%.com',
							icon = '  ',
						},
					},
				},
				pipe_table = {
					preset = 'heavy',
					cell = 'trimmed',
				},
				checkbox = {
					checked = { scope_highlight = '@markup.strikethrough' },
					custom = {
						wip = {
							raw = '[/]',
							rendered = '󰥔 ',
							highlight = 'RenderMarkdownTodo',
							scope_highlight = nil,
						},
						defer = {
							raw = '[>]',
							rendered = '󰃮 ',
							highlight = 'RenderMarkdownOk',
							scope_highlight = nil,
						},
						delegate = {
							raw = '[<]',
							rendered = '󰚎 ',
							highlight = 'RenderMarkdownOk',
							scope_highlight = nil,
						},
						question = {
							raw = '[?]',
							rendered = ' ',
							highlight = 'DiagnosticHint',
							scope_highlight = nil,
						},
						info = {
							raw = '[i]',
							rendered = ' ',
							highlight = 'RenderMarkdownInfo',
							scope_highlight = nil,
						},
						star = {
							raw = '[*]',
							rendered = ' ',
							highlight = 'DiagnosticWarn',
							scope_highlight = nil,
						},
						todo = { raw = '[_]' }, -- don't clobber [-]
						important = {
							raw = '[!]',
							rendered = ' ',
							highlight = 'RenderMarkdownWarn',
							-- scope_highlight = nil,
						},
						cancel = {
							raw = '[-]',
							rendered = '󰜺 ',
							highlight = 'RenderMarkdownWarn',
							scope_highlight = '@markup.strikethrough',
						},
					},
				},
				overrides = {
					filetype = {
						gitcommit = { heading = { enabled = false } },
					},
				},
				injections = {
					gitcommit = {
						enabled = true,
						query = [[
                ((message) @injection.content
                    (#set! injection.combined)
                    (#set! injection.include-children)
                    (#set! injection.language "markdown"))
            ]],
					},
				},
			})
		end,
	},
	{
		'https://github.com/davidmh/mdx.nvim',
		ft = { 'mdx' },
		opts = {},
	},
	{
		'https://github.com/zk-org/zk-nvim',
		config = function()
			-- I don't need the LSP I use markdown-oxide for that, I only need the commands. This is why I don't call .setup()
			require 'zk.commands.builtin'
		end,
	},
	{
		'https://github.com/obsidian-nvim/obsidian.nvim',
		version = '*',
		cmd = { 'Obsidian' },
		ft = { 'markdown' },
		dependencies = {
			'https://github.com/nvim-lua/plenary.nvim',
		},
		opts = {
			legacy_commands = false,
			workspaces = {
				{
					name = 'notes',
					path = vim.env.NOTES_DIR,
					strict = true,
					overrides = {
						attachments = {
							img_folder = vim.env.NOTES_DIR .. '/assets',
							img_name_func = function()
								return string.format(
									'%s/%s/Pasted image %s',
									vim.env.NOTES_DIR .. '/assets',
									vim.fn.expand '%:t:r',
									os.date '%Y%m%d%H%M%S'
								)
							end,
						},
					},
				},
				{
					name = 'no-vault',
					path = function()
						-- alternatively use the CWD:
						-- return assert(vim.fn.getcwd())
						return vim.fs.dirname(vim.api.nvim_buf_get_name(0))
					end,
					overrides = {
						disable_frontmatter = true,
						notes_subdir = vim.NIL, -- have to use 'vim.NIL' instead of 'nil'
						new_notes_location = 'current_dir',
						templates = {
							folder = vim.NIL,
						},
						attachments = {
							img_folder = 'assets',
						},
						daily_notes = {
							folder = vim.NIL,
						},
					},
				},
			},

			templates = {
				folder = '.zk/templates', -- must be relative to the root of the vault
				date_format = '%Y-%m-%d',
				time_format = '%H:%M',
				-- A map for custom variables, the key should be the variable and the value a function
				substitutions = {
					-- zk compatibility
					-- https://zk-org.github.io/zk/notes/template.html#date-formatting-helper
					['format-date now "%Y-%m-%dT%H:%M"'] = function()
						return os.date '%Y-%m-%dT%H:%M' -- 2025-04-01T12:05
					end,
					['format-date now "timestamp"'] = function()
						return os.date '%Y%m%d%H%M' -- 202504011205
					end,
					["format-date now '%Y-%m-%d'"] = function()
						return os.date '%Y-%m-%d' -- 2025-04-01
					end,
					['format-date now "long"'] = function()
						return os.date '%B %d, %Y' -- April 1, 2025
					end,
					['content'] = function()
						return ''
					end,
					['extra.employer'] = function()
						return vim.env.COMPANY or 'NO COMPANY'
					end,
				},
			},

			---@param title string|?
			---@return string
			note_id_func = function(title)
				local note_name = tostring(os.date '%Y%m%d%H%M')

				if title ~= nil then
					note_name = note_name
						.. ' '
						.. title:gsub(' ', '-'):gsub('[^A-Za-z0-9-]', ''):lower()
				end

				return note_name
			end,

			frontmatter = {
				-- Optional, alternatively you can customize the frontmatter data.
				---@return table
				func = function(note)
					local function convert_date(date_string)
						local year, month, day, hour, min

						-- Try to match date with time
						year, month, day, hour, min =
							date_string:match '(%d+)-(%d+)-(%d+)[T ](%d+):(%d+)'

						if not year then
							-- Try to match date only
							year, month, day = date_string:match '(%d+)-(%d+)-(%d+)'
							hour, min = 0, 0
						end

						if year then
							-- Create date table for os.time
							local date_table = {
								year = tonumber(year),
								month = tonumber(month),
								day = tonumber(day),
								hour = tonumber(hour) or 0,
								min = tonumber(min) or 0,
								sec = 0,
							}

							-- Convert to timestamp
							local timestamp = os.time(date_table)

							-- Format using os.date
							return os.date('%Y%m%d%H%M', timestamp)
						else
							return nil, 'Invalid date format'
						end
					end

					-- Add the title of the note as an alias.
					if note.title then
						note:add_alias(note.title)
					end

					local out = {
						aliases = note.aliases,
						tags = note.tags,
					}

					-- `note.metadata` contains any manually added fields in the frontmatter.
					-- So here we just make sure those fields are kept in the frontmatter.
					if note.metadata ~= nil and not vim.tbl_isempty(note.metadata) then
						for k, v in pairs(note.metadata) do
							out[k] = v
						end
					end

					-- We run this at the end so we have access to metadata too
					out.id = note.id
						or tostring(convert_date(note.metadata.date))
						or tostring(os.date '%Y%m%d%H%M')

					return out
				end,
			},

			daily_notes = {
				folder = 'journal',
				workdays_only = false,
				default_tags = { 'journal' },
				template = 'journal.md',
			},

			completion = {
				nvim_cmp = false,
				blink = false,
			},

			ui = {
				enable = false,
			},

			attachments = {
				img_folder = 'assets',
			},

			footer = {
				enabled = false,
			},
		},
	},
}
