Trying to replicate the Logseq journal

Hi there, first post here in the community.
@zef, thanks for this amazing tool and keep up the good work!

I've been wandering in the PKM systems rabbit hole for the last 4-5 years trying several tools but none stick as much to be used daily. So far silverbullet feels to hit the right spot. I've been using it daily in the last month.
Although I followed the community since V1 time of silverbullet, but was never ready enough to do the switch and use it.

Since I'm a former Logseq user, for the amount of time I used it, I really liked the journal first approach and the "automagic" linking of everything related to dates with the journal. So referencing a date would mean its linked to the journal of that day.

I know about the journal guide and that is where I started from. For my case though it doesn't work to have Journals\[YYYY-MM-DD] because it would look unnatural . Another point is having the dates shown as what I call beautified, so I like to see in my text March 28th, 2026 instead of 2026-03-28. For my workflow I tend to plan the day ahead in the journal of the current day so I need /tomorrow to reference the journal of tomorrow. Or for that matter whatever day's journal and thanks to @Mr.Red date picker I can pick a date in advance. Last but not least for my use case I don't like creating from template , so I don't create the journal page with content already. I tend to just create the page empty first , then use my custom slash command to generate some structure on my journal page.

So for anyone who feels the same, this post might be helpful.

I assume that you already have changed what is the default page opened when you open silverbullet. This is what I do as per the guide:

-- customize first loading page 
local function redirectToCustomIndex()
  local currentPage = editor.getCurrentPage()
  if currentPage == "index" then
    -- Change this to whatever page you want your index page to be
    editor.navigate(date.today())
    return
  end
end 

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

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

I have use the power of aliases see: Frontmatter, in order to display the pretty date. I have created a global function on my CONFIG.md for that:

--global function for getting pretty date logseq journal style
function getPrettyDate(pageName)
 -- Ensure name is a string to avoid .slice/match errors
  local name = pageName or ""
  local dateStr = string.match(name, "%d%d%d%d%-%d%d%-%d%d")
  
  local year, month, day
  if dateStr then
    year, month, day = string.match(dateStr, "(%d%d%d%d)%-(%d%d)%-(%d%d)")
  else
    -- Fallback to system date if page name has no date
    year, month, day = os.date("%Y"), os.date("%m"), os.date("%d")
  end
  
  day = tonumber(day)
  local suffix = "th"
  if day % 10 == 1 and day ~= 11 then suffix = "st"
  elseif day % 10 == 2 and day ~= 12 then suffix = "nd"
  elseif day % 10 == 3 and day ~= 13 then suffix = "rd"
  end
  
  local months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
  
  return months[tonumber(month)] .. " " .. day .. suffix .. ", " .. year
end

I have also overriden slightly the /tomorrow and /yesterday slash commands to achieve the referencing of the journal pages:

-- overriding base slash commands to render link with alias and pretty date
-- potentially useful when planning agenda for tomorrow
slashCommand.define {
  name = "yesterday",
  run = function()
    editor.insertAtCursor("[[" .. date.yesterday() .. "|" .. getPrettyDate(date.yesterday()) .. "]]")
  end
}

slashCommand.define {
  name = "tomorrow",
  run = function()
    editor.insertAtCursor("[[" .. date.tomorrow() .. "|" ..  getPrettyDate(date.tomorrow()) .. "]]")
  end
}

Also I've done a minor override to the local function insertDate() of @Mr.Red date picker. NOTE: I've just copied his space lua in my CONFIG.md and added my change as needed, here is just the override:

local function insertDate(args)
  if args and args.date then
    editor.insertAtCursor("[[" .. args.date .. "|" .. getPrettyDate(args.date) .. "]]")
    editor.moveCursor(editor.getCursor())
  end
end

this is my template of the journal, not really needed but just in case anyone gets inspired by it. It is implemented as a slash command. It is just a normal page which i've defined to have this path Libaray/Custom/SlashCommands/daily-journal-template

---
description: Inserts the structure I like for the daily journal
tags: meta/template/slash
exceptContexts:
- FencedCode
---
---
aliases:
- ${getPrettyDate(editor.getCurrentPage())}
tags: journal
---
# Agenda - ${getPrettyDate(editor.getCurrentPage())}

## Checklist for starting up
 

## Planned to do today


# Daily Log

