Skip to content

Migration

Josh Glazer edited this page Aug 19, 2026 · 3 revisions

Migrating to the New Enhanced Notes

This page outlines how to transition from windingwind's original zotero-better-notes plugin to this updated fork. It explains the core architectural improvements, how note templates differ in the new sandboxed model, and how to migrate your existing notes, sync links, and templates.


What's Different in This Fork?

This version is a modernized, streamlined rebuild focusing on security, efficiency, and robustness. The key differences are:

Subsystem windingwind's Original This Fork Benefit
Template Engine Arbitrary JavaScript (AsyncFunction compiler) Sandboxed LiquidJS engine No RCE security risk; templates cannot execute arbitrary system or file-access commands.
Data Access Full Zotero & BetterBibTeX API exposed Bounded, curated data model (item.*, note.*) Simpler authoring, robust autocomplete, and no database corruption risks.
Sync Efficiency O(N) periodic polling and hashing of every file and note Event-driven exports + stat-gated (mtime) checks Eliminated CPU and disk churn. Sync checks only files that actually changed on disk.
Background Sync Polling only ran when Zotero window was active Background sync runs while Zotero is unfocused Edits made in external editors (e.g. Obsidian) flow back into Zotero immediately.
Merge Logic 2-way diff modal on any concurrent change Automatic 3-way merge (diff3) Sync automatically integrates concurrent, non-overlapping edits, only prompting on line-level conflicts.
Sync Storage Sync/template state read and written directly through prefs.js at many call sites Centralized behind a single KVStore seam (LargePrefHelper); a database backend is a contained, deferred drop-in One isolated, swappable storage layer instead of scattered preference access (a DB swap is future groundwork, not yet shipped).
Front-Matter Injected $version, $libraryID, etc. into Markdown Slim, human-readable Markdown front-matter (tags, parent, collections, optional CitationKey) Removes plugin-internal clutter from your Obsidian vault.

How Templates Work Differently

In the legacy plugin, templates were compiled from arbitrary JavaScript template literals, allowing lines like topItem.getField("title") or IOUtils.writeUTF8().

In the new version, templates are sandboxed:

  1. Liquid Syntax: Replace ${ expr } (one-line) and ${{ ... }}$ (multi-line) JavaScript with standard Liquid {{ value }} and {% logic %} tags.
  2. Curated Variables: Instead of querying raw Zotero XPCOM items, you read fields from a safe data model:
    • item.title, item.year, item.abstract, item.doi, item.url
    • item.authors (array of { firstName, lastName, name } creators)
    • item.citekey (integrated Better BibTeX / citation key)
    • note.title, note.tags, note.key
  3. No Direct Database Writes: Side effects (such as auto-tagging notes) are declared in the Sentinel Header at the top of the file rather than through JavaScript.
    • Example: <!--addTags: ItemNote, Reference-->
  4. Custom Tags/Filters: Embedded components like annotations are rendered via custom tags ({% annotations %}) rather than custom JavaScript loops.

Built-In Template Converter

To make upgrading simple, the plugin includes a built-in transpiler that automatically converts legacy JavaScript templates into Liquid templates:

  • How to Use: Open the Note Template Editor (⌃⌥T), select your custom template, and select Options → Convert legacy JavaScript template to Liquid.
  • Best-Effort Translation: It translates common patterns (such as field access, year extraction, the citekey idiom, and pragma comments).
  • Manual Review Flag (BN-MIGRATE): Any complex, arbitrary JavaScript that cannot be safely converted to Liquid is commented out inside a {% comment %} BN-MIGRATE: ... {% endcomment %} block. The output is guaranteed to be valid Liquid, but you will need to review these comments to rewrite any advanced custom JS logic using Liquid filters or loops.

Step-by-Step Migration Plan

If you are upgrading from windingwind's original plugin, follow these steps:

1. Backup Your Data

Before starting, make a backup of:

  • Your Zotero profile directory.
  • Your external sync folder (e.g. your Obsidian vault where synced .md files are kept).
  • Any custom JavaScript templates you want to preserve (copy their raw text to a safe place).

2. Install the New Version

  1. Download the latest enhanced-notes.xpi from the releases page.
  2. In Zotero: Tools → Plugins → gear icon → Install Plugin From File.
  3. Select the .xpi file. (The new version will safely overwrite and replace the old plugin).
  4. Restart Zotero.

3. Clear Stale Sync Conflict States (If Any)

If you have synced notes left over from prior versions:

  • If Zotero prompts you with a sync conflict dialog on startup, hit Stop Syncing This Note or Keep Both.
  • This clears the legacy prefs.js sync states so the new sync engine can register and link the files cleanly.

4. Convert Your Custom Templates

  1. Open the Template Editor (⌃⌥T or Tools → Note Template Editor).
  2. Select your custom template from the list.
  3. Click Options → Convert legacy JavaScript template to Liquid.
  4. Check the template for any BN-MIGRATE comments. If you see them, replace the JS code with equivalent Liquid expressions or tags (see the Templates reference page).
  5. Click Save.

5. Validate Your Sync Paths

  1. Open the Sync Manager (⌃⌥M or Tools → Sync Manager).
  2. Confirm that your target sync directory is still set correctly.
  3. Trigger a manual sync (⌃⌥S) or edit a synced note to verify that modifications sync bidirectionally in the background.

Clone this wiki locally