DOI Resolver compares publication metadata across scholarly sources. Paste one DOI and see what each source reports. It highlights agreement, conflicts, and missing data. Every value keeps provenance (where it came from). It can prepare controlled updates for PURE.
DOI Resolver helps you answer one simple question: “What do different scholarly systems say about this publication?”
You paste a DOI, and the app:
- checks multiple trusted scholarly sources,
- shows where information agrees and where it differs,
- shows where each piece of data came from,
- helps prepare safe updates for PURE.
In short: it is a metadata comparison and quality-control tool for research outputs.
- Research support staff
- University libraries
- CRIS/PURE administrators
- Researchers who want to verify publication metadata across systems
It is built for transparency:
- you can see what was found,
- where it came from,
- where sources disagree,
- and what can safely be pushed to PURE.
- Input one DOI.
- Query selected scholarly sources concurrently.
- Return normalized publication, persons, organizations, identifiers, provenance, and comparison results.
- Merge person and organization candidates from multiple sources.
- Keep provenance and source-level evidence.
- Show references/citations in a dedicated tab.
- Keep citation sources separate from metadata comparison.
- Collect full-text candidates (PDF/landing/etc.) with access status and provenance.
- Rank candidates without pretending all are open.
- Generate candidate updates.
- Apply selected metadata/person/org/publication-identifier updates.
- Attach PDF to PURE through a separate controlled action.
Sources are grouped by capability:
comparison: Crossref, OpenAlex, Unpaywall, DataCite, Europe PMC, PUREenrichment: ORCID, RORcitation: Semantic Scholar, OpenCitationsfulltext: Unpaywall, Europe PMC, CORE, Crossref links
This keeps the UI readable and avoids overloading the comparison table.
- Backend: FastAPI, Pydantic, httpx
- Frontend: React, TypeScript, Vite
- Tests: pytest (backend), typed frontend build checks
GET /healthGET /sourcesPOST /resolvePOST /pure/enrichment/dry-runPOST /pure/enrichment/updatePOST /pure/enrichment/attach-pdf
app/connectors/: one connector per source (fetch + parse only).app/sources/registry.py: centralized typed source registry.app/services/resolver.py: selected-source orchestration and partial-failure handling.app/services/merge.py: merge/comparison logic for publication/entities.app/services/pure_enrichment.py: PURE dry-run/update/attach workflows.app/models/domain.py: typed internal domain models.
src/services/api.ts: API client layer.src/features/doi-resolver/: resolver logic + mapping helpers.src/components/: presentation and interaction components.- Source configuration is centralized and typed; UI is generated from config.
- Preserve all source values in
source_results. - Classify field comparison states (
exact_match,close_match,conflict,missing). - Choose merged values using explainable rules (majority + source priority fallback).
- Never discard provenance; every normalized value can carry source evidence.
- Publication fields:
title,journal,abstract,volume,issue,pages,open_access_status,license,keywords,subjects,language,published_year,published_date - Publication identifiers (filtered to publication-level types)
- Linking matched persons and organizations to the research output
Attach PDF to PURE:- tries eligible PDF candidates,
- skips blocked/challenge pages,
- uploads through PURE file upload API,
- links file as
FileElectronicVersion.
Copy the component-specific templates:
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.envDo not commit .env files.
Important variables:
UNPAYWALL_EMAIL(required for Unpaywall)PURE_BASE_URL,PURE_APIKEY(required for PURE features)SEMANTIC_SCHOLAR_API_KEY(optional but useful)CORE_API_KEY(optional, enables CORE)VITE_API_BASE_URL(frontend -> backend URL)
cd backend
../.venv/bin/pip install -e .[dev]
../.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 8011cd frontend
npm install
npm run dev -- --host 127.0.0.1 --port 4173Open: http://127.0.0.1:4173
./scripts/dev-up.shDefaults:
- backend:
127.0.0.1:8011 - frontend:
127.0.0.1:4173
Override ports if needed:
BACKEND_PORT=8013 FRONTEND_PORT=4175 ./scripts/dev-up.shRun backend tests:
cd backend
../.venv/bin/python -m pytestDetailed pytest scheme (layers, markers, skip policy, quality gates):
Optional live DOI tests:
cd backend
RUN_LIVE_DOI_TESTS=1 ../.venv/bin/python -m pytest -m live_doiRun frontend build/type checks:
cd frontend
npm run buildRun frontend tests:
cd frontend
npm test- Add connector in
backend/app/connectors/. - Declare source metadata/category in
backend/app/sources/registry.py. - Return normalized
SourceResultfrom connector parser. - Add env config if needed.
- Add tests for parser + resolver behavior.
- Update frontend source descriptions (single centralized config).
- External source rate limits and anti-bot pages can reduce coverage.
- Some fields are source-type/PURE-type dependent and cannot always be persisted.
- Citation graph data is presented in the app but not written as native PURE citation graph fields.
- Verify no secrets are committed (
.envfiles, API keys, tokens). - Confirm
.envsetup works frombackend/.env.exampleandfrontend/.env.example. - Run backend tests:
cd backend && ../.venv/bin/python -m pytest - Run frontend tests/build:
cd frontend && npm test && npm run build - Test key manual flows:
- resolve DOI
- compare sources
- PURE dry-run/update
- Attach PDF to PURE (safe and risky mode)
- Confirm README startup steps work on a clean machine.
This project is licensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only).
See LICENSE.