**${string.match(editor.getCurrentPage(), "%d%d%d%d%-%d%d%-%d%d") ~= os.date('%Y-%m-%d') and os.date('%Y-%m-%d at %H:%M') or os.date('%H:%M')}** - Generated the daily template

|^|

# Daily Review
## Checklist for winding down


## What went well today?


## What could have gone better?

Long story short. If i'm writing stuff on my journal, and I need to remind myself to do something on a specific date, or I'm planning the day for tomorrow I can:

  • type /tomorrow or pick up the date from the calendar.
  • Shift + CMD + Enter to create the page without navigating to it ( on windows i guess the shortcut is different)
  • New line indented (Logseq style :slight_smile: ) write stuff which will show up on that journals page.

this is how it looks like:

This is how it loos like with the daily template structure added:

Looking forward to hear from the community for suggestions or ways to improve this.

Thanks!

5 Likes

Nice work, I'll probably use your prettyDate function and I like the idea of landing on the Journal page for the day.

For tasks, I'm setting deadlines using Mr Red's Floating Journal as a date picker. I have written a transform function to set a deadline attribute based on the link. This allows me to have a simple query with all overdue tasks on my Journal page. Additionally, any task with today as a deadline will show up as a Linked Task (and as a Linked Mention, I might disable either of them).

To make the tasks look a bit nicer, I have another transform function to decorate my journal pages with a :tear_off_calendar: icon.

2 Likes

Thats great.
Funnily enough I never used the [Scheduled] feature of Logseq task, because I used to use more google tasks. So I might create /tasks but not really adding yet any attributes or dealing with deadlines. I haven't yet degoogled my worflow but thats a nice idea on how you implemented it.
I haven't yet decided on how to handle tasks. There are endless possibilities and I'm too afraid to chase the perfect setup cause it has potential for going in a rabbit hole. :sweat_smile:

I don't know too much about logseq features, or workflows,but with the latest update of the FloatingJournalCalendar, I’ve also added a Shift+Click feature that allows you to insert custom-formatted dates as plain text. You may find this useful in your daily workflow, either as an alternative to or alongside the date picker.

This lets you add date strings to your pages in your chosen format, for example:

  • 2026-03-28
  • March 28th
  • Saturday (March 28th, 2026)
  • 2026-03-28 14:38:07
  • 28. March 2026
  • Sat, 28/03/26
    etc.

This feature complements the existing interactions:

  • Ctrl/Cmd + Click: insert aliased journal wikilinks (based on the current selection)
  • Drag & Drop: insert simple journal wikilinks
1 Like

Thanks for taking time to read the post.
In my preferences I like things to work in a certain way without too many tinkering, configurations or key combinations to remember. Hence I don't need dates as plain text, different date formats, drag and drop or all the features your plugin offers. I only use the datepicker to pick a date by clicking on it and that will be added as a [[Wiki Reference|with Alias]].

The Logseq journal approach is just the concept of treating dates as pages of your journal so you get the reference of whatever you wrote for that date.

I may try to play with your Sleek interactive Floating Journal Calendar - #37 by Mr.Red , it feels like a silverbullet implementation for the journals plugin of Logseq GitHub - xyhp915/logseq-journals-calendar: A journals calendar for Logseq. · GitHub. I think it can get handy to navigate previous journal pages. Currently I use silversearch and its working fine. I can search by alias. Although I just have a month of journal pages , lets see how things will look like in a year :sweat_smile:.

So to make things easier for other people to follow along:

  • If someone wants to easily navigate journal pages through a calendar use the Floating Journal Calendar from Mr.Red. It provides way more features and configurations to fit more needs.
  • If your workflow has the journal page as a "first-class citizen" so you mostly write on the journal and your index page is a journal page, and you feel the same fear as me of "configuration hell" :sweat_smile:, probably you'll be better of overriding /tomorrow command to add the date as reference and /datepicker to do the same.

Nevertheless the two approaches are not mutually exclusive. They can probably live together. And certainly there many other ways to do the same.

1 Like

I quite agree: simplicity is often the highest form of sophistication, especially when one is trying to avoid "configuration hell." If your current workflow with silversearch is doing the trick, there is no need to clutter the mind with unnecessary extras.

However, should you feel like a touch of improvment without too much headache and you still want to continue to use the Date Picker I might have also an UPDATE to the Date Picker for you too.

