EDIT: info 01/08/2026
Full message below
EDIT: update of 01/05/2026
Full message below
This is pretty fancy I’d have to say!
I assume this is the output of a query and not the source for the tasks?
It’s the source. Code js does the job in real time.
Doc is being written and the code will be published on github in the afternoon… Patience!
Oh wow, even better! This seems comprehensive too!
To familiarize myself with the SilverBullet environment, I set myself a challenge: style the tasks. It was laborious but the objective was achieved.
The solution, based on a JS script, is published in my repository Github (I am not familiar with publishing via the Library Manager. Sorry!).
space-lua (yes, NOT a space-style!) and launches observer.js when the SilverBullet session startsPlease read observer_README_FR.md or observer_README_EN.md to learn everything about the making-off and set up your own rules.
Other files are made available, including:
This script anticipates the development proposed here https://github.com/silverbulletmd/silverbullet/issues/1740. @zef: can you take a look and check the consistency between the two approaches? THANKS.
Please send me your feedback here (not on Github) by publishing an image of your customization.
Happy styling!
Nice job ![]()
But if I would have something like that in my space I would instantly get a panic attack and would start heavy breathing…![]()
![]()
UPDATE 2026-01-06
New version: observer.js and observer_start.md
Reason: passing arguments to js script didn’t work
Changed: js script is now an ES6 module | the default CSS rules are removed (they are already in the space-lua)
Sorry !
I see the screenshot comprehensive demo of all the possibilities that can be achieved with the code. We only need to turn on the parts that make us more productive.
I also didn’t like the tables with tasks and wanted to change them. I took a different approach and just created a new template for tasks, then query and use that template. Happy to share if it’s useful. I am not sure if that approach would allow all the colors and cool stuff you have, but it allowed me to bold certain portions, reorganize things how I like them, etc.
Please do share your code and a screenshot for inspiration if nothing else!
So I have queries for “stale” tasks (where attribute StartDate is old) and for overdue tasks (where DueDate is older than today). Here’s a screenshot for overdue showing the client name in bold, the due date, the task text, and finally the page.
As a meta page, here is the Lua:
---
tags: meta
---
# Task Helper Functions
```space-lua
-- Initialize custom namespace
custom = custom or {}
-- Calculate age in days from a date string (YYYY-MM-DD format)
function custom.daysAgo(dateStr)
if not dateStr then return 0 end
local year, month, day = dateStr:match("^(%d%d%d%d)%-(%d%d)%-(%d%d)$")
if not (year and month and day) then
return 0
end
local taskTime = os.time({year = year, month = month, day = day})
local now = os.time()
local diff = math.floor((now - taskTime) / 86400) -- 86400 seconds in a day
return diff
end
-- Extract client name from page path (first part before /)
function custom.getClientFromPath(pagePath)
if not pagePath then return "" end
local client = pagePath:match("^([^/]+)")
return client or pagePath
end
-- Extract project name from page path (second part after first /)
function custom.getProjectFromPath(pagePath)
if not pagePath then return "" end
local _, project = pagePath:match("^([^/]+)/([^/]+)")
return project or ""
end
-- Format the task display line with client, project, date, and name
function custom.formatTaskLine(task, dateField)
local client = custom.getClientFromPath(task.page)
local project = custom.getProjectFromPath(task.page)
local dateVal = task[dateField] or ""
local parts = {}
if client ~= "" then table.insert(parts, "**" .. client .. "**") end
if project ~= "" then table.insert(parts, "_" .. project .. "_") end
if dateVal ~= "" then table.insert(parts, "đź“… " .. dateVal) end
return table.concat(parts, " | ")
end
Here is the query for the overdue tasks:
${template.each(query[[
from index.tag "task"
where not done and DueDate != nil and table.includes(itags, "work") and DueDate < os.date("%Y-%m-%d")
order by DueDate
limit 20
]], function(task)
local client = task.page:match("^([^/]+)") or ""
return "* [" .. task.state .. "] **" .. client .. "** · Due: ==" .. task.DueDate .. "== | " .. task.name .. " | [[" .. task.ref .. "]]\n"
end)}
Here is the query for the stale tasks:
${template.each(query[[
from index.tag "task"
where not done and table.includes(itags, "work") and StartDate != nil and ((StartDate < os.date('%Y-%m-%d', os.time() - 5*86400)) )
order by StartDate
limit 20
]], function(task)
local client = task.page:match("^([^/]+)") or ""
return "* [" .. task.state .. "] **" .. client .. "** | Started: " .. task.StartDate .. " | " .. task.name .. " | [[" .. task.ref .. "]]\n"
end)}
This work is deprecated with the Edge version published 2026-01-08 which adds an enclosing span with a specific class (“sb-attribute”) and a “data-x”.
<span class="sb-list sb-task"> TODO </span>
<span class="sb-attribute" data-statut="ok"> /* <= NEW line
added by the Edge version published 2026-01-08) */
<span class="sb-list sb-frontmatter sb-meta">[</span>
<span class="sb-list sb-frontmatter sb-atom">statut</span>
<span class="sb-list sb-frontmatter sb-meta">: </span>
<span class="sb-list sb-frontmatter">ok</span>
<span class="sb-list sb-frontmatter sb-meta">]</span>
</span>
Good to know, thank you. But thank you for the whole thread and code. Even if this particular work was made redundant, I learned a lot from your work!
Sorry, can you explain this more? I don’t understand the significance of the sb-attribute addition.
Evolution proposal 1740 was integrated yesterday, by @zef , into the Edge (pre-release) version of Silverbullet.
When generating the html code (backend of md pages) by Silvebullet, a span is added to the description of the attributes it encapsulates.
This span is associated:
This will make, among other things, customizing the display of a task much easier.
Example of the new structure for a task attribute:
<span class="sb-list sb-task"> TODO </span>
<span class="sb-attribute" data-statut="ok">
<span class="sb-list sb-frontmatter sb-meta">[</span>
<span class="sb-list sb-frontmatter sb-atom">statut</span>
<span class="sb-list sb-frontmatter sb-meta">: </span>
<span class="sb-list sb-frontmatter">ok</span>
<span class="sb-list sb-frontmatter sb-meta">]</span>
</span>
CSS rule example with new components:
background of all atributs elements :
.sb-attribute[data-statut] { background-color: red;}
background of the value alone:
.sb-attribute[data-statut] > .sb-list.sb-frontmatter:not(.sb-meta):not(.sb-atom) { background-color: red;}
A more complete example, here: