# fdossi/zotfetch architecture

> Architecture diagram of the GitHub repository fdossi/zotfetch, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-11). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/fdossi/zotfetch
- Repository: https://github.com/fdossi/zotfetch

## Overview

ZotFetch is a Zotero plugin for batch PDF acquisition. Its main workflow extracts identifiers from selected library items, builds ordered source candidates, resolves landing pages to validated PDF URLs, then imports the PDF as an attachment; batch modes also support retries and live progress. Separate capabilities include publisher-specific and browser-based extraction, proxy/CAPES access, request pacing and challenge protection, and preferences. The README documents several source routes and extraction behaviors whose detailed wiring was not sampled; those are represented at subsystem level.

Main entry points: [`chrome/content/fetch.mjs`](https://github.com/fdossi/zotfetch/blob/master/chrome/content/fetch.mjs) (Batch orchestration), [`chrome/content/pdf-resolvers.mjs`](https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs) (PDF resolver dispatch), [`chrome/content/ui.mjs`](https://github.com/fdossi/zotfetch/blob/master/chrome/content/ui.mjs) (Commands and progress), [`chrome/content/source-resolvers.mjs`](https://github.com/fdossi/zotfetch/blob/master/chrome/content/source-resolvers.mjs) (Source candidates)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_interaction["Zotero interaction"]
  node_ui["Commands and progress<br/>[ui.mjs]"]
end

subgraph group_pipeline["Acquisition pipeline"]
  node_batch["Batch orchestration<br/>[fetch.mjs]"]
  node_identifiers["Identifier extraction<br/>[identifiers.mjs]"]
  node_doi_lookup["DOI recovery<br/>[fetch.mjs]"]
  node_source_routes["Source candidates"]
  node_oa_services{{"OA lookup services"}}
  node_proxy_routes["Proxy and CAPES routes"]
  node_importer["Attachment import<br/>[importer.mjs]"]
end

subgraph group_resolution["PDF resolution"]
  node_pdf_resolvers["PDF resolver dispatch<br/>[pdf-resolvers.mjs]"]
  node_publisher_rules["Publisher extraction rules<br/>[pdf-resolvers.mjs]"]
  node_html_extractor["Generic HTML extraction<br/>[pdf-resolvers.mjs]"]
  node_hidden_browser["Hidden browser<br/>[pdf-resolvers.mjs]"]
  node_pdf_validation["PDF validation<br/>[pdf-resolvers.mjs]"]
end

subgraph group_resilience["Network resilience"]
  node_network["Safe network requests<br/>[utils.mjs]"]
  node_cooldown["Rate limiting<br/>[cooldown.mjs]"]
  node_host_protection["Challenge protection"]
end

subgraph group_settings["Preferences"]
  node_preferences["Preference services<br/>[prefs.mjs]"]
  node_prefs_dialog["Preferences dialog<br/>[prefs-dialog.js]"]
end

node_user(("Library user"))
node_zotero(("Zotero host"))

node_user -->|"selects commands"| node_ui
node_ui -->|"starts batches"| node_batch
node_batch -->|"extracts identifiers"| node_identifiers
node_batch -->|"recovers DOI"| node_doi_lookup
node_batch -->|"builds candidates"| node_source_routes
node_source_routes -.->|"queries sources"| node_oa_services
node_batch -->|"tries proxy routes"| node_proxy_routes
node_batch -->|"resolves candidates"| node_pdf_resolvers
node_pdf_resolvers -->|"applies rules"| node_publisher_rules
node_pdf_resolvers -->|"extracts links"| node_html_extractor
node_pdf_resolvers -->|"loads rendered pages"| node_hidden_browser
node_pdf_resolvers -->|"validates PDF"| node_pdf_validation
node_batch -->|"imports resolved PDF"| node_importer
node_pdf_resolvers -->|"requests documents"| node_network
node_source_routes -->|"requests source data"| node_network
node_batch -->|"checks request timing"| node_cooldown
node_batch -->|"checks host policies"| node_host_protection
node_ui -->|"opens settings"| node_preferences
node_prefs_dialog -->|"reads and saves"| node_preferences
node_batch -.->|"reports progress"| node_ui
node_zotero -.->|"provides library"| node_importer

click node_ui "https://github.com/fdossi/zotfetch/blob/master/chrome/content/ui.mjs"
click node_batch "https://github.com/fdossi/zotfetch/blob/master/chrome/content/fetch.mjs"
click node_identifiers "https://github.com/fdossi/zotfetch/blob/master/chrome/content/identifiers.mjs"
click node_doi_lookup "https://github.com/fdossi/zotfetch/blob/master/chrome/content/fetch.mjs"
click node_source_routes "https://github.com/fdossi/zotfetch/blob/master/chrome/content/source-resolvers.mjs"
click node_proxy_routes "https://github.com/fdossi/zotfetch/blob/master/chrome/content/source-resolvers.mjs"
click node_pdf_resolvers "https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs"
click node_publisher_rules "https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs"
click node_html_extractor "https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs"
click node_hidden_browser "https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs"
click node_pdf_validation "https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs"
click node_network "https://github.com/fdossi/zotfetch/blob/master/chrome/content/utils.mjs"
click node_importer "https://github.com/fdossi/zotfetch/blob/master/chrome/content/importer.mjs"
click node_cooldown "https://github.com/fdossi/zotfetch/blob/master/chrome/content/cooldown.mjs"
click node_host_protection "https://github.com/fdossi/zotfetch/blob/master/chrome/content/protected-hosts.mjs"
click node_preferences "https://github.com/fdossi/zotfetch/blob/master/chrome/content/prefs.mjs"
click node_prefs_dialog "https://github.com/fdossi/zotfetch/blob/master/chrome/content/prefs-dialog.js"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_ui,node_user toneBlue
class node_batch,node_identifiers,node_doi_lookup,node_source_routes,node_oa_services,node_proxy_routes,node_importer toneAmber
class node_pdf_resolvers,node_publisher_rules,node_html_extractor,node_hidden_browser,node_pdf_validation toneMint
class node_network,node_cooldown,node_host_protection toneRose
class node_preferences,node_prefs_dialog,node_zotero toneIndigo
```

## Components

### Zotero interaction

- [Commands and progress](https://github.com/fdossi/zotfetch/blob/master/chrome/content/ui.mjs): `chrome/content/ui.mjs`

### Acquisition pipeline

- [Batch orchestration](https://github.com/fdossi/zotfetch/blob/master/chrome/content/fetch.mjs): `chrome/content/fetch.mjs`
- [Identifier extraction](https://github.com/fdossi/zotfetch/blob/master/chrome/content/identifiers.mjs): `chrome/content/identifiers.mjs`
- [DOI recovery](https://github.com/fdossi/zotfetch/blob/master/chrome/content/fetch.mjs): `chrome/content/fetch.mjs`
- [Source candidates](https://github.com/fdossi/zotfetch/blob/master/chrome/content/source-resolvers.mjs): `chrome/content/source-resolvers.mjs`
- **OA lookup services**
- [Proxy and CAPES routes](https://github.com/fdossi/zotfetch/blob/master/chrome/content/source-resolvers.mjs): `chrome/content/source-resolvers.mjs`
- [Attachment import](https://github.com/fdossi/zotfetch/blob/master/chrome/content/importer.mjs): `chrome/content/importer.mjs`

### PDF resolution

- [PDF resolver dispatch](https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs): `chrome/content/pdf-resolvers.mjs`
- [Publisher extraction rules](https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs): `chrome/content/pdf-resolvers.mjs`
- [Generic HTML extraction](https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs): `chrome/content/pdf-resolvers.mjs`
- [Hidden browser](https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs): `chrome/content/pdf-resolvers.mjs`
- [PDF validation](https://github.com/fdossi/zotfetch/blob/master/chrome/content/pdf-resolvers.mjs): `chrome/content/pdf-resolvers.mjs`

### Network resilience

- [Safe network requests](https://github.com/fdossi/zotfetch/blob/master/chrome/content/utils.mjs): `chrome/content/utils.mjs`
- [Rate limiting](https://github.com/fdossi/zotfetch/blob/master/chrome/content/cooldown.mjs): `chrome/content/cooldown.mjs`
- [Challenge protection](https://github.com/fdossi/zotfetch/blob/master/chrome/content/protected-hosts.mjs): `chrome/content/protected-hosts.mjs`

### Preferences

- [Preference services](https://github.com/fdossi/zotfetch/blob/master/chrome/content/prefs.mjs): `chrome/content/prefs.mjs`
- [Preferences dialog](https://github.com/fdossi/zotfetch/blob/master/chrome/content/prefs-dialog.js): `chrome/content/prefs-dialog.js`

### Other components

- **Library user**
- **Zotero host**

## Connections

- Library user → Commands and progress: selects commands (evidence: `README.md`)
- Commands and progress → Batch orchestration: starts batches (evidence: `README.md`)
- Batch orchestration → Identifier extraction: extracts identifiers (evidence: `chrome/content/fetch.mjs`)
- Batch orchestration → DOI recovery: recovers DOI (evidence: `chrome/content/fetch.mjs`)
- Batch orchestration → Source candidates: builds candidates (evidence: `chrome/content/fetch.mjs`)
- Source candidates → OA lookup services: queries sources (evidence: `README.md`)
- Batch orchestration → Proxy and CAPES routes: tries proxy routes (evidence: `README.md`)
- Batch orchestration → PDF resolver dispatch: resolves candidates (evidence: `chrome/content/fetch.mjs`)
- PDF resolver dispatch → Publisher extraction rules: applies rules (evidence: `README.md`)
- PDF resolver dispatch → Generic HTML extraction: extracts links (evidence: `README.md`)
- PDF resolver dispatch → Hidden browser: loads rendered pages (evidence: `README.md`)
- PDF resolver dispatch → PDF validation: validates PDF (evidence: `README.md`)
- Batch orchestration → Attachment import: imports resolved PDF (evidence: `chrome/content/fetch.mjs`)
- PDF resolver dispatch → Safe network requests: requests documents (evidence: `chrome/content/pdf-resolvers.mjs`)
- Source candidates → Safe network requests: requests source data (evidence: `chrome/content/source-resolvers.mjs`)
- Batch orchestration → Rate limiting: checks request timing (evidence: `chrome/content/fetch.mjs`)
- Batch orchestration → Challenge protection: checks host policies (evidence: `chrome/content/fetch.mjs`)
- Commands and progress → Preference services: opens settings (evidence: `README.md`)
- Preferences dialog → Preference services: reads and saves (evidence: `chrome/content/prefs-dialog.js`)
- Batch orchestration → Commands and progress: reports progress (evidence: `README.md`)
- Zotero host → Attachment import: provides library (evidence: `README.md`)
