My Zotero annotation template that works

I have made some tweaks to group and name annotations groups with the help of AI. See below for example.

---
{% if title %}Title: "{{title}}"{% endif %}
Authors: {{authors}}{{directors}}
{% if publicationTitle %}Publication: "{{publicationTitle}}"{% endif %}
{% if date %}Date: {{date | format("YYYY-MM-DD")}}{% endif %}
citekey: {{citekey}}
tags: {{hashTags}}
---
## {{title}}
Bibliography : {{bibliography}}
Link to publication : {{url}}
Link Zotero : {{pdfZoteroLink}}
Zotero Tags : {{hashTags}} 
>[!abstract]+
>« {{abstractNote}} »

{% set colorMappings = {

    "#5fb236": "Essential information (Green)",
    
    "#2ea8e5": "Unassigned color category (Blue)",

    "#aaaaaa": "Follow up references (Grey)",
    
    "#ff6666": "Author challenge / Disagreement (Red)",
      
    "#a28ae5": "Definition (Purple)",
     
    "#ffd400": "Highlight (Yellow)",

    "#e56eee": "Personal take (Magenta)",
      
    "#f19837": "Futher reading on concept (Orange)"

} %}

{% for color, calloutName in colorMappings %}
## <span style="color:{{color}}">{{calloutName}}</span>
{% for annotation in annotations %}
{% if annotation.color == color %}
>[!{{calloutName}}|{{annotation.color}}]+ 
>{%- if annotation.annotatedText -%}« {{annotation.annotatedText}} »([{{annotation.page}}](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.page}}&annotation={{annotation.id}})){% endif %}{% if annotation.imageRelativePath %}![[{{annotation.imageRelativePath}}]]{% endif %}{% if annotation.comment %} 
>
>{{annotation.comment}}{%- endif %}
{% endif %}
{% endfor %}
{% endfor %}

  • Removed the colour from the headers, as html span tags were used. However the tags didn’t render in Reading view if headers were used as internal links, and appeared as part of the header name.
  • Added coloured emojis instead. Placed at the end of the header, as at the start makes internal header links more difficult to work with.

-Removed nunjuck white space in editing view.

---
{% if title %}Title: "{{title}}"{% endif %}
Authors: {{authors}}{{directors}}
{% if publicationTitle %}Publication: "{{publicationTitle}}"{% endif %}
{% if date %}Date: {{date | format("YYYY-MM-DD")}}{% endif %}
citekey: {{citekey}}
tags: {{hashTags}}
---
## {{title}}
Bibliography : {{bibliography}}

Link to publication : {{url}}

Link Zotero : {{pdfZoteroLink}}

Zotero Tags : {{hashTags}} 
>[!abstract]+
>« {{abstractNote}} »

{%- set colorMappings = {
    "#a28ae5": "Definition 🟪 ",
    "#ffd400": "Highlight 🟨",
    "#ff6666": "Author challenge / Disagreement 🟥",
    "#e56eee": "Personal take 🧠 ",
    "#f19837": "Further reading on concept 🟧 ",
    "#5fb236": "Essential information 🟩 ",
    "#aaaaaa": "Follow up references ⬜ ",
    "#2ea8e5": "Unassigned colour category 🟦"
} -%}
{%- for color, calloutName in colorMappings -%}
{%- set hasAnnotations = false -%}
{%- for annotation in annotations -%}
{%- if annotation.color == color -%}
{%- set hasAnnotations = true -%}
{%- endif -%}
{% endfor %}
{% if hasAnnotations -%}
## {{calloutName}}
{%- for annotation in annotations -%}
{% if annotation.color == color %}
>[!{{calloutName}}|{{annotation.color}}]+ 
>{% if annotation.annotatedText %}« {{annotation.annotatedText}} »([{{annotation.page}}](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.page}}&annotation={{annotation.id}})){% endif %}{% if annotation.imageRelativePath %}![[{{annotation.imageRelativePath}}]]{% endif %}{% if annotation.comment %} 
>
>
>_**{{annotation.comment}}**_»([{{annotation.page}}](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.page}}&annotation={{annotation.id}})){% endif %}
{% endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}

1 Like

Hey, I have many PDFs with chapter sections. In PDF Expert I can export my annotations to markdown and it treats those section headings as markdown headings. Example:

