Skip to content

bbbburns/goodreads-to-obsidian

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

goodreads-to-obsidian

Take a Goodreads CSV export and convert that into a series of markdown notes for Obsidian.

Is it done?

This works for me. I think it's ready to use. You can find my blog post about it for some more background.

Who is this for?

For those who want to migrate all of their existing Goodreads book data to individual markdown files in Obsidian. Then you plan to stop adding new books to Goodreads.

How do I do this?

  1. Optionally, prepare your Vault with a book template See the code snippet below for Obsidian Book Template
  2. Optionally, build a books dashboard with dataview. See the code snippet below for Obsidian Library Dashboard
  3. Login to Goodreads.
  4. Export your books to CSV under My Books (think of sample book format)
  5. Run csv-to-md.py
  6. Take all of these .md files and copy them to your Obsidian vault. 🎉
  7. Add new books with this other great plugin Obsidian Book Search

Running the python file

I wrote this with python 3.10. You will have better results if you use a similar or newer version.

Usage:

user@host$ python3 csv-to-md.py -h
usage: csv-to-md.py [-h] [--template TEMPLATE] [--out OUT] [--sub_len SUB_LEN] [--dry] [--alias] csv

positional arguments:
  csv                  Goodreads CSV export file to import

options:
  -h, --help           show this help message and exit
  --template TEMPLATE  Book Markdown template file with $variables. Uses book.md.Template by default.
  --out OUT            Output directory. Uses current dir as default.
  --sub_len SUB_LEN    Subtitle length for file name. 0 = none (default). a = ALL subtitle words. 1+ = num words long. c = custom
  --dry                If passed, perform a dry run and skip the file write steps.
  --alias              Add the base title as frontmatter alias when subtitle exists.

Here's an example of how I use this to do a dry run, looking at the output to make sure it's correct before writing a file:

python3 csv-to-md.py /home/user/Downloads/goodreads_library_export.csv --template book.md.Template --out /tmp/books --sub_len c --alias --dry

That allows me to take in the CSV export file from a Downloads folder, use the specified template that's in this repo, and place the files into /tmp/books.

The option for --sub_len c lets me take very long subtitles and decide which ones should be dropped from the output file names or included. You can also decide this with other values of sub_len.

The option to --alias populates the value of the frontmatter aliases: key with the short title name. This is great for Obsidian if you want the book to have the full title, but link to it by the short name.

The final option is --dry which turns off the file write operations and just dumps output to the console.

Obsidian Book Template

This is a helpful template for your Obsidian if you are using Templater and want to merge what I have here with the Obsidian Book Search plugin. I copy this to my Templates directory as a file called BookTemplate.md. Then I setup Templater and the Obsidian Book Search plugin to use this template. NOTE: This template is DIFFERENT than the one the Python script uses. This template here is for Obsidian.

---
tags: book, media
publish: false
title: {{title}}
aliases:
series_name: 
series_num: 
author: [{{author}}]
status: 
isbn: {{isbn10}}
isbn13: {{isbn13}}
category: [{{category}}]
rating:
read_count:
binding:
num_pages: {{totalPage}}
pub_date: {{publishDate}}
cover: {{coverURL}}
date_add: <% tp.date.now("YYYY-MM-DD") %>
date_start:
date_end:
created: <% tp.file.creation_date() %>
modified:
---
# {{title}}

## Description

{{description}}

## Review

Note: I have changed this to flatten series_name and series_num to top-level keys. They're no longer nested under the now-deleted seres. If you've used a version of this prior to July 2025, you may have the old style nested property.

Old:

series:
  series_name:
  series_num:

New:

series_name:
series_num:

See the section on Flattening Frontmatter at the end.

Obsidian Library Dashboard

The dataview is where all of this comes together. Here's where you can see all of your shelves and the list of all your books. This is entirely inspired by the Obsidan Book Search plugin and I've modified it some. I copy this to my _dataview folder as a file called Library.md This query has also been modified to handle the flattened series.

# 📚 Library

## Currently Reading

```dataview
TABLE WITHOUT ID
	file.link as Book,
	date_start as Started
FROM  #book
WHERE 
	status = "currently-reading" 
	AND !contains(file.path, "Templates")
SORT date_start DESC
```

## To Read

```dataview
TABLE WITHOUT ID
	file.link as Book,
	date_add as Added
FROM  #book
WHERE 
	status = "to-read" 
	AND !contains(file.path, "Templates")
SORT date_add DESC
```

## All Books

```dataview
TABLE WITHOUT ID
	status as Status,
	"![|60](" + cover + ")" as Cover,
	link(file.link, title) as Title,
	author as Author,
	series_name + " " + series_num as Series
FROM #book
WHERE !contains(file.path, "Templates")
SORT status ASC, file.ctime DESC
```

Note: If you still use nested properties for series, the All Books query would be as follows for series:

series.series_name + " " + series.series_num as Series

Why would I want this?

If you're planning to do all future book reviews in a private Obsidian vault, but have a bunch of book read data that you want to bring with you.

What happens to my data in Goodreads?

Nothing, unless you choose to take some action. This is just a simple data converter.

What about new books that I read and log into Goodreads?

You could use another great plugin Goodsidian to add new books directly to Obsidian. This script won't do that.

What if I want to keep using Goodreads?

Then this script is probably not for you. However, there are some solutions that do that! Like Goodsidian - which takes updates from your feeds of active Goodreads use and puts those into Obsidian. That wasn't what I wanted!

Flattening Frontmatter

If you've used a version of this before July 2025, you likely have nested frontmatter.

series:
  series_name:
  seres_num:

To convert your old notes, you can use a text editor such as VS Code to delete the series: and remove the spaces before series_name and series_num in every note.

You could also use the flatten-series.py in the following manner:

  1. Make a backup of your Vault. You are about to run a script that could modify or delete LOTS of files really fast.
  2. Copy all of your book notes into some temporary directory. Let's assume it's called tmp.
  3. Install the python-frontmatter library with pip install python-frontmatter
  4. Run the flatten-series command. python3 flatten-series.py
  5. When prompted, specify the location of your tmp directory.
  6. Look at all the modified notes in your tmp directory.
  7. If you're happy with these notes, delete all of the book notes in your Obsidian vault (remember, you have a backup, right?) and copy in these new, modified files from tmp.

About

Take a Goodreads CSV export and convert that into markdown notes for Obsidian

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages