React component for annotating IIIF images. Supports drawing shapes over images and highlighting OCR text, both backed by a W3C Web Annotation server.
- Node 18+
- The readux Django app (for local integration)
The annotator is consumed by readux directly from source — readux's Vite build resolves ecds-annotator to ../ecds-annotator/src/index.jsx via an alias, so no build step is needed here.
First-time setup
# In this repo — build generates dist/style.css, which readux's postinstall copies
npm install
npm run build
# In readux
cd ../readux
npm install # postinstall copies dist/style.css → apps/static/css/ecds-annotator.min.cssdist/ is git-ignored. Re-run npm run build here any time you change CSS; JS changes are picked up from source automatically.
HTTPS certificate (one-time)
readux requires HTTPS. Use mkcert to create a locally-trusted certificate — this avoids browser warnings without any per-request confirmation.
# Install mkcert (macOS)
brew install mkcert
mkcert -install # installs the local CA into the system trust store
# Generate certs in the readux directory
cd ../readux
mkcert localhost # creates localhost.pem and localhost-key.pemThe cert files are already present in the readux repo if a teammate generated them — mkcert -install is still required on each new machine to trust the CA.
Running the dev server
Start readux's watch build, then the Django HTTPS server:
# Terminal 1 — rebuilds main.js on every source change
cd ../readux
npm run dev
# Terminal 2 — Django dev server over HTTPS (via django-extensions)
cd ../readux
python manage.py runserver_plus --cert-file localhost.pem --key-file localhost-key.pemOpen https://localhost:8000. Changes to any file under src/ are picked up automatically by the --watch build — reload the browser after it finishes.
Standalone Vite dev server (optional — useful for isolated UI work without Django)
npm run dev
# opens http://localhost:3000Edit index.html at the repo root to point at a real IIIF manifest URL.
Production builds are handled automatically by readux's GitHub Actions workflow (.github/workflows/depoly.yml). No manual build step is required here — push to main or develop in readux and the pipeline takes care of everything.
How it works
- The GH Actions workflow checks out both readux and this repo (into
ecds-annotator/inside the readux workspace) before building the Docker image. - The Docker
js-builderstage copies the ecds-annotator source to/home/ecds-annotator/, which is where readux'svite.config.jsalias andpackage.jsonfile:dependency both resolve to fromWORKDIR /home/readux. npm run buildinside the container compiles everything — ecds-annotator source included — intoapps/static/js/main.js.- The production stage copies the built JS from
js-builderand runscollectstaticat startup viaentrypoint.sh.
If you need to verify the production build locally
# From the readux repo root — requires ecds-annotator checked out as a sibling
cd ../readux
docker build --target js-builder -t readux-js-test .This only runs the JS build stage and lets you inspect apps/static/js/main.js without standing up the full container.
- Vite lib mode —
vite buildhere outputs ES and UMD bundles todist/. Only the CSS is used by readux in production; the JS bundles exist if the component is ever consumed standalone. - Source alias in readux —
readux/vite.config.jsaliasesecds-annotator→../ecds-annotator/src/index.jsx. This lets Rollup tree-shake and compile everything together, avoiding CJS interop issues from double-bundling a pre-built package. - IIFE output — readux's Vite outputs
main.jsas an IIFE so Django can load it with a plain<script>tag (notype="module"required). - react-draggable stub —
react-draggableis aliased to a no-op passthrough in readux's Vite config. The upstream package callsReactDOM.findDOMNode, which is absent from the React 18 production bundle. The editor popup is fixed-position rather than draggable as a result.