Create Annotated Bibliographies with Quarto

Introduction

An annotated bibliography is a compilation of sources related to a particular research topic, each accompanied by a brief evaluative commentary. Unlike a traditional bibliography that solely lists references, an annotated bibliography provides a concise summary of each source’s content, methodology, and relevance to the research project. It serves as a critical tool for graduate students and other researchers to assess the scholarly landscape, demonstrating their understanding of key literature and showcasing the ability to critically analyze and synthesize information.

This annotated compilation not only aids in constructing a robust theoretical framework but also helps researchers (1) identify gaps in existing literature and (2) determine the potential contributions of their own work within the academic discourse. For the purposes of this post, we will be creating a bibliography that has the full citation text followed by summary bullet points underneath which can be organized into sections or themes.

Why use Zotero and Quarto?

Zotero is a free, open-source reference management software designed to help researchers collect, organize, cite, and share bibliographic information. Quarto is a free, open-source scientific and technical publishing system produced by Posit. These two programs can be combined to create books, scientific articles, websites, presentations, and many other products.

I suggest using these options because they are free, natively integrated, and highly flexible. This process allows for great flexibility, like rendering into HTML, PDF, or Word formats independently or all at once. I prefer multi-format rendering so I can send them all out in a zipped folder and the recipient can choose whichever works best for them.

Perhaps the most important element of this workflow, at least in my opinion, is that all your summary notes are maintained in Zotero. This allows you to keep any citation notes organized in the reference management software and not spread out across versions of bibliographic documentation.

What are potential alternatives?

Zotero provides a reporting functionality in the desktop application by right-clicking an item, selection of items, or an entire collection, then selecting “Generate Report From…”. This option works well if you need to quickly output your citations and notes, but is limited to exporting in HTML or Rich Text formats.

Another alternative workflow might be to use Obsidian, a freemium note-taking software that operates on Markdown files. This application integrates very well will Zotero as well, but my personal preference is Quarto in the RStudio environment. Consider following this tutorial if you want to use Obsidian.

Workflow in Zotero

Add Citations and Notes

The first step, which you may be at already, is to get literature into your Zotero library. There are a variety of ways to accomplish this, but I prefer using either the Add Item by Identifier tool or the web extension to automatically load documents into their respective libraries, collections, or sub-collections.

Once you have your literature in Zotero you can review each article as you normally would. While doing so, add in notes and annotations that summarize the main findings, key terms, important methods, and so forth. An important note about this workflow is that each comment or annotation made on an article must be stored as an individual note item. Each of these will eventually become a bullet point in our final bibliography. Your Zotero should look similar to the below screenshot.

Example of a Zotero library item to include in our bibliography with each comment as an individual note item.

Example of a Zotero library item to include in our bibliography with each comment as an individual note item.

Export Item(s) as BibTeX

Once you have all your literature added to Zotero and any annotations you need to make based on your review of each article, it is now time to export this information. Just like with the reports, exporting can occur at the level of each item, selection of items, or entire collections. I have found it easiest to make sub-collections for major themes or sections.

In this step, we are simply exporting the information from Zotero into a portable BibTeX file with the .bib extension. Other similar extension types may work, but I have only tested the standard format. To export, you need to (1) right-click the item of interest, (2) select “Export…”, (3) ensure that the Format: BibTeX and the Export Notes options are selected, and (4) specify an accessible location to store this file. This should save a .bib file to this location containing all pertinent information and notes on the citation(s) of interest.

If you open up the .bib file you just exported, each included article should look similar to the following example. The annote portions contain the notes we added in the previous step.

