A continuously updated MPRA database built with Nuxt 4, Vue 3, and Tailwind CSS 4. Browse and search studies, inspect processed experiment tables, download retained raw inputs individually or as a ZIP, and access the public read-only API. Canonical site: https://mpra.johnomeara.com.
For most research uses, start with the public API documentation. You can retrieve study/experiment metadata, processed CSVs, and retained raw files without running the discovery and packaging pipeline or scraping the website's HTML:
curl 'https://mpra.johnomeara.com/api/v1/studies?page=1&limit=100'Follow the response's pagination.has_more and increment page to enumerate studies. Use the documented per-study endpoints for raw files/ZIPs and per-experiment endpoints for complete processed tables. Limit concurrency and back off on 429 responses. The live collection can change between pages; retain study identifiers and deduplicate results. Source licenses still apply. The public API deliberately excludes internal full text and pipeline state, so it is not a complete backup or a seed for reproducing the private pipeline.
To generate and host your own database, use these companion repositories:
| Repository | Role |
|---|---|
| openmpra-scraper | Discovers candidate papers, classifies them, runs isolated AI-assisted study packaging, verifies packages, and uploads them. Requires model access and incurs inference costs. |
| openmpra-http | Hosts a private filesystem copy, accepting authenticated study uploads and serving files to this app. Keep it off the public internet: it includes internal full text. |
| OpenMPRA (this repository) | Public Nuxt website and read-only API, with a periodically refreshed index of the private HTTP source. |
Set up the private HTTP host, configure and run the scraper against it, then point this app's NUXT_DATABASE_URL at that host. The companion READMEs cover prerequisites, credentials, paths, and scheduling. No repository includes the production database, private run history, or credentials. Fresh generation may process a large backlog and is not guaranteed to reproduce the hosted collection exactly.
Requires Node.js 22.12+ (24 recommended) and network access from the app server to the database described in DATABASE.md. The database and research data are not included in this repository.
git clone https://github.com/jsomeara/OpenMPRA.git
cd OpenMPRA
cp .env.example .env
npm ci
npm run devOpen http://localhost:3000. The server builds the initial index automatically. Until that first scan completes, the catalog returns a retryable 503. Optionally run npm run sync before starting. Copy .env.example to .env if you need different settings; Nuxt reads it in development. The sync CLI reads exported environment variables, or run node --env-file=.env scripts/sync-catalog.mjs.
The server re-indexes on startup and every 15 minutes. Set NUXT_CATALOG_REFRESH_SECONDS to adjust the interval (minimum 60 seconds). A refresh discovers additions, re-reads metadata and raw-file listings, and drops removed or unfinalized studies after a successful full scan. Files and tables are streamed live, so their bytes are not cached in the index.
Refreshes use six discovery workers, cannot overlap within one server process, and atomically replace data/catalog.json. A failed or empty scan retains the previous catalog and logs a diagnostic. Index refresh timestamps are not source-data update timestamps and are not presented as such. Existing visitors can reload to retrieve a new snapshot (the internal UI catalog HTTP cache lasts at most 60 seconds). Keep finalized absent while editing a study and restore it only after all its files are ready. The HTTP database does not offer a global transaction or revision token; a scan cannot guarantee a point-in-time snapshot if files change during traversal.
Run one app process per catalog path. For multiple replicas, give each an independent catalog volume/path to avoid concurrent writers. Do not run the manual sync CLI concurrently with the app against the same path.
npm run build
NUXT_DATABASE_URL=http://192.168.4.101:22289/ \
NUXT_CATALOG_PATH=/var/lib/openmpra/catalog.json \
NUXT_CATALOG_REFRESH_SECONDS=900 \
HOST=127.0.0.1 PORT=3000 node .output/server/index.mjsThe runtime user must have write access to the catalog directory. Mount persistent storage there to retain the last good catalog across restarts. The standalone .output/ contains the server and its runtime dependencies. Production does not automatically load .env; configure environment variables through your service/container manager.
Deploy this Node server on a host that can reach the private database, and place HTTPS/reverse-proxy access in front of it. Only the app port needs to be public. A public static host or a cloud worker with no route to the LAN cannot provide the required downloads. No database URL or upstream redirect is sent to the client by the file API. Source-publication links are independent external resources.
Reverse proxies should allow streaming responses and adequate download timeouts. Table scans have a 60-second limit; source requests and raw ZIP downloads have a 10-minute limit. Four table readers, eight individual downloads, and two raw ZIP downloads may run concurrently per process; additional requests receive 429. Apply deployment-level request/bandwidth limits for public traffic. Very large or late-page scans re-read the CSV; for substantially larger traffic, add an analytical table index or job queue rather than increasing memory limits. Downloads do not currently support byte-range resume.
- Shareable text searches and assay, organism, genome, design, biosample, and year facets; sort and paginate studies.
- Study abstracts, full author citations, external resources, raw-file search and downloads, and all-raw-files ZIPs. Study full text remains internal.
- Experiment metadata, QC notes, processed CSV downloads, hover/focus column tooltips, full column dictionary, column visibility, and full-cell inspection.
- Streaming table pagination and text/exact/numeric filtering; public API for programmatic access.
- Database citation dialog with plain text, BibTeX, RIS, and CSL-JSON formats and an editable access date. Citation metadata is maintained in
shared/citations.ts; no paper, DOI, or publication date is implied. - No invented harmonization: original experiment schemas and missing metadata are retained.
Processed CSV downloads and raw ZIP entries preserve exact source bytes, without spreadsheet escaping or harmonization. Source licenses apply; the app does not assign a blanket data license. Processed tables vary in schema, units, and measurements; consult each experiment's column definitions and QC notes.
The API is served at /api/v1/. Human-readable documentation is at /api-docs, and an OpenAPI 3.1 document at /api/v1/openapi.json. It supports study/experiment search and pagination, full metadata, 50-row table pages with filters, complete processed CSVs, raw-file listings, individual raw downloads, and per-study raw ZIPs. No API key is needed. Cross-origin GET/HEAD/OPTIONS requests are supported; no public mutation endpoints exist. /api/catalog is internal to the UI and not part of the stable API contract.
Nuxt SSR remains enabled. Study and experiment content, title/description, and social tags are rendered in the initial HTML. Canonical URLs use https://mpra.johnomeara.com; query variants use noindex/follow. /robots.txt allows page crawling and advertises /sitemap.xml, which is generated from the current catalog and includes all study/experiment pages. API responses are noindex. No source modification dates are invented. Configure the production reverse proxy to serve the app over HTTPS at the canonical hostname without crawler-blocking authentication; this code cannot guarantee Google indexing. The implementation follows Nuxt's SEO guidance.
Nebula Sans WOFF2 files are self-hosted under public/fonts/ with the supplied OFL license. Favicons and the web manifest are under public/. Every text style, including code and tables, uses Nebula Sans.
npm test
npm run typecheck
npm run buildTests exercise CSV parsing, scientific filters, and index refresh behavior against an isolated local HTTP fixture. The live database is never modified.
TEST_BASE_URL=http://localhost:3001 npm run test:smoke runs HTTP checks against a running app and the real source database, including Googlebot SSR, canonical/meta tags, sitemap, assets, API filters/pagination, removed routes, raw-file checksums, and raw ZIP integrity. It requires unzip, the example study from DATABASE.md, and the small raw-data fixture study S7OGDAMGE already in the database.
The Tailwind integration follows the official Nuxt guide. See AGENTS.md for architecture and contributor guidance.
See ops/README.md for a localhost-only Linux deployment using user-level systemd services. It includes a private Node runtime, boot startup, crash recovery, and polling of GitHub's main branch. New releases are built and checked separately before activation; a failed activation restores the previous release. Database indexing and application deployments are independent background processes.
Bug reports and pull requests are welcome at GitHub. Include reproduction steps and relevant study or experiment identifiers; do not include credentials, private source URLs, or unpublished data. For substantial changes, open an issue first to discuss scope.
Read AGENTS.md for the architecture and scientific-data constraints. Run the validation commands above and python3 -m unittest discover -s ops/tests before submitting a pull request. Keep API documentation and tests consistent with behavior. CI runs these checks without accessing the live database.
Application code is licensed under the MIT License, copyright 2026 John S. O'Meara. Nebula Sans is distributed under its included SIL Open Font License. The software license does not apply to studies, publications, or downloaded research data; consult their respective source licenses.