WhatsApp Analyser and Obsidian yearly setup

Whatsapp Analyser

Since the year 2025 just started I wanted to create a tool that makes it possible for me to visualize the data from my WhatsApp chats. Since whatsapp is the main form of communication for me, I wanted to see how my communication with others has changed over the years. And since I saw a few tools online which did that I thought I could just do it myself and improve some stuff which I didn’t like about them. E.g. filter yearly, show emoji usage and filter popular words and stuff like that.

Example of the my Whatsapp Analyser tool

Obsidian

So I wanted to have some way to quickly move through my recent diary entries, in a simple way. And there was no way to automatically navigate between the daily notes, weekly notes, and quarterly notes without installing multiple additional plugins. Which I did not want to do, since I already have quite a few plugins installed, so I used dataview and chatgpt to figure something out that works for me.

The main idea is that I keep track of what I want to do, so I don’t forget about it, and then remind myself Quarterly, Weekly and then Daily about it. The idea is inspired/taken from this video 6 Habits to Make 2025 Your Best Year Yet

Diary Dataview display

Example of the Dataview Query for the Diary visualized

careful this is not my reccomended solution anymore, see the end of the post

// Get the current file's name and check if it's a valid date in YYYY-MM-DD format
const currentFileName = dv.current().file.name;
if (moment(currentFileName, "YYYY-MM-DD", true).isValid()) {
const currentDate = moment(currentFileName, "YYYY-MM-DD"); // Parse the daily note's name
// Calculate Yesterday, Tomorrow, Quarterly Note, and Weekly Note
const yesterday = currentDate.clone().subtract(1, "day").format("YYYY-MM-DD");
const tomorrow = currentDate.clone().add(1, "day").format("YYYY-MM-DD");
const quarterlyNote = currentDate.clone().format("YYYY-[Q]Q"); // Format as "YYYY-QX"
const weeklyNote = currentDate
.clone()
.startOf("isoWeek")
.format("YYYY-[W]ww"); // Weekly note in "YYYY-Www"
// Render the navigation bar
const navigationBar = `###### << [[${yesterday}|Yesterday]] | [[${tomorrow}|Tomorrow]] >> 🗓️ [[${quarterlyNote}|Quarterly Note]] | 📆 [[${weeklyNote}|Weekly Note]]`;
// Output the final Markdown text
dv.el("div", navigationBar, { cls: "nav-bar" });
} else {
dv.el("div", "This file's name is not a valid date format (YYYY-MM-DD).");
}

Weekly Dataview display

Example of the Dataview Query for the Weekly Review visualized

careful this is not my reccomended solution anymore, see the end of the post

// Get the current file's name and check if it's a valid ISO week format
const currentFileName = dv.current().file.name;
if (moment(currentFileName, "YYYY-[W]ww", true).isValid()) {
const currentWeek = moment(currentFileName, "YYYY-[W]ww"); // Parse the weekly note's name
// Calculate Last Week, Next Week, and the Quarterly Note
const lastWeek = currentWeek.clone().subtract(1, "week").format("YYYY-[W]ww");
const nextWeek = currentWeek.clone().add(1, "week").format("YYYY-[W]ww");
const quarterlyNote = currentWeek.clone().format("YYYY-[Q]Q"); // Format as "YYYY-QX"
// Generate links for all days in the week
const daysOfWeek = Array.from(
{ length: 7 },
(_, i) =>
`[[${currentWeek.clone().startOf("isoWeek").add(i, "day").format("YYYY-MM-DD")}|${currentWeek
.clone()
.startOf("isoWeek")
.add(i, "day")
.format("dd")}]]`,
).join(" | ");
// Render the navigation bar
const navigationBar = `###### ⬅️ [[${lastWeek}|Last Week]] | 🗓️ [[${quarterlyNote}|Quarterly Note]] | [[${nextWeek}|Next Week]] ➡️
${daysOfWeek}`;
// Output the final Markdown text
dv.el("div", navigationBar, { cls: "nav-bar" });
} else {
dv.el("div", "This file's name is not a valid ISO week format (YYYY-Www).");
}

Quarterly Dataview display

Example of the Dataview Query for the Quarterly Review visualized

careful this is not my reccomended solution anymore, see the end of the post

