UPDATE: I no longer use this approach. I still have obsidian.nvim in my nvim configuration, however I mainly take notes through Obsidian instead.

I realized that the context switch actually helps makes me focus more and slow down a bit when taking notes, which results in better quality notes I believe.

Also, since I use hyprland, Obsidian just stays open on one of my workspaces all the time, and the switch is not a big deal.

Of course, feel free to refer to this blog if it is helpful to you in any way, but be warned that obsidian.nvim api might have also changed since this was not updated for so long.


Recently, I started using obsidian.nvim to edit notes in
neovim instead of obsidian. The goal, as described by the obsidian.nvim developer, is that I enjoy
the neovim experience so much that I prefer editing notes in it rather than obsidian. I still use
obsidian for viewing and certain editing workflows (such as excalidraw), but most of my note-taking
time is spent in neovim.

The experience so far has been good. However, I have noticed a lack of support for certain workflows.
In the following sections, I will discuss these workflows and then explain how I implemented a custom
lua function and nvim keymaps for them.

Note Capture Link to this heading

Sometimes, you simply want to quickly jot down some notes without worrying about where to put them or
their structure. Later on, you can review and process those notes along with others.

One example would be when you are coding. Suppose you have discovered that a library function you are
using is buggy, and you do not want to forget what causes the bug, or for some other similar reason.

In this example, during the normal workflow, you would determine a location to save the file, decide
on its name and structure, and additionally, implement a mechanism to ensure that you do not forget this
note later on.

This workflow is too distracting for me, and I easily lose focus on what I was previously working on.
Yes, it is possible to automate this through neovim configuration, but there is still the problem of
having two different “note-taking mechanisms” if you are also using Obsidian and cannot really give it up
in favor of neovim for note taking.

The workflow I desire for this “capture” process is as follows:

  • Quickly create a capture note on a split window using a keymap.
  • The note should be saved in a subfolder named ‘capture’ within the Obsidian vault.
  • The note’s name should be in the ‘zettelkasten’ style ISO time stamp format.

Notes with templates Link to this heading

Another workflow involves automatically creating notes using specific templates. For instance, you can
create a blog post note (similar to this one) with specific front matter lines that you configure for
your static site generator configuration or other use cases. Ideally, this note would be stored in a
different subfolder as well.

obsidian.nvim already provides “templating” functionality with the ObsidianTemplate command, which
opens a telescope window listing the templates in your vault. When you select a template, it is applied
to the file. This feature is convenient and works perfectly fine. However, I would like to have specific
templates automatically applied to files created in specific subfolders immediately after they are created.

The desired workflow for this “templating” process is as follows:

  • Create a note quickly on a split window using a keymap.
  • The note should be saved in a specific subfolder within the Obsidian vault.
  • Immediately apply a template specific to the subfolder to the note.

As you can see, this workflow is more generic, although it shares some similarities with the previous one.
Let’s proceed to the next section where we will set these up.

obsidian.nvim configuration Link to this heading

Before we proceed with implementing our own note function, we should first check some of the options
available in obsidian.nvim, beginning with opening notes on a split window.

Opening notes in a split window Link to this heading

In both workflows, I want to open notes in a split window. Obsidian.nvim already has an option
called open_notes_in for this purpose. However, as you will see, in our lua function for
creating new notes, we will have to accomplish this using lua code because the notes created
through that function will not be managed by obsidian.nvim for opening in a split.

Notes without a file name Link to this heading

We will prompt through neovim for the file name of the new note when we are creating a regular
note. However, what occurs when no file name is provided? By default, obsidian.nvim generates a
random filename/id that consists of a timestamp and random strings.

This can be changed via note_id_func. In our case, as we will see later, we want the
yymmddHHMMSS format for our file names if a file name is not given.

To manage or not to manage front matter Link to this heading

If you set disable_frontmatter = false, obsidian.nvim is able to handle the front matter of your notes.
You can customize it by defining a function for note_id_func. I was initially using this approach, but
found it limiting after a while.

The first reason is that you cannot selectively manage the front matter. What I mean by this is that for
certain notes in specific subfolders (such as ‘capture’), I do not want any front matter management or any
front matter at all.

The second reason is that I want to apply templates immediately after the note is created, which makes
front matter management completely unnecessary.

The obsidian.nvim configuration Link to this heading

Based on the points mentioned earlier, I have the following (partial) configuration in my neovim
configs for obsidian.nvim:

