Zotero Connectors use a Gulp-based build system orchestrated byDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/zotero/zotero-connectors/llms.txt
Use this file to discover all available pages before exploring further.
build.sh. A single build.sh invocation copies source files from src/, runs Babel to transpile JSX, injects the correct script lists into manifests, and writes finished extension directories under build/. The same pipeline produces both the Manifest V2 Firefox build and the Manifest V3 Chromium build from one shared source tree.
Prerequisites
Before building you need:- Node.js 20 (the version pinned in
.github/workflows/ci.yml) - npm (bundled with Node.js) — used to install all devDependencies
- Git with submodule support — the repo uses nested submodules for
src/translate,src/utilities, and others
The
package.json lists Gulp 4, Babel 7, Puppeteer 24, Mocha 11, React 16, and several other packages as devDependencies. All of these are installed by npm install — there is nothing to install globally except Node.js.Initial Setup
Clone the repository with submodules
--recursive flag initialises all git submodules in one step. If you already cloned without it, run init.sh (see below) to pull them in afterwards.Install npm dependencies
package.json.(Optional) Copy config.sh
config.sh to supply signing keys and deployment paths before doing a production build. See config.sh below for the full list of variables.Build Commands
build.sh accepts three option flags and can combine them freely:
| Flag | Meaning |
|---|---|
-d | Debug build — enables the translator tester UI, sets isDebug = true in zotero.js, skips minification |
-p b | Build only the browserExt target (Chrome / Firefox / Edge) |
-p s | Build only the Safari target |
-v VERSION | Override the version string injected into manifests and zotero.js (defaults to 4.999.0) |
-p b nor -p s is given, both targets are built. When TEST_CHROME=1 or TEST_FX=1 is set in the environment, build.sh automatically selects the browserExt target; TEST_SAFARI=1 selects the Safari target.
Build Output
The script starts by building a common
build/browserExt/ directory, then rsyncs it into build/manifestv3/ and renames the original to build/firefox/. Each copy then receives browser-specific post-processing (icon sizes, manifest applications field removal for Chrome, etc.).Automatic Rebuilding with gulp watch
After doing an initial build, leave a watch process running so that any file change triggers an incremental recompile:
gulp watch monitors ./src/browserExt/**, ./src/common/**, ./src/safari/**, and the Google Docs integration connector sources. When a file changes it is passed through the same processFile() pipeline that the full build uses and written directly to build/.
A variant task gulp watch-chrome additionally calls chrome-cli to reload the Chrome extensions tab automatically.
Gulp Tasks
All Gulp logic lives ingulpfile.js. The main task is process-custom-scripts:
processFile() stream transform handles each source file:
.jsxfiles — transpiled with@babel/plugin-transform-react-jsxand@babel/plugin-proposal-class-properties; the.jsxextension is stripped to produce.jszotero_config.js— environment variable overrides forZOTERO_GOOGLE_DOCS_DEV_MODE,ZOTERO_GOOGLE_DOCS_API_URL,ZOTERO_GOOGLE_DOCS_OAUTH_CLIENT_KEY,ZOTERO_REPOSITORY_URL, andZOTERO_ALWAYS_FETCH_FROM_REPOSITORYare substituted at build timezotero.js—isDebuganddebug.logare set totruein debug builds;allowRepoTranslatorTesteris set based on whetherZOTERO_REPOSITORY_URLis definedschema.js— the/*ZOTERO_SCHEMA*/placeholder is replaced with the inlined JSON fromsrc/zotero-schema/schema.jsonmanifest.json/manifest-v3.json—/*BACKGROUND SCRIPTS*/and/*INJECT SCRIPTS*/placeholders are replaced with the correct script arrays; the version string is injected- HTML files (
preferences.html,progressWindow.html, etc.) —<!--BEGIN DEBUG-->…<!--END DEBUG-->blocks are stripped in production builds
build/manifestv3/, build/firefox/, or build/safari/ directory.
The config.sh File
Copy config.sh-sample to config.sh and fill in the values you need:
build.sh sources config.sh at startup if the file exists. The file is listed in .gitignore so credentials are never committed.
The environment variables used by the Gulp build pipeline —
ZOTERO_GOOGLE_DOCS_DEV_MODE, ZOTERO_GOOGLE_DOCS_API_URL, ZOTERO_GOOGLE_DOCS_OAUTH_CLIENT_KEY, ZOTERO_REPOSITORY_URL, and ZOTERO_ALWAYS_FETCH_FROM_REPOSITORY — are separate from the deployment variables in config.sh. Set them directly in your shell environment or in a wrapper script before invoking build.sh.The init.sh Script
init.sh is a lightweight helper that sources config.sh (if present) and sets BUILD_DIR to <repo-root>/dist if it is not already defined in the environment. It is intended to be sourced by other automation scripts, not run directly, and is not a replacement for git submodule update --init --recursive.
If you need to reinitialise submodules after a fresh clone (without --recursive), run:
Browser-Specific Bundle Generation with scripts/replace_browser.js
The gulpfile.js calls replaceBrowser(contents, options) from scripts/replace_browser.js when processing zotero.js. It rewrites the browser-detection comment stubs to concrete true/false assignments:
src/common/zotero.js produces browser-specific values for Zotero.isFirefox, Zotero.isBrowserExt, Zotero.isManifestV3, and Zotero.isSafari at build time.
MV2 vs MV3 Build Targets
Firefox (build/firefox/) | Chrome/Edge (build/manifestv3/) | |
|---|---|---|
| Manifest version | 2 | 3 |
| Background | Event page (background.js, scripts array) | Service worker (background-worker.js) |
| Source manifest | src/browserExt/manifest.json | src/browserExt/manifest-v3.json |
| Inject scripts | injectIncludeBrowserExt list | injectIncludeManifestV3 list (adds virtualOffscreenTranslate.js) |
| Offscreen docs | Not needed | offscreen/offscreen.html, offscreen/offscreenSandbox.html |
"minimum_chrome_version": "88" and uses the offscreen permission; the MV2 manifest sets "strict_min_version": "58.0" inside the applications.gecko block.
Running from the Build Directory
- Chrome / Edge
- Firefox
- Safari
- Navigate to
chrome://extensions/(oredge://extensions/) - Enable Developer mode
- Click Load unpacked and select
build/manifestv3/
CI Pipeline
The GitHub Actions workflow (.github/workflows/ci.yml) runs on every push and pull request:
-p b -d (debug + browserExt only) so that the test suite, which targets build/manifestv3/, always has a fresh debug build available.