Creating links to previous and next existing daily notes

What I’m trying to do

I’d like to set up links at the top of my daily note template so that I can navigate to:

  • the previous existing daily note (which would not necessarily be the previous day’s, if I’ve skipped a number of days),
  • the next (existing) note,
  • and the weekly note for the corresponding week

Of note, I’m using the following date format in the Daily Notes plugin so that notes live in nested folders (I read that the format field accepts paths): YYYY/MM-MMMM/YYYY-MM-DD (i.e. 2023 > 01-January). Potentially relevant because the nesting seems to be throwing off the command to open the previous/next daily note… after I switched to this date format, these options no longer appear in the command palette.

Things I have tried

I’ve been trying to follow this reddit post and the updated method in this comment.

I have the following at the top of my daily note template:

<% tp.user.daily_prev() %>  |  [[{{date:gggg/gggg-[W]ww}}|Week]]  |  <% tp.user.daily_next() %>

In the Templater plugin, I’ve enabled “User System Command Functions.”

Function #1 - daily_prev:

daily_notes_path="$(pwd)/Notes - Daily" 
prev_format="Previous" 
prev_note="$(/bin/ls "${daily_notes_path}" | tail -n2 | head -n1 | cut -f 1 -d '.')" 

echo "[[${prev_note}|$prev_format]]"

Function #2 - daily_next:

daily_notes_path="$(pwd)/Notes - Daily" 
next_format="Next" 
prev_note="$(/bin/ls $daily_notes_path | tail -n2 | head -n1)" sed -i "" "s/${next_format}/[[<% tp.file.title %>|${next_format}]]/g" "${daily_notes_path}/${prev_note}" 

echo $next_format

(According to the original reddit post, once the daily note is created, it not just links to the next most recent note, but it should also modify the “Next” link in that previous note to point to your current post, which is pretty cool.)

But the links don’t work as intended… for example, when I click on “Previous” in today’s daily note, instead of taking me to the previous daily note from two days ago, it creates a new note titled “2023” (nested in the folders: Daily Notes folder > 2023 > 11-November > 2023.md)

I have a feeling it’s not working because of my nested date format. How can I alter the functions to take this into account and create workable links?

Thank you in advance!

I might have a solution for the previous note case, using the dataview plugin. My code looks as follows (this is inside a dataviewjs codeblock where I want the link to show up):

const last_entry = await dv.tryQuery(`
	TABLE Datum, file.path
	FROM "Journal"
	WHERE (Datum < date(today))
	SORT Datum DESC
	LIMIT 1
`);
const values = last_entry.values[0];

if (values) {
	let path_prev, datestring;
	[, datestring, path_prev] = last_entry.values[0];
	datestring = datestring.setLocale('de-de').toRelativeCalendar();
	const dispstring = `Letzter Eintrag (${datestring})`
	const link_prev = dv.fileLink(path_prev, false, dispstring);
	dv.paragraph(link_prev);
	
} else {
	dv.paragraph("Keine älteren Einträge");
	
}

What this does:

  • It queries all notes from the folder “Journal” where the value of the date property “Datum” (German for date) is < (excluding) today, and returns only the most recent entry
  • If the returned entry is not NULL (ie., if at least one note matches the query)
    • It extracts the Datum and file.path properties (the first table column, “File”, which is created by default, is omitted). Additionally, the date is reformatted into a human-readable string.
    • It constructs a link to the corresponding file, and finally renders it via dv.paragraph. (The display string “Letzter Eintrag …” translates to “Last entry …”)
  • If there is no note matching the query, it simply renders a line “Keine älteren Einträge” (“No older entries”). The else statement could also be omitted, in which case, nothing would be rendered if no note matches the query.

Of course, you would have to install the Dataview plugin and enable dataviewjs queries from the plugin settings. Also, you would have to slightly modify the code: in this variant, the query always returns the note most recent relative to today’s date, not relative to the note’s creation date. If you were to look at a note you created, say, a year ago, the “previous note” link would point to a note much more recent than the one you are currently reading. I think the easiest way to achieve this, if you create the notes with Templater, might be to insert <% tp.date.now %> directly into the dataviewjs codeblock, resulting in the correct date being “hard-coded” into the note when it is created.

I think this code could also quite easily be adapted in order to achieve the desired “next note” behaviour. If you modify the query string accordingly, in case a later note is found, the link would be created analogous to the way shown. If no note matches the query (else expression), you could use something like DateTime.now() + Duration.fromObject({ days: 1 }) to get tomorrow’s date, and use this to construct a link object pointing to the corresponding note (which will be created if the link is clicked).

I hope this helps, sorry if my answer is confusing, it is quite late already. I will happily elaborate after I had some sleep :upside_down_face:

I’m doing a similar thing in my daily notes, where each of the notes have the following line at the start of the note:

`$= await dv.view("js/header") `

This refers to a javascript file called within the dataview context, and in there I produce various headers for use in my daily notes. One of the elements it produces are previous and next links.

The algorithm I’m using to get these links is a query listing all the daily notes ordered by the date, and then I loop through them searching for the note I’m within. With some look ahead/-back code I then detect the interesting links, and breaks out of the loop when both are found.

The following code excerpt is lifted from my header script with some slight adaptions. You might need to adapt the query to match your settings. I’ve tried to match your setup.

const currFile = dv.current().file

// Fetch all notes ordered by date
const pages = await dv.pages('"Notes - Daily"')
  .sort ( p => p.file.day )
  
// Variables used when looking for previous and next links
let thisPrevious = null
let thisNext = null
let previous = null   // Intermediate candidate for previous link

// Loop through looking for next and previous links
for (let page of pages) {

  if (previous && (page.file.path === currFile.path) ) {
    thisPrevious = previous.file
  } 

  if (previous && (previous.file.path === currFile.path) ) {
    thisNext = page.file
    break
  }
  
  // We've not found both, so update previous candidate
  // and lets loop again
  previous = page 
}

// Output the links
dv.span([
    thisPrevious ? thisPrevious.link : "No previous",
    currFile.name,
    thisNext ? thisNext.link : "No next"
  ].join(" | ") )

For an ordinary day with both links it shows as this:
image

And if there is no next link (and similar for previous links):
image

If you don’t want the name of the current file included, then remove the currFile.name, line from the output links section. And if you want some other output, you could use thisPrevious and thisNext to your liking.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.