New features included:

  • Keyboard Navigation: For when reaching for the mouse feels like an unnecessary journey.
  • Added Settings Panel: To keep any "tinkering" contained in one tidy corner.
  • UI Tweaks: General refinements to keep the interface looking sharp.

It should play quite nicely with your current workflow too, it simply stays entirely out of your way until called upon using the /datepicker slash command.

I will still keep on using the datepicker because it does exactly what I need it to do. It picks the date for me.
I see that you're very persistent to say the least :grin:, which is good for the community.

The work you've done is impressive, considering that is free. I had a look at the updated space lua / javascript implemenation of your datepicker. Big wall of code to get lost into :grin: . Previous one is a bit smaller.

Until @zef or whoever in the community ( even me if I find the time and energy), comes up with a proper collapsable (persistent) block, I would rather stay with the medium wall of text in my CONFIG.md file. It has already become unmanagable to go a read and find something.

I currently have headers which I have to collapse one at a time until I reach the spot I need. And yes I already know about your TOC on the side :), but for the same reasons I have avoided it so far.

Although the discussion is shifting away from the main topic post.

So for anyone else to follow along. The updated DatePicker add-on as SlashCommand - #19 by Mr.Red, now includes the formatting and date referencing configurable. You don't need neccessarily a custom getPrettyDate() unless you want to also override the /yesterday and /tomorrow slash commands. I'm pretty sure that @Mr.Red will make another update soon to include them also :smile: .

1 Like

Note that you can put your space-lua anywhere and it's probably a good idea to split it out in various pages (e.g. under Library/), you don't need to keep everything in CONFIG.

2 Likes

Great topic. Coming here with some Logseq experience as well. In that app there is an journal page displaying all the journal pages from newest at the top to oldest at the bottom. With autoload (aka endless scroll). I am not even sure this is a best practice for journaling. But has anyone tried to replicate this feature?

I think the his would be very easy to replicate using queries.
This would only display the journals contents, but it wont be editable in place.

Do you have any video or screenshots of how that looks IRL ? I wouldn’t want to install logseq just to check this out.

This is how it works in Logseq.
In this program users are encouraged to always start with a journal.

logseq-journals

Well I know this ain't entirely what you showed, but this next function queries the space for all the journal pages and display them as:

# Pagename
![[Pagename]]

for each query item found:

Here is the space-lua:

-- priority: 10  
function journalWidget()  
  local pages = query[[  
    from index.tag "page"   
    where name:startsWith("Journal/")   
    order by name desc  
  ]]  
    
  local output = ""  
  for _, p in ipairs(pages) do  
    output = output .. "# [[" .. p.name .. "]]\n\n"  
    output = output .. "![[" .. p.name .. "]]\n\n---\n\n"  
  end  
    
  return widget.new {  
    markdown = output,  
    display = "block"  
  }  
end

Usage:

On any empty page add:

${journalWidget()}

this could even be extended as a VirtualPage to show only the Journal entries of a certain Year or Month. depending on the VirtualPage argument.

2 Likes

Thanks! Your answer is not only a working solution, but also a great way to start understanding what space lua can do and how to work with it.

Being a web developer I am interested if and how could we add js functionality to the mix, so we could have something like the endless scroll with auto-loading more journal pages as we scroll down, so we do not load them all.

@Mr.Red , @zef , could you suggest where one could learn about this stuff?

i don't think there is an official source to help you with that beside the documentation on silvebullet.md, but that wont address your exact use cases.

  • other good documentation source is: silverbulletmd/silverbullet | DeepWiki where you can ask questions regarding the source code.
  • other good source for inspiration are the source codes of various silverbullet libraries. i can only talk for mine, but there are plenty exemples on how to combine space-lua with js and css snippets.
  • my libraries are 70% created using AI-coding tools, but it can be still used also as inspiration for other implementations (of course AI wont always inplement best code practices). you might look into the code of following libraries:
  • Pomodoro Clock - easy example on how to integrate space-lua & js & css
  • MediaGallery - a little more complex code - but this tackles: Space-lua, JS, Virtual Pages, Widgets, etc.
  • KanbanBoard - similar to MediaGallery, but with querying tasks instead of objects and displaying them as widget on a page.
2 Likes