Skip to content

Periodic Notes System#468

Open
mdavis36 wants to merge 13 commits intoobsidian-nvim:mainfrom
mdavis36:md/weekly-cmd
Open

Periodic Notes System#468
mdavis36 wants to merge 13 commits intoobsidian-nvim:mainfrom
mdavis36:md/weekly-cmd

Conversation

@mdavis36
Copy link
Copy Markdown

@mdavis36 mdavis36 commented Oct 16, 2025

Summary

Introduces a periodic notes system similar to daily notes, supporting:

  • Weekly notes with configurable week start day (Monday by default)
  • Monthly notes
  • Quarterly notes (Q1-Q4)
  • Yearly notes

All period types include:

  • Current period command (e.g., :Obsidian weekly)
  • Last/next period commands (e.g., :Obsidian last_week, :Obsidian next_week)
  • Offset-based access (e.g., :Obsidian monthly -2 for 2 months ago)
  • Picker commands for browsing multiple periods (e.g., :Obsidian weeklies -5 2)

Architecture Changes

New system:

  • Created lua/obsidian/periodic.lua - Core module providing shared infrastructure for all period types
  • Refactored lua/obsidian/daily/init.lua to use the new system
  • All period modules (daily, weekly, monthly, quarterly, yearly) now use the same pattern

Benefits:

  • Consistent behavior across all period types
  • Easy to add new period types (e.g., bi-weekly) by adding one entry to PERIODS config
  • Bug fixes automatically apply to all period types

New Commands

Weekly:

  • :Obsidian weekly [OFFSET]
  • :Obsidian last_week, :Obsidian next_week
  • :Obsidian weeklies [START] [END]

Monthly:

  • :Obsidian monthly [OFFSET]
  • :Obsidian last_month, :Obsidian next_month
  • :Obsidian monthlies [START] [END]

Quarterly:

  • :Obsidian quarterly [OFFSET]
  • :Obsidian last_quarter, :Obsidian next_quarter
  • :Obsidian quarterlies [START] [END]

Yearly:

  • :Obsidian yearly [OFFSET]
  • :Obsidian last_year, :Obsidian next_year
  • :Obsidian yearlies [START] [END]

Configuration

New config options mirroring daily_notes:

weekly_notes = {
  folder = nil,
  date_format = nil,        -- defaults to "%Y-W%V" (2024-W42)
  alias_format = nil,       -- defaults to "Week %V, %Y"
  template = nil,
  default_tags = { "weekly-notes" },
  start_of_week = 1,        -- 1 = Monday, 0 = Sunday
}

monthly_notes = {
  folder = nil,
  date_format = nil,        -- defaults to "%Y-%m" (2024-10)
  alias_format = nil,       -- defaults to "%B %Y" (October 2024)
  template = nil,
  default_tags = { "monthly-notes" },
}

quarterly_notes = {
  folder = nil,
  date_format = nil,        -- defaults to "%Y-Q%q" (2024-Q4)
  alias_format = nil,       -- defaults to "Q%q %Y" (Q4 2024)
  template = nil,
  default_tags = { "quarterly-notes" },
}

yearly_notes = {
  folder = nil,
  date_format = nil,        -- defaults to "%Y" (2024)
  alias_format = nil,       -- defaults to "%Y" (2024)
  template = nil,
  default_tags = { "yearly-notes" },
}

PR Checklist

  • The PR contains a description of the changes
  • I read the [CONTRIBUTING.md] file
  • The CHANGELOG.md is updated
  • The changes are documented in the README.md file
  • The code complies with make chores (for style, lint, types, and tests)

@neo451
Copy link
Copy Markdown
Member

neo451 commented Oct 16, 2025

Wow, great work!

Initial thoughts:

  1. I am all for adding periodic notes as a primitive, feels much better than obsidian app only have dailies
  2. We can slowly work on this, to have less impact on top level config options and user commands and reduce the size of this PR a bit

More context around other improvements planned for daily_notes, not necessarily related to this PR:

  1. see here Module Improvement Tracker #309 I am beginning to think putting all these in one place is a bad idea now lol
  2. so a big reason I put a separate folder dailies is because I intended to have a dailies/moment.lua, so that date formats can be compatible to obsidian app

Changes I would like to see:

  1. create_period_functions can be replaced with a class, like
local Periodic = {}

Periodic.__index = Periodic

---@param period_config obsidian.PeriodicConfig
---@return table Functions: this_period, last_period, next_period, period, period_note_path
Periodic.new = function(period_config)
  return setmetatable(period_config, Periodic)
end

Periodic.this = function(self)
  --- functions.this_period
  --- access period_config like self.get_period_start, self.default_date_format
end
  1. related to 2 points above, we can just do in periodic.lua, without adding more folders.
M.daily = Periodic.new(M.PERIODS.daily)
M.monthly = ...
  1. (Up to discussion) We can have a top level config module periodic_notes, with type table<string, obsidian.config.PeriodicOpts>., and rename everything to periodic.daily, perodic.weekly and etc, for now really daily_notes into periodic.daily and warn user it will be deprecated in 4.0.0, (see how it was done in frontmatter module). This is all to have a clean top level config module, so that later on we can have a better wiki or potentially a doc site, with subpages split by top level config options, like https://cmp.saghen.dev/

  2. Other general goal is to keep the commands interface minimal, so I would personally want no new default commands unless I explicitly add them, so I would like to see in each kind of periodic, a enabled field, and except for daily_notes they should be default off, and when registering commands, we see if enabled = false, just not register that sub command.

@mdavis36
Copy link
Copy Markdown
Author

@neo451 thank you for turning around a first pass on the review so quickly. I wanted to stick to the current pattern for a first pass (and I needed something functional for my workflow immediately). However, I agree the top level command noise is quite a lot here and there needs to be something to abstract that away. Very happy to revise some of this implementation with your design changes when I get some time here soon.

@washtubs
Copy link
Copy Markdown

Not sure if you're still working on this, but if you use %V to get the current week, use %G to get the corresponding ISO year. It's currently Dec 29, 2025. Right now, %V prints 01 because this week has at least 4 days in 2026. However %Y ofc prints 2025. %G correctly rolls over with %V.

Btw I'm personally more partial to just using the YYYY-MM-DD of the week's Monday. Because that gives me a better idea of when something happened when I look at my notes.

@mdavis36
Copy link
Copy Markdown
Author

mdavis36 commented Dec 30, 2025

I am, it's just been getting pushed further and further on my todo list. I'm hoping to come back to this before the end of the year here.

I was thinking about if this week should belong to 2025-W52 or 2026-W1 a few days ago so good timing, thank you!! I'll be sure to add that change when I get a pass at this.

edit : frazzled from the holidays it should definitely be 2026-W1, I see the problem... 🫠

@mdavis36 mdavis36 force-pushed the md/weekly-cmd branch 2 times, most recently from 807618c to a3744f8 Compare December 31, 2025 22:37
@mdavis36
Copy link
Copy Markdown
Author

mdavis36 commented Dec 31, 2025

@neo451 I still need to update documentation on the commands, but I believe the design hits the architectural requests you had above and reduces the PR size quite significantly

Comment thread lua/obsidian/periodic.lua
Comment on lines +52 to +55
end,
default_date_format = "%G-W%V",
default_alias_format = "Week %V, %G",
},
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woohoo! Happy new year and happy week 2!

@neo451
Copy link
Copy Markdown
Member

neo451 commented Apr 4, 2026

@mdavis36 sorry for no further response to your last comment for a long time, I did had to work on the moment module for this one to really work nicely, see require"obsidian.lib.moment", this makes the date formatting a lot nicer, so I wonder are you still interested in picking up the work? If not I can take over the work as well, anyway thank your for the work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants