# Notes setup
This directory contains the Neovim-side notes integration for the dotfiles repository. The setup keeps `zk` as the source of truth for note creation, uses `markdown_oxide` for Markdown/wiki-link LSP behavior, and normalizes frontmatter independently of Obsidian.nvim.
## Goals
- Create notes consistently from the CLI and Neovim.
- Keep note files compatible with the Obsidian desktop app by using plain Markdown, YAML frontmatter, and Obsidian-style wiki links.
- Let `markdown_oxide` handle workspace-aware Markdown LSP features such as hover, definitions, diagnostics, and missing-link actions.
- Keep frontmatter fallback behavior independent of Obsidian.nvim.
## Files
| File | Purpose |
| --- | --- |
| `init.lua` | Defines Neovim commands such as `:Note`, `:N`, `:NoteWork`, and `:NoteFrontmatter`. It calls `zk-nvim` for note creation and then normalizes frontmatter. |
| `frontmatter.lua` | Shared frontmatter normalization logic used by the Neovim commands. |
| `README.md` | This document. |
Related files outside this directory:
| File | Purpose |
| --- | --- |
| `config/nvim/plugin/markdown.lua` | Loads Markdown plugins, configures `zk-nvim` with its LSP disabled, and calls `require('_.notes').setup()`. |
| `config/nvim/plugin/lsp.lua` | Enables `markdown_oxide` as the Markdown LSP and makes navic prefer it for Markdown symbols. |
| `config/zk/config.toml` | Owns CLI note creation aliases, filename templates, group rules, and default templates. |
| `config/zk/templates/` | Owns the actual note content templates used by `zk` for CLI and Neovim-created notes. |
| `nix/parts/modules/shared/zk.nix` | Installs `zk` and links the `zk` config and templates. |
| `nix/parts/modules/shared/vim.nix` | Installs `markdown-oxide` and Neovim support tooling. |
## Creation model
`zk` is the only source of truth for creating intentional notes. This means filename generation, template expansion, group-specific behavior, and default frontmatter all come from `config/zk/config.toml` and `config/zk/templates/`.
The Neovim commands call `zk-nvim`'s API, which delegates to `zk`. They do not duplicate template rendering in Lua. Lua only decides which `zk` options to pass and then normalizes frontmatter after the file exists.
Prefer `:Note`/`:N` over the generic `:ZkNew` command for interactive note creation. `:ZkNew` remains available from `zk-nvim`, but `:Note` adds this repository's target parsing, command completion, and frontmatter normalization while still delegating note creation to `zk`.
## Neovim commands
### `:Note` and `:N`
`:Note` is the real command. `:N` is a command-line abbreviation because `:N` is already a built-in Ex command.
Examples:
```vim
:Note My root note
:N My root note
:Note work Planning note
:N personal Private note
:Note til Something I learned
:Note { dir = 'work', template = 'system-design.md', title = 'Queues' }
```
Default behavior creates a note at the root of `$NOTES_DIR`:
```vim
:N My root note
```
If the first argument is a known alias or an existing top-level subdirectory, that target is used and the rest of the command becomes the title:
```vim
:N work Team design note
:N projects Side project note
```
First-argument completion includes both configured aliases and top-level subdirectories under `$NOTES_DIR`. Hidden directories and `assets` are excluded from completion.
Bang form creates the note without opening it:
```vim
:N! Inbox note
```
### Convenience commands
These commands are thin wrappers around `:Note` aliases:
```vim
:NoteWork
:NotePersonal
:NoteTil
:NoteJournal
:NoteRfc
```
They exist for muscle memory and discoverability; the flexible `:Note`/`:N` command is the preferred base command.
### `:NoteFrontmatter`
`:NoteFrontmatter` normalizes frontmatter in the current buffer without writing the file.
`:NoteFrontmatter!` normalizes frontmatter and writes the file.
This command is useful for existing notes, notes created by tools outside the normal `zk` flow, or manual cleanup.
## Frontmatter normalization
Frontmatter normalization is implemented in `frontmatter.lua` and is deliberately independent of Obsidian.nvim.
Normalization guarantees these fields:
- `id`
- `title`
- `aliases`
The normalizer preserves other existing frontmatter fields. It also sorts known keys in this order when it rewrites frontmatter:
```text
id, title, date, aliases, tags, then all other keys in their existing order
```
### `id` fallback order
`id` is derived in this order:
1. Existing valid `id`.
2. Timestamp/date prefix in the filename.
3. Existing `date` field.
4. Current timestamp as `YYYYMMDDHHMM`.
Supported date inputs include:
```text
YYYYMMDDHHMM
YYYYMMDD
YYYY-MM-DDTHH:MM
YYYY-MM-DD HH:MM
YYYY-MM-DD
```
A date-only input falls back to midnight, so `2024-01-02` becomes `202401020000`.
### `title` fallback order
`title` is derived in this order:
1. Existing `title` field.
2. First level-one Markdown heading.
3. Filename stem with a leading timestamp/date prefix removed.
Examples:
```text
202606141200 My Note.md -> My Note
2024-01-02 My Note.md -> My Note
Plain Note.md -> Plain Note
```
### `aliases` fallback behavior
The normalizer parses existing inline or list-style aliases, then adds the normalized title as an alias if it is missing.
Examples:
```yaml
aliases: ['Existing']
```
```yaml
aliases:
- Existing
```
Both forms are read. The rewritten form is inline:
```yaml
aliases: ['Existing', 'Title']
```
## When frontmatter normalization runs
Frontmatter normalization runs in these places:
1. After creating a note through `:Note`, `:N`, or one of the convenience commands.
2. When an empty Markdown file under `$NOTES_DIR` is opened or created in Neovim.
3. Manually via `:NoteFrontmatter`.
The empty-file path is important for `markdown_oxide`: if its missing-link code action creates an empty Markdown file, opening that file in Neovim adds fallback frontmatter.
## LSP responsibilities
`markdown_oxide` is the Markdown LSP. It owns workspace-aware Markdown behavior such as:
- wiki-link resolution
- hover
- jump to document
- diagnostics for unresolved links
- code actions for missing linked files
`zk-nvim` is still installed, but its LSP auto-attach is disabled. It is used as a command/API layer for `zk` note creation and note pickers, not as the active Markdown LSP.
Obsidian.nvim is intentionally not used. Obsidian app compatibility comes from the file format: plain Markdown, YAML frontmatter, and wiki links.
## CLI behavior
CLI note creation remains owned by `zk` and `config/zk/config.toml`.
Examples:
```sh
zk p 'Personal note'
zk w 'Work note'
zk j
zk til 'Something I learned'
```
## Troubleshooting
### `:N` does not appear as a normal user command
`:N` is an abbreviation for `:Note` because `:N` is already a built-in Ex command. Use `:Note` if you want to bypass abbreviation behavior.
### A new note was created in the wrong directory
`:Note` treats the first word as a target only if it is a configured alias or an existing top-level subdirectory under `$NOTES_DIR`. Otherwise the entire command is treated as the title and the note is created at the root.
### Frontmatter was not added to a file created by another tool
Open the file in Neovim, or run `:NoteFrontmatter!` in the buffer.