Five Obsidian templates to manage 200+ book notes
The five Obsidian templates I use to manage 200+ book notes
Obsidian is my PKM of choice to keep track of the books I am reading, have read and want to read. I use five templates to manage this digital bookshelf. This might be too much for your use case, but I hope you can still take away some templating inspiration and find handy code snippets.
Background
Breakdown: The 242 book notes in my vault are currently distributed like this:
- 92 books noted
- 13 books interested
- 2 books held
- 4 books reading
- 131 books read
Your mileage might vary. Having five book templates is likely too much for most people. I don’t recommend you copy and paste the whole system but pluck out the parts that complement yours.
All of these templates require the Templater plugin and some the Dataview plugin.
One book, one file
There are many apps to keep track of what you’re reading. I started with Goodreads. After a while I switched to The StoryGraph which is a great Amazon-free alternative, started out as a side-project and features gorgeous reading stats.
The “killer feature” about Obsidian though is its interconnectedness.
The first clue that a book might be worth reading for me is if it comes up a lot. Having a note for a book since the first time I hear about it allows me to keep track of it. A title gets mentioned in a podcast — I add a backlink to it. A friend recommends a book — I add a note in the book file. Once a book has accumulated enough of those notes and backlinks it is probably time to start reading it.
Also, it provides context. For example, the Cortex Podcast mentioned Thinking, Fast and Slow in an episode, connecting it to the Replication crisis. I quickly jot that down and if I read the book at a later date, there is that context in the book note already.
Steps
In order to keep track of all the book notes in my vault, I categorise them into five stages:
- Noted: Someone mentions a book and I want to remember the title.
- Interested: A book keeps coming up again and sounds interesting.
- Held: Books that I own or have reserved at the library.
- Currently reading: Books that I am reading at the moment.
- Read: Books that I’ve read.
Below you can find the template for each step broken down, and a Templater code snippet that might be valuable for you regardless of the use case.
If you just want to skip to the implementation, the code for each template is available on GitHub.
Stage 1: Noted
When I first hear a book that I want to keep track of, I run this template. It is designed to be quick and work on- or offline.
This is what happens:
- Enter the book title into a prompt
- The template fetches three fitting titles from the Google Books API. Choose one.
- Select genre: Fiction, non-fiction or biographical
- Set author, year published, pages, thumbnail and id from Google Books
- Set the added field to today’s date and the status to noted.
- Move the file to the books folder (in my case,
30 External/31 Books/31.00 Backshelf
1)
In case the Google Books API is unavailable, like when I’m running the template without internet access, the template creates a book note with the entered title and fills in the baseline template.
See the template for Books — Noted on GitHub
If you’re just looking for a basic book note template that set things up for you, out of the five templates this is the one you would want to use.
Code snippet: Fetch from the Google Books API
// fields to fetch from Google API
const fields =
"fields=items/volumeInfo(title,authors,pageCount,publishedDate,imageLinks/*),items/id";
const bookQuery = await tp.system.prompt("Enter book");
const url = `https://www.googleapis.com/books/v1/volumes?q=${encodeURI(
bookQuery
)}&maxResults=${limit}&${fields}`;
// Call API
try {
// successful response
const response = await requestUrl({
url: url,
});
const bookObj = response.json;
// pick a book from the suggestions
const chosenIndex = await chooseBook(response.json);
const chosenBook = bookObj.items[chosenIndex];
// keep processing the chosenBook data…
} catch (error) {
// error handling...
new Notice("📶 No Signal: " + error);
}
Stage 2: Interested
Once a book gets mentioned a couple of times in different conversations or podcasts, I move it to the Interested stage.
- Change the status field to interested.
- Open a browser window to the search results of the book title of the local library. Open a prompt to ask for the library book URL.
- Open a browser window to search for the DDC number of the book.
- Open a browser window to Amazon to copy the Kindle link of the book.
- If the Google Books API request failed on the previous attempt (so there is no
id
in the note), run another request to fetch the missing fields.
↪ View the template for Books — Interested on GitHub
Code snippet: Replace dataview fields
This snippet replaces the value inside an inline dataview field like this: [status:: held]
.
const replaceField = async (field, newValue) => {
const content = tp.file.content;
const find = new RegExp(`\\[${field}:: .*?\\]`, "g");
const replace = `[${field}:: ${newValue}]`;
const newContent = content.replace(find, replace);
// Write content
const tFile = tp.file.find_tfile(tp.file.title);
await app.vault.modify(tFile, newContent);
};
// called like this:
await replaceField("status", "interested");
Stage 3: Held
Once I reserved a book at the local library or have bought it, I move the book to this stage.
This is what happens in the template:
- Choose whether to replace the thumbnail. Most book covers from the Google Books API are low resolution, and I like to replace it with an image with better resolution from Amazon.
- Update status to held.
↪ See the template for Books — Held on GitHub
Code snippet: Open browser URL
const url = "https://obsidian.md/";
window.open(url);
Stage 4: Currently-Reading
This stage kicks in once I start reading a book.
- Choose whether to have this book note public on Publish.
- Set status to currently-reading
- Update started to today's date
- Add #currently-reading tag
- Move book out of the backshelf folder into
30 External/31 Books
.
↪ See the template for Books — Currently-Reading on GitHub
Code snippet: Append
Insert content in a specific place in a note.
async function append(place, add) {
const content = tp.file.content;
const find = place;
const replace = place + "\n" + add;
const newContent = content.replace(find, replace);
// Write content
const tFile = tp.file.find_tfile(tp.file.title);
await app.vault.modify(tFile, newContent);
}
// Usage
append("up:: [[Books]]", "#currently-reading");
Stage 5: Read
Once I finished reading a book, this template gets run.
- Choose a rating for the book. Set the rating field to the chosen book.
- Update status to read.
- Set the read field to today's date.
- Add a heading for Summary/Reflection.
↪ See the template for Books — Read on GitHub
Code snippet: Rating chooser
async function ratingStars() {
var displayArr = [];
var ratingArr = [];
// Populate Array
for (let i = 5; i >= 0; i = i - 0.25) {
ratingArr.push(i);
if (i <= 1.25) {
displayArr.push("✨ " + i);
} else if (i > 1.25 && i <= 2.5) {
displayArr.push("💫 " + i);
} else if (i > 2.5 && i <= 3.75) {
displayArr.push("⭐️ " + i);
} else if (i > 3.75 && i <= 5) {
displayArr.push("🌟 " + i);
}
}
return await tp.system.suggester(displayArr, ratingArr);
}
Conclusion
The great thing about Obsidian is that it creates space for so much context. Backlinks are one way in which context is generated. Front matter is another.
Keeping track of the metadata of books, I can filter, sort and query my personal digital library. I can create my own custom charts based on started and end dates, see the statistics for my reading on a whole year and find my next read based on length, genre and level of interest.
Obsidian’s powerful templating capabilities make building and navigating that personal treasure trove of books a breeze.
Footnotes
- This note gives an overview of what the folder structure in my vault looks like: JD System 2022-03-26 ↩