Automatic Update of link to current daily note when opening an older daily note

How can I dynamically update the todayDate when I click on any daily note in the past so it will jump to today’s calendar date?

Templater code for Daily notes Template:
let todayDate = moment().format(“YYYY-MM-DD”);
let content = [[${todayDate} | Today]];
tR += content;

Above will create a link to today’s date but this is static and any older daily note will have the date when it was created as todayDate.

Thanks for any help!

Here is the solution :slightly_smiling_face:

<%*
// == Templater Startup Script ==
// Updates "Today" links in daily notes with a delay and batching.

// --- Configuration ---
const delaySeconds = 5;          // Delay in seconds before starting the update
const batchSize = 10;            // Number of files to process per batch
const batchIntervalMillis = 500; // Interval between batches in milliseconds
const dailyNoteFolder = "Path/to/your/folder"; // Replace with your actual daily notes folder

// --- Script Logic ---
const today = tp.date.now("YYYY-MM-DD");

async function updateLinksInBatch(files, startIndex) {
    const endIndex = Math.min(startIndex + batchSize, files.length);
    for (let i = startIndex; i < endIndex; i++) {
        const file = files[i];
        try {
            let content = await app.vault.read(file);
            const regex = /\[\[(\d{4}-\d{2}-\d{2}) \| Today\]\]/g;
            let updatedContent = content.replace(regex, `[[${today} | Today]]`);
            if (content !== updatedContent) {
                await app.vault.modify(file, updatedContent);
                console.log(`[Today Link Updater] Updated link in: ${file.path}`);
            }
        } catch (error) {
            console.error(`[Today Link Updater] Error processing file ${file.path}:`, error);
        }
    }

    if (endIndex < files.length) {
        setTimeout(() => updateLinksInBatch(files, endIndex), batchIntervalMillis);
    } else {
        console.log("[Today Link Updater] Daily note links update complete.");
    }
}

setTimeout(async () => {
    console.log(`[Today Link Updater] Starting link update in ${delaySeconds} seconds...`);
    const dailyNotes = app.vault.getMarkdownFiles().filter(file => file.path.startsWith(dailyNoteFolder + "/"));
    console.log(`[Today Link Updater] Found ${dailyNotes.length} daily notes to process.`);
    if (dailyNotes.length > 0) {
        updateLinksInBatch(dailyNotes, 0);
    } else {
        console.log("[Today Link Updater] No daily notes found to update.");
    }
}, delaySeconds * 1000);

console.log("[Today Link Updater] Startup script initialized.");
%>

Steps

  1. Put this script in its own note and in its own folder.
  2. Add the daily notes folder path to the script.
  3. Go to settings and go to templater and select the note where the script is located and place it in the templater startup scripts list.

Explanation

The script checks all your daily notes with a short delay to not slow down the startup speed and divides the notes into several sections and each section searches for links containing the word today in this format [[YYYY-MM-DD | Today]] and updates it to the date of the present day.

@Rios , so every time Obsidian starts up you’ll run through all daily notes and update the link for todays note? This sounds a little expensive after you’ve gotten a few years worth of daily notes…

I’d recommend two other solutions. The first is to use a dynamic link in all daily notes which is executed when you open that daily note to point to todays daily note. Dataview would be a good candidate for this kind of query.

The second solution would be to let all of your daily notes embed a small file at the top which holds the link to todays daily note. Then you could update that one for every day to be the correct link, and not every daily note in your vault.

1 Like

@holroy 've offered theoretical suggestions that are either incomplete and unaccompanied by a concrete solution or difficult to implement after we’ve gotten a few years worth of daily notes due to the difficulty of embedding a “file” for this large number of notes manually or with an undefined process, necessitating manual tinkering to update that link for every day to be the correct link. Furthermore, there is no feasible method to do this. Let’s just call them ‘solutions’ for now… Prepare to see a real, comprehensive, and simple solution.