// Get the current file's name and check if it's a valid ISO quarter format
const currentFileName = dv.current().file.name;
if (moment(currentFileName, "YYYY-[Q]Q", true).isValid()) {
const currentQuarter = moment(currentFileName, "YYYY-[Q]Q"); // Parse the quarterly note's name
// Calculate Last Quarter, Next Quarter, and the Last Year
const lastQuarter = currentQuarter
.clone()
.subtract(1, "quarter")
.format("YYYY-[Q]Q");
const nextQuarter = currentQuarter
.clone()
.add(1, "quarter")
.format("YYYY-[Q]Q");
const lastYear = currentQuarter.clone().subtract(1, "year").format("YYYY");
// Render the navigation bar
const navigationBar = `###### ⬅️ [[${lastQuarter}|Last Quarter]] | 📅 [[${lastYear}|Last Year]] | [[${nextQuarter}|Next Quarter]] ➡️`;
// Output the final Markdown text
dv.el("div", navigationBar, { cls: "nav-bar" });
} else {
dv.el("div", "This file's name is not a valid ISO quarter format (YYYY-QX).");
}

The Template can be downloaded here:

careful this is not my reccomended solution anymore, see the end of the post

Journals

Then I use Journals to keep track and easily view my calendar, which contains the Daily, Weekly and Quarterly template.

I do this by setting the root folder and then subdirectories

And using this structure which I also configured in the Journals settings, where the folders for Diary, Weekly and Quarterly are set to:

With the name template values:

Edit: 2025-01-12

I had to change the setup of the dataview templates since it toook sooo long for dataview to load, and then it would be a performance bottleneck and I didn’t like that I saw the “loading” state while the graph was being built. So the new template is using Tempalter with the following template

Diary/Daily note

<%*
const currentFileName = tp.file.title;
if (moment(currentFileName, "YYYY-MM-DD", true).isValid()) {
const currentDate = moment(currentFileName, "YYYY-MM-DD");
// Calculate Yesterday, Tomorrow, Quarterly Note, and Weekly Note
const yesterday = currentDate.clone().subtract(1, "day").format("YYYY-MM-DD");
const tomorrow = currentDate.clone().add(1, "day").format("YYYY-MM-DD");
const quarterlyNote = currentDate.clone().format("YYYY-[Q]Q"); // Format as "YYYY-QX"
const weeklyNote = currentDate.clone().startOf("isoWeek").format("YYYY-[W]ww"); // Weekly note in "YYYY-Www"
// Render the navigation bar
const navigationBar = `###### << [[${yesterday}|Yesterday]] | [[${tomorrow}|Tomorrow]] >> 🗓️ [[${quarterlyNote}|Quarterly Note]] | 📆 [[${weeklyNote}|Weekly Note]]`;
tR += navigationBar;
}
%>

Weekly Note

<%*
const currentFileName = tp.file.title;
if (moment(currentFileName, "YYYY-[W]ww", true).isValid()) {
const currentWeek = moment(currentFileName, "YYYY-[W]ww"); // Parse the weekly note's name
// Calculate Last Week, Next Week, and the Quarterly Note
const lastWeek = currentWeek.clone().subtract(1, "week").format("YYYY-[W]ww");
const nextWeek = currentWeek.clone().add(1, "week").format("YYYY-[W]ww");
const quarterlyNote = currentWeek.clone().format("YYYY-[Q]Q"); // Format as "YYYY-QX"
// Generate links for all days in the week
const daysOfWeek = Array.from({ length: 7 }, (_, i) =>
`[[${currentWeek.clone().startOf("isoWeek").add(i, "day").format("YYYY-MM-DD")}|${currentWeek
.clone()
.startOf("isoWeek")
.add(i, "day")
.format("dd")}]]`
).join(" | ");
// Render the navigation bar
const navigationBar = `###### ⬅️ [[${lastWeek}|Last Week]] | 🗓️ [[${quarterlyNote}|Quarterly Note]] | [[${nextWeek}|Next Week]] ➡️
${daysOfWeek}`;
// Output the final Markdown text
tR += navigationBar;
}
%>

Quarterly

<%*
const currentFileName = tp.file.title;
if (moment(currentFileName, "YYYY-[Q]Q", true).isValid()) {
const currentQuarter = moment(currentFileName, "YYYY-[Q]Q"); // Parse the quarterly note's name
// Calculate Last Quarter, Next Quarter, and the Last Year
const lastQuarter = currentQuarter.clone().subtract(1, "quarter").format("YYYY-[Q]Q");
const nextQuarter = currentQuarter.clone().add(1, "quarter").format("YYYY-[Q]Q");
const lastYear = currentQuarter.clone().subtract(1, "year").format("YYYY");
// Render the navigation bar
const navigationBar = `###### ⬅️ [[${lastQuarter}|Last Quarter]] | 📅 [[${lastYear}|Last Year]] | [[${nextQuarter}|Next Quarter]] ➡️`;
// Output the final Markdown text
tR += navigationBar;
} else {
tR += "This file's name is not a valid ISO quarter format (YYYY-QX).";
}
%>

Make sure that you don’t use the default daily note template from obisidan, as that seems to not execute the templater script, use the journal plugin instead.