@article{morisette_tracking_2009,
    title = {Tracking the rhythm of the seasons in the face of global change: phenological research in the 21st century},
    volume = {7},
    issn = {1540-9295, 1540-9309},
    shorttitle = {Tracking the rhythm of the seasons in the face of global change},
    url = {https://esajournals.onlinelibrary.wiley.com/doi/10.1890/070217},
    doi = {10.1890/070217},
    abstract = {Phenology is the study of recurring life‐cycle events, classic examples being the flowering of plants and animal migration. Phenological responses are increasingly relevant for addressing applied environmental issues. Yet, challenges remain with respect to spanning scales of observation, integrating observations across taxa, and modeling phenological sequences to enable ecological forecasts in light of future climate change. Recent advances that are helping to address these questions include refined landscape‐scale phenology estimates from satellite data, advanced, instrument‐based approaches for field measurements, and new cyberinfrastructure for archiving and distribution of products. These breakthroughs are improving our understanding in diverse areas, including modeling land‐surface exchange, evaluating climate–phenology relationships, and making land‐management decisions.},
    language = {en},
    number = {5},
    urldate = {2023-12-31},
    journal = {Frontiers in Ecology and the Environment},
    author = {Morisette, Jeffrey T and Richardson, Andrew D and Knapp, Alan K and Fisher, Jeremy I and Graham, Eric A and Abatzoglou, John and Wilson, Bruce E and Breshears, David D and Henebry, Geoffrey M and Hanes, Jonathan M and Liang, Liang},
    month = jun,
    year = {2009},
    pages = {253--260},
    annote = {Given the increasing rate of climate change projected over the next 80 years, there is a pressing need to establish the spatial and temporal phenological responses to climate change.
},
    annote = {“help us to adapt to climate change and to better manage our natural resources.” (Morisette et al., 2009, p. 259) “Cyberinfrastructure will enable these data to be synthesized and used by increasingly advanced spatial–temporal analysis and modeling activities” (Morisette et al., 2009, p. 259)
},
    annote = {Predicting and assessing phenological responses can be difficult due to issues associated with spatial scale and physiological response differences across taxa.
}

Important Note - If you update any metadata about the citation (e.g., authors, abstract, etc.) or add/edit item notes you will need to re-export a .bib file to see these updates carried throughout this workflow. That is unless you use the Better BibTeX for Zotero Extension, which can automatically re-export the collection to a .bib file.

Workflow in Quarto

These next steps will all be carried out using Quarto within RStudio. At the time of this post, I am using this workflow with R version 4.3.2, Quarto version 1.4.510, and RStudio version 2023.09.1 without issues. Some of these steps may need to be adapted based on your working versions and system configuration. This post assumes you have successfully installed Quarto on your machine and are comfortable with markdown document creation using this program.

Setup YAML Header

When starting a new Quarto document, often one of the first steps is setting up your YAML header. This initial bit of code is bordered by --- on the top and bottom, and contains the necessary elements that tells Quarto how to generate the document.

---
1title: "Literature Review"
title-block-banner: true
2format:
  html: default
  docx: default
  pdf: default
3bibliography: exported_items.bib
4link-citations: false
5csl: apa-cv.csl
6execute:
  echo: false
  warning: false
  output: asis
---
1
Set the title and title banner formatting for the document.
2
Specify which output formats to render, including any options (defaults used in this example).
3
Specify the BibTeX file to reference. This will be the one we just exported from Zotero with our notes.
4
Tell Quarto whether to link each in-text citation to the full bibliography at the bottom.
5
Important step! - Specify what CSL (Citation Style Language) to use for the bibliography. This example uses the APA-CV style because it formats the full citation text for both the in-text and references section. This style and many others can be downloaded from the Zotero Style Repository.
6
Set the document-wide execution options for the code chunks. Here we suppress both the code and warning messages. Specifying output: asis allows for the bullet points to be rendered as raw markdown.

Load Packages

There are only two packages needed to perform the required steps. The first is the bib2df package, which is a BibTeX parser that turns .bib files into easy-to-read tibbles. The second is the dplyr package within the tidyverse, which allows us to wrangle, filter, and select data from our parsed dataframe. Install these packages as necessary from CRAN, then load them into your environment.

# Load these required packages
library(tidyverse) # --- for data wrangling
library(bib2df)    # --- for .bib parsing

Specifying Literature to Cite

Quarto is very similar to many other markdown formats, including RMarkdown, such that you can add in-text citations based on their citation keys. Zotero will generate these automatically when exporting the .bib file, but can sometimes lead to issues if they change with successive exports. To resolve this, a good option is to use the Better BibTeX for Zotero Extension which makes it easier to manage your citation keys.

The following code provides an example of how to insert a citation into your Quarto document. Traditionally, this is how an in-text citation would be placed at that location, but since we specified our CSL as the APA-CV style it will render the entire citation instead. The morisette_tracking_2009 portion is the citation key and will be referenced in the next part as well.

@morisette_tracking_2009

After you insert the proper citation, the next part is a chunk of executable R code. This is the meat and potatoes of the whole operation.

This chunk will need to be copy-pasted after each citation key you want to use. Then you will need to copy the citation key and paste it into whichever chunk follows it.

1df <- bib2df::bib2df(file = rmarkdown::metadata$bibliography) |>
2  filter(BIBTEXKEY == "morisette_tracking_2009") |>
3  select(contains("ANNOTE")) |>
  gather(key = "Column", value = "Value") |>
  pull(Value)

4list <- paste("- ", df, collapse = "\n")
cat(list)
1
Using the bib2df function, parse the .bib file specified in the YAML into a dataframe. The rmarkdown::metadata$bibliography does not need to be changed between citation code chunks.
2
Filter this new dataframe for the citation of interest as specified by its citation key. This is the only portion of the code chunk that will need to be changed between citations to update the citation key text in the parentheses.
3
Select only the fields for our annotations, which are parsed as “ANNOTE”. Then collect a vector of these character strings.
4
To create the bullet list, this part adds a “-” before and a linebreak after each note. Then we concatenate and print our notes, which output as an un-ordered list as raw markdown to be rendered.

This chunk is strictly optional, but makes the process a little less cluttered. Here, we create a function to pull the notes associated with that specific key. Place this chunk at the beginning of the document, then you can just call the pull_notes function instead of repeating the whole chunk each time.

pull_notes <- function(key) {
  df <- bib2df::bib2df(file = rmarkdown::metadata$bibliography) |> 
    filter(BIBTEXKEY == key) |>              
    select(contains("ANNOTE")) |>                                  
    gather(key = "Column", value = "Value") |>                     
    pull(Value)                                                    
  
  list <- paste("- ", df, collapse = "\n")                         
  cat(list)                                                        
}

So after each citation key, you can just paste the following to run the function:

pull_notes(key = "morisette_tracking_2009")

Sidenote for Better BibTeX

For anyone using the Better BibTeX extension, the structure of the exported .bib file varies slightly from the one exemplified above. If you exported an item or collection from Zotero with the Format: Better BibTeX option set the annotations will not be individually separated. Instead, they will appear in the same field. But no worries, we have an alternative solutions for this.

Here is an example .bib file when exporting using the BetterBibTeX format. See how all of our annotations are combined into a single “note” field and that they are separated by a \par? That is the main difference than the previous .bib file we looked at.

@article{MorisetteRichardsonKnapp:2009,
  title = {Tracking the Rhythm of the Seasons in the Face of Global Change: Phenological Research in the 21st Century},
  shorttitle = {Tracking the Rhythm of the Seasons in the Face of Global Change},
  author = {Morisette, Jeffrey T and Richardson, Andrew D and Knapp, Alan K and Fisher, Jeremy I and Graham, Eric A and Abatzoglou, John and Wilson, Bruce E and Breshears, David D and Henebry, Geoffrey M and Hanes, Jonathan M and Liang, Liang},
  year = {2009},
  month = jun,
  journal = {Frontiers in Ecology and the Environment},
  volume = {7},
  number = {5},
  pages = {253--260},
  issn = {1540-9295, 1540-9309},
  doi = {10.1890/070217},
  urldate = {2023-12-31},
  abstract = {Phenology is the study of recurring life-cycle events, classic examples being the flowering of plants and animal migration. Phenological responses are increasingly relevant for addressing applied environmental issues. Yet, challenges remain with respect to spanning scales of observation, integrating observations across taxa, and modeling phenological sequences to enable ecological forecasts in light of future climate change. Recent advances that are helping to address these questions include refined landscape-scale phenology estimates from satellite data, advanced, instrument-based approaches for field measurements, and new cyberinfrastructure for archiving and distribution of products. These breakthroughs are improving our understanding in diverse areas, including modeling land-surface exchange, evaluating climate{\textendash}phenology relationships, and making land-management decisions.},
  langid = {english},
  note = {1. ``help us to adapt to climate change and to better manage our natural resources.'' (Morisette et al., 2009, p. 259) ``Cyberinfrastructure will enable these data to be synthesized and used by increasingly advanced spatial{\textendash}temporal analysis and modeling activities'' (Morisette et al., 2009, p. 259)
\par
2. Given the increasing rate of climate change projected over the next 80 years, there is a pressing need to establish the spatial and temporal phenological responses to climate change.
\par
3. Predicting and assessing phenological responses can be difficult due to issues associated with spatial scale and physiological response differences across taxa.},
  file = {Morisette et al. - 2009 - Tracking the rhythm of the seasons in the face of .pdf}
}

To handle this difference, we can use the ReadBib function in the RefManageR package instead of bib2df.

library(tidyverse) # for dplyr and stringr
library(RefManageR) # for ReadBib function

df <- RefManageR::ReadBib(file = rmarkdown::metadata$bibliography) |> 
  as_tibble(rownames = "BIBTEXKEY") |> 
  filter(BIBTEXKEY == "morisette_tracking_2009") |> 
  select(contains("Note")) |> 
  pull(contains("Note")) |> 
  str_split_1(pattern = "\n\\\\par\n")

  cat(paste0(gsub("`", "\\\\'", df), "\n"))

Render into Preferred Format

The final, and often most nerve-racking, step is to render our .qmd document. As I mentioned earlier, there are several formats we can use (e.g., .pdf, .docx). I tend to render into HTML initially, then troubleshoot Pandoc conversion issues with other formats once I know it compiles.

If everything goes as planned, you should end up with a document looking similar to the below examples. Styles will depend on your configuration and can be adjusted to fit your needs. For this example, I have placed a single citation and its summary notes under a heading titled “Ecological Phenology”, which could be a broad theme or a way to structure your thesis sections. A comprehensive bibliography will be printed at the end of the document showing all citations from the citation keys referenced throughout.

---
title: "Literature Review for Masters Thesis"
title-block-banner: true           
format:                            
  html: default                    
  docx: default                    
  pdf: default                     
bibliography: exported_items.bib   
link-citations: false              
csl: apa-cv.csl                    
execute:                           
  echo: false                      
  warning: false                   
  output: asis                     
---

## Ecological Phenology

@morisette_tracking_2009

```r
df <- bib2df::bib2df(file = rmarkdown::metadata$bibliography) |>
  filter(BIBTEXKEY == "morisette_tracking_2009") |>
  select(contains("ANNOTE")) |>
  gather(key = "Column", value = "Value") |>
  pull(Value)

list <- paste("- ", df, collapse = "\n")
cat(list)
```

## References

::: {#refs}
:::

You can see that each of the notes we exported from Zotero are now their own bullet point under their respective citation. One potential alteration to this would be to concatenate all the notes into a single paragraph or to make the un-ordered list into an ordered one. The annotations in the .bib file are parsed in the order they appear in Zotero which is alphabetical by default. Feel free to mess around will the different formats and styles to create a final product that meets your needs.

Final Thoughts

This process has worked exceptionally well for me so far in my academic journey. I am a huge proponent of open-source programs, like Quarto, that help make research and technical publishing more streamlined.

If you are interested in other cool ways to handle citations and bibliographies in Quarto, I highly suggest checking out the website of Andrew Heiss. If others have suggestions on improving this workflow or techniques of handling this sort of literature review another way, I would love to hear more about it. Happy citing!

Citation

BibTeX citation:
@online{tjepkes2024,
  author = {Tjepkes, Benjamin},
  title = {Create {Annotated} {Bibliographies} with {Quarto}},
  date = {2024-01-01},
  url = {https://btjepkes.github.io/posts/building-annotated-bibliographies-with-quarto},
  langid = {en}
}
For attribution, please cite this work as:
Tjepkes, Benjamin. 2024. “Create Annotated Bibliographies with Quarto.” January 1, 2024. https://btjepkes.github.io/posts/building-annotated-bibliographies-with-quarto.