Journal previous day and next day navigation

I use the Journal plug, and it’s neat! I wanted to be able to easily navigate from one day’s entry to the previous or next, and there wasn’t anything out-of-the-box. It was pretty simple to add though.

This script and template will put something like the following (with working links) at the top of each Journal page (only Journal pages - other pages are left alone).

:arrow_left: Previous | :date: Journal/Day/2024-10-27 | Next :arrow_right:

‘Previous’ takes you to the previous day, and clicking ‘Previous’ on that page will take you to the day before, and so on. It’s possible to navigate back days and weeks using this, which I find useful sometimes if I don’t know which particular day’s notes I want.

Here’s what worked for me. You need to create 2 new pages, but it doesn’t matter much where you put them. (I have mine in Custom/Extensions).

  1. Create a new page for the space script (I called mine JournalNavigationScript) and add the following:
```space-script
silverbullet.registerFunction({name: "newJournalNameFromExistingJournalName"}, (page, days) => {
  const parts = page.split("/");
  const date = parts[parts.length - 1];
  const plainDate = Temporal.PlainDate.from(date);
  const offsetDate = plainDate.add(Temporal.Duration.from({ days: Number(days) }));
  const result = parts.slice(0, -1);
  result.push(offsetDate.toString());
  return result.join("/");
});

(Not rendered here - three backticks to close the script.)

  1. Create a new page for the template (I called mine JournalNavigationTemplate) and add the following frontmatter and template:
---
description: Adds Journal navigation to journal pages.
tags: template
hooks.top.where: 'name =~ /^Journal\/Day/'
---
```template
[[{{newJournalNameFromExistingJournalName(@page.name, -1)}}|⬅️ Previous]] | [[{{@page.name}}|📅 {{@page.name}}]] | [[{{newJournalNameFromExistingJournalName(@page.name, 1)}}|Next ➡️]]

(Not rendered here - three backticks to close the template.)

The frontmatter and template does need to be on a page on its own, but the script can go on a page with other scripts if you prefer.

5 Likes

Wow, Thank you so much for this! :pancakes:

1 Like

Glad you like it - I really hope it’s useful!

Lua version of this,

:arrow_left: Previous | :date: Journal/Day/2024-10-27 | Next :arrow_right:

  1. Create a new page for the space-lua