# Riepilogo note di Guichard 2012 – Eau et société dans l’islam occidental.pdf.
#### Introduction
 *Sottolinea [pagina 2]:* Les musulmans ont en effet entretenu avec l’eau un rapport conditionné par des faits qui tiennent à la fois à la civilisation arabe originelle, aux règles religieuses édictées par le Prophète, et au milieu géographique où s’est développée la nouvelle civilisation.

 *Sottolinea [pagina 2]:* Dans la pratique même de l’islam, la grande importance donnée à la pureté rituelle faisait de l’eau un élément volontiers considéré comme presque indispensable à l’exercice même des obligations religieuses.

#### Le thème de l’eau dans la littérature
 *Sottolinea [pagina 3]:* une énumération et analyse des vocables liés à l’eau à laquelle s’est livrée Francisco Vidal Castro.

Is there any way to have something similar with Zotero and Obsidian? How can I account for that in my Zotero Integration template?

1 Like

hey all! I have a question:
in Zotero I do not use highlights of different colors, instead I tag my highlights.
in Obsidian I would like to get my annotation grouped by tag rather than color (for example all the annotation / highlights tagged “questions” should have “questions” as group title and then be one after the other under that).

Any help is appreciated, I am not able to find a solution or an already existing template..

I think you could use @Feralflora template (link here) and adapt the line {%- set grouped_annotations = annotations | groupby("color") -%} with color replaced by tag. The main drawback is that it’s not an easy template to begin with.
Hopefully this helps even if tests would probably be required.

2 Likes

Hi everyone,

I’m trying to adapt an existing “Zotero-Obsidian import template” to fit my own workflow. My goal is to group Zotero annotations (highlighted text + comments + tags) into predefined sections of my note based on the highlight color.

The idea is:

- highlight text in Zotero using different colors (e.g. red = critique, yellow = results, blue = methods)

-When importing into Obsidian, each annotation should automatically be written into a specific section of the template corresponding to its color

-I also use a CSS snippet to visually style the highlights, but the grouping itself should happen at import time via the template.

At the moment, the import works, but all annotations are inserted together and I have to manually sort them into the correct sections afterward. (see section “In-text annotations”)

I’ve tried filtering annotations in the template using their color (e.g. looping over annotations and checking the color field), but it doesn’t behave as expected.

My questions are:

Is it possible to group Zotero annotations by color directly in an Obsidian import template?

Which annotation field should be used for this (color, colorCategory, or something else)?

Is there a known limitation of the Zotero Integration / Citations / Highlightr plugins that would prevent this?
Thanks a lot for any pointers!

My template:

---
title: "{{title | escape}}"
year: {{date | format("YYYY")}}
authors: {{authors}}
citekey: {{citekey}}
tags: [{% for t in tags %}{{t.tag}}{% if not loop.last %}, {% endif %}{% endfor %}]
---
# {{title | escape}}

**Authors:** {{authors}}  
**Year:** {{date | format("YYYY")}}

---
## Links
- [PDF]({{citekey}}.pdf)  
- [Zotero item]({{zoteroSelectURI}})

---
## Abstract
{% if abstractNote %}
{{abstractNote | safe}}
{% else %}
*No abstract available.*
{% endif %}

---

> [!note]+ Atomic Notes
> {% persist "atomic-notes" %}
> Write the **core ideas of this paper in your own words**.
> - One idea per paragraph  
> - Phrase ideas so they can stand alone  
> - Link concepts to other notes  
> {% endpersist %}

---

## Annotations

---

{% set groups = {
  "magenta": {
    "title": "🟣 Core concepts / hypotheses / frameworks",
    "question": "What is the central idea or hypothesis?",
    "persist": "synthesis-core-concepts"
  },
  "gray": {
    "title": "⚫ Background / definitions / context",
    "question": "What do I need to understand the paper?",
    "persist": "synthesis-background"
  },
  "red": {
    "title": "🔴 Contradictions / critical issues",
    "question": "What conflicts with other studies or assumptions?",
    "persist": "synthesis-contradictions"
  },
  "yellow": {
    "title": "🟡 Key empirical results",
    "question": "What did they actually find?",
    "persist": "synthesis-results"
  },
  "blue": {
    "title": "🔵 Methods & experimental design",
    "question": "How was this measured or tested?",
    "persist": "synthesis-methods"
  },
  "green": {
    "title": "🟢 Mechanisms & ecological interpretation",
    "question": "Why does this happen biologically/ecologically?",
    "persist": "synthesis-mechanisms"
  },
  "orange": {
    "title": "🟠 Limitations & uncertainties",
    "question": "Where does this break down?",
    "persist": "synthesis-limitations"
  }
} %}