lua
 1-- ...
 2
 3open_notes_in = "vsplit",
 4disable_frontmatter = true,
 5templates = {
 6    subdir = "templates",
 7    date_format = "%Y-%m-%d",
 8    time_format = "%H:%M",
 9    -- A map for custom variables, the key should be the variable and the value a function
10    substitutions = {},
11},
12note_id_func = function(title)
13    -- If title is not given, use ISO timestamp, otherwise use as is
14    if title == nil then
15        return tostring(os.date("%y%m%d%H%M%S"))
16    end
17    return title
18end,
19note_frontmatter_func = function(note)
20    return {} -- return empty as we don't manage front matter anyway
21end,
22
23-- ...

Please note that I have also added the templates option here in case you want to include
custom variables that will be used with your obsidian templates.

The custom note creation function Link to this heading

Finally, here is the lua function I use for the workflows listed above:

lua
 1-- ...
 2
 3local client = require('obsidian').setup(...) -- save client after setup
 4
 5--- Create a note
 6--
 7---@param subdir string?
 8---@param ask_name boolean?
 9---@param template string?
10---@return nil
11local function new_note(subdir, ask_name, template)
12    -- get file name, otherwise use ISO timestamp
13    local fname = ""
14    if ask_name == true then
15        -- get file name from user input or return ""
16        inp = vim.fn.input("Name: ", "") 
17        
18        -- if no name given and ask_name == true, cancel note creation
19        if inp == "" then 
20            return
21        end
22
23        fname = inp
24    else
25        -- if ask_name == false, then assign timestamp for filename
26        fname = tostring(os.date("%y%m%d%H%M%S")) 
27    end
28
29    -- create query to check if note already exists
30    -- can be a file name or path to a file
31    local query = fname .. ".md"
32    if subdir ~= nil then
33        query = subdir .. "/" .. fname .. ".md"
34    end
35
36    -- try to find the note, and create if not found
37    -- if path given, checks all sub directories of the vault for the path
38    -- if file name is given, checks again all sub directories of the vault for the name
39    local note = client:resolve_note(query)
40    if note == nil then
41        note = client:new_note(fname, fname, client.dir .. "/" .. subdir)
42    end
43
44    -- create a split window and open note on that window
45    vim.cmd("vsplit")
46    vim.cmd("edit " .. tostring(note.path))
47
48    -- if a template is given, apply the template immediately
49    if template ~= nil then
50        vim.cmd("ObsidianTemplate " .. template .. ".md")
51    end
52end
53
54-- ...

Here you go. I have documented the function as well and hope it is easy to understand.
Now, let’s move on to the keymaps I have created for using this function.

lua
 1-- ...
 2
 3-- Create a permanent note on the vault root,
 4-- get file name from the input, and apply the 
 5-- "basic" template
 6vim.keymap.set("n", "<leader>nN", function()
 7    new_note(nil, true, "basic")
 8end, { noremap = true, desc = "Permanent Note" })
 9
10-- Create a capture note on 'capture' sub directory
11-- of the vault, use ISO timestamp as the file name,
12-- and don't apply any templates.
13vim.keymap.set("n", "<leader>nn", function()
14    new_note("capture", false, nil)
15end, { noremap = true, desc = "Capture Note" })
16
17-- Create a project note on 'project' sub directory
18-- of the vault, get file name from the input,
19-- and apply the "project" template
20vim.keymap.set("n", "<leader>np", function()
21    new_note("projects", true, "project")
22end, { noremap = true, desc = "Project Note" })
23
24-- Create a project note on 'blog' sub directory
25-- of the vault, get file name from the input,
26-- and apply the "blog" template
27vim.keymap.set("n", "<leader>nb", function()
28    new_note("blog", true, "blog")
29end, { noremap = true, desc = "Blog Note" })
30
31-- ...

I hope these were clear as well. I have other keybindings for obsidian.nvim as well,
but they are using the default commands so were not mentioned here. For example, I still
use ObisidianToday and ObsidianYesterday commands for journal notes. You can
see my configuration from
here.

Closing thoughts Link to this heading

I hope that this will be helpful for your note-taking setup as well. Personally, I really
enjoy this workflow. It motivates me to take more notes and I am much more productive when
coding, etc. This is because I can quickly jot down notes on things that I don’t need to
remember at the moment and instead, focus on my coding. Though would prefer to have a better
lua API from obsidian.nvim, but it is OSS so I can’t complain much.

I might add couple more custom functions for processing these ‘capture’ notes in bulk later,
or for more complex templating. I would be sure to share it here though, if I do implement
those (plug ‘follow me’ here - currently I don’t have the mechanism for follows yet, but
RSS should be available ( ͡❛ ‿‿ ͡❛) ).

Alright, long post already. See you later, byeee 👋