```space-lua
Journal = Journal or {}

function Journal.navigateWidget(currentJournal)
    -- currentJournal should be in the format "path/year-month-day"
    local path, year, month, day = string.match(currentJournal, "(.+/)(%d+)-(%d+)-(%d+)")

    if not (path and year and month and day) then
        print("Invalid date format: " .. tostring(currentJournal))
        return "Invalid date format"
    end

    local date = os.time({year = tonumber(year), month = tonumber(month), day = tonumber(day)})

    local prevWeek = os.date("%Y-%m-%d", date - 7 * 24 * 60 * 60)
    local nextWeek = os.date("%Y-%m-%d", date + 7 * 24 * 60 * 60)

    local prevWeekLink = path .. prevWeek
    local nextWeekLink = path .. nextWeek

    local link = "[[" .. prevWeekLink .. "|⬅️ Previous]] | [[" .. tostring(currentJournal) .."|📅 " .. tostring(currentJournal) .. "]] |[[" .. nextWeekLink .. "| Next ➡️]]"
    -- local link = "[[" .. prevWeekLink .. "|⬅️ Previous]]" ..  tostring(currentJournal)  .. "[[" .. nextWeekLink .. "| Next ➡️]]"
  
    return link
end

Create a new page for the template

---
description: Adds Journal navigation to journal pages.
tags: template
hooks.top.where: 'name =~ /^Journal\/Day/'
---

${Journal.navigateWidget(editor.getCurrentPage())}
6 Likes

Thanks so much for this!

I think widgets need widget.new now?

The function Journal.navigateWidget returns markdown text, so doesn’t need widget.new.

I think I have just worked out what a widget is

hi @LogeshG5 , i’m running on the latest v2 of Silverbullet and i don’t know why isn’t working.
I create a journalTemplate like this

---
command: Journal Note
description: Adds Journal navigation to journal pages.
key: "Alt-Shift-j"
tags: meta/template/page
hooks.top.where: 'name =~ /^Journal\/Day/'
---

${Journal.navigateWidget(editor.getCurrentPage())}

and a journalScript same as you.

When i CRTL+SHIFT+j with multiple test, these what i see in console:

silverbullet_1  | Error GETting file 2025-08-31.md Not found
silverbullet_1  | Writing file 2025-08-31.md
silverbullet_1  | Writing file 2025-08-31.md
silverbullet_1  | Error GETting file 2025-8-31.md Not found
silverbullet_1  | Writing file 2025-8-31.md
silverbullet_1  | Writing file 2025-8-31.md
silverbullet_1  | Error GETting file Journaux/2025-08-31.md Not found
silverbullet_1  | Writing file Journaux/2025-08-31.md
silverbullet_1  | Writing file Journaux/2025-08-31.md
silverbullet_1  | Error GETting file Journaux/2025-8-31.md Not found
silverbullet_1  | Writing file Journaux/2025-8-31.md
silverbullet_1  | Writing file Journaux/2025-8-31.md

And my pages always show an Invalid date format
I think the script run before the page was created
can you help me?

I use this in v2, note the change string.match(currentJournal, "(.+/)(%d+)%-(%d+)%-(%d+)")

event.listen {
  name = "hooks:renderTopWidgets", -- or hooks:renderBottomWidgets
  run = function(e)
    if not editor.getCurrentPage().startsWith("Journal/Week/") then
        return
    end
    return widget.new {
      markdown = Journal.navigateWidget(editor.getCurrentPage()) .. "\n"
    }
  end
}

Journal = Journal or {}

function Journal.navigateWidget(currentJournal)
    -- current Journal should be in the format "path/year-month-day"
    local path, year, month, day = string.match(currentJournal, "(.+/)(%d+)%-(%d+)%-(%d+)")

    if not (path and year and month and day) then
        print("Invalid date format: " .. tostring(currentJournal))
        return "Invalid date format: " .. tostring(path) .. tostring(year) .. tostring(month) .. tostring(day)
    end

    local date = os.time({year = tonumber(year), month = tonumber(month), day = tonumber(day)})

    local prevWeek = os.date("%Y-%m-%d", date - 7 * 24 * 60 * 60)
    local nextWeek = os.date("%Y-%m-%d", date + 7 * 24 * 60 * 60)

    local prevWeekLink = path .. prevWeek
    local nextWeekLink = path .. nextWeek

    local link = "[[" .. prevWeekLink .. "|⬅️ Previous]] | [[" .. tostring(currentJournal) .."|📅 " .. tostring(currentJournal) .. "]] |[[" .. nextWeekLink .. "| Next ➡️]]"
    -- local link = "[[" .. prevWeekLink .. "|⬅️ Previous]]" ..  tostring(currentJournal)  .. "[[" .. nextWeekLink .. "| Next ➡️]]"
  
    return link
end
1 Like

I’ve changed mine a bit, but since I’m moving away from Silverbullet I figured I’d put all my code for my version here in case someone finds it useful.

I have 4 files, and I put them in Custom/Journal.

Custom/Journal/IndexPage:

```space-lua
local function redirectToTodaysJournal()
  if editor.getCurrentPage() == "index" then
    editor.navigate({kind = "page", page = "Journal/Day/" .. date.today()})
  end
end

-- Trigger the above function when the editor is first loaded
event.listen {
  name = "editor:init",
  run = redirectToTodaysJournal
}

-- And also when any page is loaded (because it may be the index page)
event.listen {
  name = "editor:pageLoaded",
  run = redirectToTodaysJournal
}

Custom/Journal/JournalWidget:

```space-lua
event.listen {
  name = "hooks:renderTopWidgets",
  run = function(e)
    local currentPage = editor.getCurrentPage()
    if not currentPage.startsWith("Journal/Day") then
        return
    end

    -- currentPage should be in the format "path/year-month-day"
    local path, year, month, day = string.match(currentPage, "(Journal/Day/)(%d%d%d%d)%-(%d%d)%-(%d%d)")
    
    if not (path and year and month and day) then
        print("Invalid Journal date format: " .. currentPage)
        return "Invalid Journal date format: " .. currentPage
    end

    local currentPageDate = os.time({year = tonumber(year), month = tonumber(month), day = tonumber(day)})

    local previousDate = currentPageDate - 24 * 60 * 60
    local nextDate = currentPageDate + 24 * 60 * 60

    return widget.new {
      markdown = "[[" ..
        path .. os.date("%Y-%m-%d", previousDate) ..
        "|" ..
        "⬅️ (" .. os.date("%Y-%m-%d", previousDate) .. ") Previous" ..
      "]] | [[" ..
        tostring(currentPage) ..
        "|📅 " ..
        os.date("%Y-%m-%d", currentPageDate) ..
      "]] | [[" ..
        path .. os.date("%Y-%m-%d", nextDate) ..
        "|" ..
        "Next (" .. os.date("%Y-%m-%d", nextDate) .. ") ➡️" ..
      "]]"
    }
  end
}

Custom/Journal/JToday:

---
description: Insert a link to today's Journal entry
tags: meta/template/slash
exceptContexts:
- "FencedCode"
- "LuaDirective"
---
[[Journal/Day/${os.date("%Y-%m-%d")}]] 

Custom/Journal/PageTemplate:

---
command: "Journal: Daily Note"
suggestedName: "Journal/Day/${date.today()}"
confirmName: false
openIfExists: true
tags: meta/template/page
---
* |^|
1 Like