{% for color, g in groups %}
### {{ g.title }}
**Question answered:** _{{ g.question }}_

{% for a in annotations if a.annotatedText and a.colorCategory == color %}
> **Excerpt (p. {{ a.pageLabel }}):**  
> "{{ a.annotatedText | safe }}"
{% if a.comment %}
> _Note:_ {{ a.comment | safe }}
{% endif %}
>
{% endfor %}

> [!summary]+ Synthesis — {{ g.title | replace("🟣","") | replace("⚫","") | replace("🔴","") | replace("🟡","") | replace("🔵","") | replace("🟢","") | replace("🟠","") }}
> {% persist g.persist %}
> 
> {% endpersist %}
{% endfor %}

---
### In-text annotations

{% for annotation in annotations -%}
{%- if annotation.annotatedText -%}
{% if annotation.color %} <mark class="hltr-{{annotation.colorCategory | lower}}">"{{annotation.annotatedText | safe}}"</mark> {% else %} {{annotation.type | capitalize}} {% endif %}[Page {{annotation.pageLabel}}](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.pageLabel}}&annotation={{annotation.id}})
{%- endif %}
{% if annotation.comment %}
{{annotation.comment | safe}} [Page {{annotation.pageLabel}}](zotero://open-pdf/library/items/{{annotation.attachment.itemKey}}?page={{annotation.pageLabel}}&annotation={{annotation.id}})
{% endif %}
{%- if annotation.imageRelativePath %} 
![[{{annotation.imageRelativePath}}]]
{%- endif %}
{% if annotation.allTags %}
{{annotation.allTags}}
{% endif %}
{% endfor -%}

My css snippet

/* Base Zotero highlight styling */
mark[class^="hltr-"] {
  opacity: 0.75;
  padding: 0.15em 0.4em;
  border-radius: 6px;
  line-height: 1.6;
  font-weight: 500;
  position: relative;
}

mark.hltr-magenta {
  background-color: rgba(242, 114, 212, 0.25);
  border-left: 4px solid #f272d4;
}

mark.hltr-magenta::before {
  content: "Concept / Hypothesis";
  font-size: 0.7em;
  font-weight: 700;
  color: #b24c9c;
  margin-right: 0.5em;
}

mark.hltr-gray {
  background-color: rgba(149, 165, 166, 0.25);
  border-left: 4px solid #7f8c8d;
}

mark.hltr-gray::before {
  content: "Background";
  font-size: 0.7em;
  font-weight: 700;
  color: #5f6a6a;
  margin-right: 0.5em;
}

mark.hltr-blue {
  background-color: rgba(52, 152, 219, 0.25);
  border-left: 4px solid #3498db;
}

mark.hltr-blue::before {
  content: "Method";
  font-size: 0.7em;
  font-weight: 700;
  color: #21618c;
  margin-right: 0.5em;
}

mark.hltr-yellow {
  background-color: rgba(255, 221, 87, 0.35);
  border-left: 4px solid #f1c40f;
}

mark.hltr-yellow::before {
  content: "Result";
  font-size: 0.7em;
  font-weight: 700;
  color: #a67c00;
  margin-right: 0.5em;
}

mark.hltr-green {
  background-color: rgba(46, 204, 113, 0.25);
  border-left: 4px solid #2ecc71;
}

mark.hltr-green::before {
  content: "Mechanism";
  font-size: 0.7em;
  font-weight: 700;
  color: #1e8449;
  margin-right: 0.5em;
}
mark.hltr-purple {
  background-color: rgba(178, 114, 242, 0.25);
  border-left: 4px solid #b272f2;
}

mark.hltr-purple::before {
  content: "Model / Theory";
  font-size: 0.7em;
  font-weight: 700;
  color: #6c3483;
  margin-right: 0.5em;
}

mark.hltr-orange {
  background-color: rgba(230, 126, 34, 0.25);
  border-left: 4px solid #e67e22;
}

mark.hltr-orange::before {
  content: "Limitation / Question";
  font-size: 0.7em;
  font-weight: 700;
  color: #935116;
  margin-right: 0.5em;
}

mark.hltr-red {
  background-color: rgba(231, 76, 60, 0.25);
  border-left: 4px solid #e74c3c;
}

mark.hltr-red::before {
  content: "Critical";
  font-size: 0.7em;
  font-weight: 700;
  color: #922b21;
  margin-right: 0.5em;
}

1 Like

Thank you so much! Your template was easy to read and organise!