Zotero Reader Position Stack is a Zotero desktop plugin that adds an explicit, persistent position tree for each reader attachment. It is useful when reading papers or books non-linearly and you want movable reading positions, move back to a parent position, and return to branches without relying on Zotero's normal linear navigation history.
Each tree element is the live position for that branch: while you read, the current node moves with the reader. The plugin stores Zotero reader positions as opaque restorable payloads, so the tree model is independent of PDF, EPUB, or snapshot-specific details.
- Per-attachment persistent position trees.
- Explicit
Push Position,Pop Position, andForward Branchcommands. - A popup tree selector with keyboard navigation.
- Manual subtree deletion and session-only delete undo.
- User-configurable keyboard shortcuts.
- Reader menu entries under
Go -> Reader Position Stack.
This plugin targets Zotero desktop 9.0.4 or newer.
Zotero 6 and older are not supported. Zotero 7 compatibility has not been tested.
Download reader-position-stack.xpi from the release artifacts and install it in Zotero:
- Open Zotero.
- Go to
Tools -> Add-ons. - Choose
Install Add-on From File.... - Select
reader-position-stack.xpi. - Restart Zotero.
For development from this source tree, create an extension proxy file in your Zotero profile's extensions directory:
reader-position-stack@local
The file contents should be the absolute path to this repository root:
/path/to/zotero-reader-position-stack
Restart Zotero after creating or changing the proxy.
Open a PDF, EPUB, or snapshot in Zotero Reader and use Go -> Reader Position Stack.
Push Positioncreates a child branch at the active reader position and makes it current.Pop Positionsaves the current branch's latest reader position, then moves to the current node's parent.Forward Branchsaves the current branch's latest reader position, then moves to the last-active child branch.Select Position...opens the tree selector.Delete Current Nodedeletes the current node subtree, except the root.Delete Current Childrendeletes all children of the current node.Undo Deleterestores the most recent delete transaction for the active document during the current Zotero session.
Inside the tree selector:
Up/Downchanges the selected row.Home/Endjumps to the first or last row.Enternavigates to the selected node.Deletedeletes the selected node.Shift+Deletedeletes the selected node's children.Escapecloses the selector.
The selector updates while it is open when the active position moves.
No shortcuts are assigned by default.
Configure shortcuts in Zotero Preferences under Reader Position Stack. Each field accepts strings such as:
Accel+Alt+P
Ctrl+Shift+[
Shift+Delete
Alt+Left
F8
Accel maps to Ctrl on Linux and Windows and Cmd on macOS. Leave a field blank to disable that shortcut. Changes apply to open Zotero windows without restarting.
Tree data is stored in the Zotero profile as:
reader-position-stack.json
Delete undo is intentionally not persisted. Only the most recent delete transaction per attachment is kept in memory for the current Zotero session.
Install dependencies if needed, then run:
npm test
npm run buildThe packaged extension is written to:
dist/reader-position-stack.xpi
dist/ is ignored by git because it contains generated artifacts.
- Update
versioninmanifest.jsonandpackage.json. - Run
npm test. - Run
npm run build. - Upload
dist/reader-position-stack.xpito the GitHub release. - Install the uploaded XPI in a clean Zotero profile and smoke-test push, pop, forward, selector navigation, deletion, undo delete, and shortcut configuration.
bootstrap.js: Zotero plugin bootstrap and chrome registration.content/controller.js: command handling and lifecycle coordination.content/reader-adapter.js: Zotero Reader capture and restore integration.content/tree-model.js: persistent tree model.content/selector.js: popup selector UI.content/keymap.js: preference-backed shortcut parsing and binding.preferences.xhtml,preferences.css,prefs.js: shortcut preference UI and defaults.tests/: Node tests for pure logic.