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.

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

careful this is not my recommended 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 formatconst 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

careful this is not my recommended solution anymore, see the end of the post
// Get the current file's name and check if it's a valid ISO week formatconst 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

careful this is not my recommended solution anymore, see the end of the post
// Get the current file's name and check if it's a valid ISO quarter formatconst 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 recommended solution anymore, see the end of the post
They got updated in the last change (see the last edit)
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
- Root folder
Year {{date:YYYY}}
{{date:YYYY}}
- 2025-01-01.md
- weekly
- 2025-W01.md
- quarterly
- 2025-Q1.md
And using this structure which I also configured in the Journals settings, where the folders for Diary, Weekly and Quarterly are set to:
Year {{date:YYYY}}/{{date:YYYY}}
Year {{date:YYYY}}/quarterly
Year {{date:YYYY}}/weekly
With the name template values:
{{date}}
- Default value for Weekly Notes
- Default value for Quarterly Notes
Edit: 2025-01-12
I had to change the setup of the dataview templates since it took 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 Templater 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 Obsidian, as that seems to not execute the templater script, use the journal plugin instead.
Edit: 2025-04-15
i updated the obisidan files to reflect my current usage, which was mostly just the change inside the weekly to add a reference to the quarterly goals in addition to the last edit