Academic Reference Management
Browser-native reference management for large academic collections. Full-text search, metadata fetching, JEL classification, LOC subclassing, CSV import, six-panel library analytics, and virtual-scrolled rendering of 10,000+ entries — now with a dedicated @archival entry type, Internet Archive search, and Chicago NB citation export. No build step, no server, no dependencies.
Feature Set
.bib file to import. Export the full library with all custom fields at any point. Handles nested braces, @string macros, and malformed entries without halting.author, title, year, etc. — with a sample value shown for each column. Duplicate keys auto-resolved. Entries stamped csv-import.datasource simultaneously. Results update in under 200 ms. Sidebar filters by type, year range, JEL, LOC, and provenance.BIBFORGE_CONFIG.autoLoad to a repo-relative path and the library fetches automatically on startup. Same-origin, no CORS, no auth. Works out of the box on GitHub Pages.datasource Fieldcrossref, openlibrary, googlebooks, csv-import, archive-visit, or manual. Written to the .bib file. Filterable in sidebar.repository, collection, box, folder, call_number, date_range, access, finding_aid_url, visit_date. Access badges in entry rows (open / digitized / restricted / by-appointment). Date-range-aware year filter and sort.@archival format (item · date range · collection · box/folder · repository). Copy-to-clipboard in one click.Citation Key Convention
BibForge uses the author:year:keyword convention — matching the Better BibTeX plugin pattern. Collision suffixes (smithb, smithc) appended automatically.
Better BibTeX pattern:
[auth:lower]:[year]:[title:lower:clean:truncate=20]
Editing Cycle
data/library.bib via same-origin fetch.bib, commit to repo — every push is a dated snapshotOutbound Requests
All processing is client-side. No library data is ever transmitted. Outbound requests are limited to the following endpoints:
| Endpoint | Triggered when | What is sent |
|---|---|---|
| api.crossref.org | DOI lookup (Tab 1 or Quick-Add) | The DOI only |
| openlibrary.org | ISBN or title lookup (Tab 2 / 3) | ISBN or search query |
| googleapis.com/books | Google Books lookup or fallback | ISBN or search query |
| archive.org/advancedsearch | Archival Search tab — Internet Archive | Search query only |
| aeaweb.org/econlit/…xml | First Fetch JEL click (cached) | Nothing (GET request) |
| gc.zgo.at/count.js | Page load (analytics) | Page URL, referrer (no cookies) |
| fonts.googleapis.com | App startup | Nothing (GET request) |
| same-repo .bib path | Auto-load on startup | Nothing (same-origin GET) |
WorldCat, ArchiveGrid, SNAC, DPLA, and Europeana open in a new browser tab — no data passes through the app. GoatCounter collects no personal data and sets no cookies.
Changelog
@archival, copy-to-clipboard@archival entries@archival entry type with 11 dedicated fields: repository, collection, box, folder, item, call_number, date_range, access, finding_aid_url, visit_date, access_notearchive-visit added as a valid datasource value; auto-set when type is @archivalcsv-import added as a valid datasource valueTechnical Notes
Written from scratch — no external dependencies. Handles nested braces, @string and @preamble blocks, # concatenation, multi-byte characters, and malformed entries without halting the parse.
Fixed row height of 76px. Only visible rows are in the DOM at any time. Switching filters or running a search recalculates the virtual list instantly — rendering cost is proportional to viewport size, not library size.
Keyword-scoring against the full AEA EconLit tree fetched on first use and cached for the session. Specificity bonus for 3-character leaf codes. Falls back to an embedded table of 200+ codes if CORS-blocked.
The @archival type writes standard BibTeX — custom fields like repository and date_range are preserved in round-trips through Zotero and JabRef. Internet Archive fetch uses the public advancedsearch.php endpoint — no API key required.
Rename to bibforge.html, push to GitHub, enable Pages. No _config.yml, no Jekyll, no build pipeline. File size stays under GitHub Pages' 100 MB limit at any realistic library size.