Creating Daily Habit tracker in Weekly Notes?

What I’m trying to do

I like to use Weekly Notes, and I am trying to create a Habit Tracker that tracks daily habits, inside the weekly notes. The challenge is that most of the cool habit tracking plugins expect daily notes!

Things I have tried


habit1

At the bottom of my Weekly Note template, I have a list of daily tasks. These automatically get the date assigned. I then present the current days tasks to check off, and attempt to graph it.

However, I would love if it looked more like this:

But you can’t add checkboxes to a table, and all the cool habit-tracking plugins like Obsidian Tracker seem to rely on Daily Notes, which I don’t like. Does anyone have any creative solutions? A table with tick boxes would be fine, but I can’t seem to figure it out.

Thx

-arcane

Maybe the Kanban or Projects plugin could help?

In the longer term, you could post a feature request in the GitHub issues of a tracking plugin.

I reckon you could put a query in your weekly note featuring buttons to press trough the meta-edit plugin, which could update the local frontmatter. It’ll be somewhat gnarly to setup, but once done it should work nicely.

This would allow for your table layout of habits rather nicely, I think.

Ok, here is what I ending up doing. A bit of a hack but does the trick for now:

At the bottom of my weekly template is a long list of tasks set like

#### Monday <% tp.date.weekday("YYYY-MM-DD", 1) %> 
- [ ] 💪Exercise ⏳ <% tp.date.weekday("YYYY-MM-DD", 1) %> #habit
- [ ] 🧘Meditate ⏳ <% tp.date.weekday("YYYY-MM-DD", 1) %> #habit
- [ ] 🧹Clean ⏳ <% tp.date.weekday("YYYY-MM-DD", 1) %>  #habit
- [ ] 国語 Study Japanese  ⏳ <% tp.date.weekday("YYYY-MM-DD", 1) %>  #habit

Then at the top of the template, divided up by columns is

 tasks
scheduled today
tags include #habit 
hide scheduled date
hide edit button
hide backlink

and the table

dataviewjs
let pg = dv.current();
var habitDict = {
	'exercise': 0,
	'meditation': 0,
	'japanese': 0,
	'cleaning': 0
}

const tasks = dv.current().file.tasks
	.sort(t => dv.date(t.due))
	.where(t => {
                // exclude completed tasks and ones w/out due dates
		if(!t.text.includes("#habit")) {
		  return false;
		}
		
		if(t.completion) {
			if(t.text.includes("Exercise"))
			{ 
				habitDict["exercise"] += 1;
			}
			if(t.text.includes("Meditate"))
			{ 
				habitDict["meditation"] += 1;
			}
			if(t.text.includes("Japanese"))
			{ 
				habitDict["japanese"] += 1;
			}
			if(t.text.includes("Clean"))
			{ 
				habitDict["cleaning"] += 1;
			}
		}
		
		return true;
	});
  dv.table(
     ["Habit", "Streak"],
     [ 
      [ "Japanese", "✅".repeat(habitDict["japanese"]) + "❌".repeat(7-(habitDict["japanese"])) ],
	  [  "Meditate", "✅".repeat(habitDict["meditation"]) + "❌".repeat(7-(habitDict["meditation"])) ],
	  [  "Exercise",  "✅".repeat(habitDict["exercise"]) + "❌".repeat(7-(habitDict["exercise"])) ],
	  [   "Clean",  "✅".repeat(habitDict["cleaning"]) + "❌".repeat(7-(habitDict["cleaning"])) ]
	  ]);
	  

The final result is

I’m sure it could be nicer from a JS perspective and an aesthetic perspective but for now it works. Next iteration I will probably have table cells for each day of the week, for starters.

Alright fixed the code: This actually creates an accurate streak count and lists by day:

dataviewjs
let pg = dv.current();

var habitArray = [ 
	["Exercise"],
	["Meditate"],
	["Japanese"],
	["Clean"]
	];

const tasks = dv.current().file.tasks
	.sort(t => dv.date(t.due))
	.where(t => {
		if(!t.text.includes("#habit")) {
		  return false;
		}
		 for (let i = 0; i < habitArray.length; i++) {
			    if(t.text.includes(habitArray[i][0]))
			    { 
				    if(t.completion) { 
					    habitArray[i].push("✅");
				    } else { 
				    habitArray[i].push("❌");
				    }
				}
		}
		return true;
	});
  dv.table(
    ["Habit", "M","T","W","TH","F","SA","SU"], 
    habitArray);

Habit

NOTE: This code makes the assumption you have these tasks assigned for each of the seven dates in the week as the template example shows above.

1 Like

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