The Final Solution

  1. Go to Settings and go to Community plugins and install Dataview plugin.
  2. Go to Settings and go to Dataview and enable inline JavaScript queries.
  3. Replace Your old script in the daily notes template with this inline script :
`$=dv.span("[[" + dv.date('today').toFormat("yyyy-MM-dd") + " | Today]]")`

Note : I highly recommend you make a backup of your daily notes before doing the next step.

  1. Put this script in its own file.

The script:

<%*
const folderPath = "Your/Daily/Notes/Folder";  // Replace with your daily notes folder path
const dataviewCode = "`$=dv.span(\"[[\" + dv.date('today').toFormat(\"yyyy-MM-dd\") + \" | Today]]\")`";

async function updateDailyNotes(folderPath) {
    const files = app.vault.getMarkdownFiles().filter(file => file.path.startsWith(folderPath));

    for (const file of files) {
        let content = await app.vault.read(file);
        const linkRegex = /\[\[\d{4}-\d{2}-\d{2} \| Today\]\]/g; // Regex to match [[YYYY-MM-DD | Today]] links

        if (content.match(linkRegex)) {
            const updatedContent = content.replace(linkRegex, dataviewCode);
            await app.vault.modify(file, updatedContent);
        }
    }

    return "Done!";
}

const result = await updateDailyNotes(folderPath);
tR += result;
%>
  1. Run this script and wait until it prints “Done !”.

Explanation

The first script presents today’s date in a dynamic manner as required with the desired format.
The second script replaces all of the old today’s links in your daily notes with our new solution.

There is no such solution, to such a complex idea. I deliberately left out any implementations of my ideas to allow for the OP to enter the stage again explaining what they really wanted, instead of proposing a halfway solution which might or might not apply to their situation.

I’m not going to enter into a debate on what the best generic solution is, as I don’t believe it exists, but here is the gist of three different additions/changes which all could be made to a daily template:

A call to dv.view()

Personally I’m using a call like `$= await dv.view("header.js") `, which triggers a javascript which builds a header suitable for whatever note I inserted that segment into. The script will detect what kind of note it is inserted into, and build an appropriate header.

At any point in time, I can then change this script to suit my current style of what I want to to have in the header.

Embedding of a header file

As hinted to in my previous post a simpler solution which solves some of the same, would be to have ![[my header]] at the top of your daily note, and then use that file to hold the header of your daily notes. One major downside to this, is that the embedded file doesn’t know the originating file, so it needs to be generic.

For some this might be a valid option, and would allow for the daily note to focus on the new existing bits and pieces related to that day in particular. And you could do simple queries within this file to allow for showing todays date, or listing open tasks.

You could also have it really simple, and just have the link, and use another file/query to update the link. It would still be simpler to maintain a query updating one file, rather than having a query update your entire vault.

Dynamic queries

You could also use inline queries, like @Rios suggested, but these tend to be outdated at some point in time, maybe due to you wanting a different output, or due to changes in Obsidian or the plugin executing the query. Then you’re left with doing global queries changing your files, which not everybody is comfortable with doing. And correctly so, global search-and-replace do need to handled carefully, as there are many pitfalls when doing so.

If you’re happy having this dependency in your daily note, you could use the following in your daily note to link to todays note:

`= link(dateformat(date(today), "yyyy-MM-dd"), "Today") `

And I’m yet again not posting a script to change anyone’s vault globally, as I don’t feel we got enough information to do so in a secure manner. There are just too many unknowns.

But either of the solutions above do need to either accept that daily notes before a given date has a different structure, and from here on we adhere to a different structure, or they need for some global changes to be made to older notes.

My advice before doing those global changes are to be very sure what you want to change to, and that the implications of those changes don’t lead to even more changes down the road.

Thank you Rios and Holroy, both of your one-line codes work. Found a quick no-code solution which works on any past daily note: Ctrl + POS1 jumps to to the current daily note (or creates one, if not present) Best regards Frank