BLD-002·Building
Building a MARC Cataloger From Scratch
BTCat is gone. The alternatives cost too much or do too little. So I'm building one. Open source, modern stack, designed for how catalogers actually work.
There's a gap in cataloging tools. Not a gap where nobody noticed (catalogers talk about this constantly), but a gap where nobody's built the thing yet. So I'm building it.
A few months ago I went looking for a standalone MARC editor that met a pretty basic bar: modern UI, decent keyboard shortcuts, the ability to validate records without round-tripping through an ILS. The kind of tool that should exist in 2026.
Here's what I found: BTCat is gone. MarcEdit is a one-person project that Terry Reese has maintained heroically for decades, and it's a desktop app built on assumptions from a different era. OCLC Connexion does what it does well within its ecosystem, with the pricing and integration that come with that. The ILS-native editors vary in fit depending on your vendor and workflow.
What this is
The working name is MarcForge. It's a standalone cataloging tool, not an ILS or a discovery layer. It does one job: help catalogers create, edit, validate, and export MARC records efficiently.
The stack:
- Frontend: Next.js + React with a purpose-built MARC editor component
- Backend: Python/FastAPI
- Storage: PostgreSQL + OpenSearch
- Cache/queue: Redis
- Dual format storage: raw MARC21 binary alongside normalized MARCJSON
That last point matters. MARC21 is the exchange format. It's what your ILS imports, what OCLC expects, what Z39.50 serves. But it's a hard format to query, diff, or build UI around. MARCJSON gives you a clean JSON representation for the application layer while keeping the canonical binary for interoperability. You always have the real record. You also have a version you can actually work with.
Why standalone
This was the first real decision. Why not build cataloging directly into l/30?
l/30 has a cataloging module. It works. But a lot of catalogers don't work inside a single ILS. They work across systems: contributing to OCLC, pulling records from Z39.50 sources, editing batches for a consortium, cleaning up a migration file. The tool they need isn't married to one system's data model. It's a workbench that connects to whatever they need it to connect to.
BTCat understood this. It was standalone, it was fast, and catalogers loved it. When Baker & Taylor wound down its operations and BTCat went with it, the loss wasn't only the software. It was a philosophy about cataloging tools being their own thing rather than a feature inside something else.
MarcForge is designed to work with l/30, with Koha, with Evergreen, with anything that speaks Z39.50 or SRU. A tool, not a module.
The editor
The editor is the heart of the project. A MARC editor that catalogers will actually use needs to feel like an instrument, not a form.
When you type a tag number, you get the field definition, valid indicators, and common subfield patterns inline. Not a lookup table you have to memorize or a PDF in another window. Think VS Code's autocomplete, but for MARC. Guidance stays out of your way when you know what you're doing and shows up when you don't.
Side-by-side diff and merge handles the case where you pulled a record from OCLC, you have a local version, and they don't match. Today that means eyeballing two records and manually copying fields. MarcForge shows you exactly what changed, field by field, and lets you merge selectively. This is the workflow that eats hours in batch cataloging and the place where a focused UI can save the most time.
Macro automation covers the repetitive edits catalogers do constantly: stripping fields for a specific load profile, normalizing punctuation across a batch, adding local fields based on location codes. The plan is sandboxed Python macros with access to the record structure but restricted globals so they can't reach outside the record.
Validation runs continuously, not as a batch step after the fact. And it understands context: it's not just "is this field repeatable," it's "does this 245 have the right punctuation for ISBD" and "does this 1XX match an authority record" and "is this call number consistent with the classification scheme in the 050."
Authority linking
This is one of the pieces I'm most interested in getting right. When a cataloger types a name in a 100 field, MarcForge queries id.loc.gov in real-time and offers matching authority records. Accept a match and the heading is linked. Not just text-matched, but URI-linked to the Library of Congress authority file.
This is where MarcForge connects to the BIBFRAME conversation. MARC records with authority URIs are MARC records that are ready for linked data. You're not doing BIBFRAME yet, but you're building records that will translate cleanly when the time comes. Every linked heading is one less thing to reconcile during a future migration.
The authority linking also works for subjects (LCSH, LCGFT), classification numbers, and geographic names. Anywhere the Library of Congress maintains an authority file, MarcForge can connect to it. The lookup is fast because results are cached in Redis with a sensible TTL. You're not hammering id.loc.gov on every keystroke.
Multi-tenant and audit trail
MarcForge supports multiple users and organizations from the start. Role-based access control, because not everyone in a cataloging department has the same permissions and not every consortium member should see every other member's records.
Every change to every record is tracked. Full audit history: who changed what, when, and what the record looked like before. This is good practice, and it's something catalogers have asked for. When you're trying to figure out why 200 records lost their 856 fields last Tuesday, "check the audit log" should be a real answer.
ILS integration
MarcForge connects to the systems catalogers already use:
- Z39.50/SRU for searching and retrieving records from any compliant source (OCLC, LC, other libraries, your own ILS)
- Koha via its REST API for direct record push/pull
- Evergreen via its APIs
The integration is read-write where the target system supports it. Search a Z39.50 source, pull a record into your workspace, edit it, push it back to your ILS. That's the core loop, and proving that it works cleanly is what Phase 0 is about.
Where this stands
Phase 0. I'm calling it a spike because that's what it is. I'm proving the core loop works before I build out the full feature set.
The core loop: search a source, retrieve a record, display it in the editor, edit it, validate it, export it. Every link in that chain touches a different technical problem. The MARC21 parser has to handle the real-world records that exist, not the spec-perfect records that don't. The editor has to render variable-length fields with proper subfield display. The validator has to know the difference between an error and a cataloging choice.
The first concrete target for Phase 0: round-tripping a MARC21 record through the MARCJSON representation and back without any data loss. That sounds simple but it isn't. Real-world MARC records from different ILS exports have inconsistencies the parser has to handle gracefully. Getting that right before building the editor on top of it is the right order.
The first version of the editor will be wrong, and I know that going in. The field ordering will annoy someone. The keyboard shortcuts will conflict with something. The validation will flag things that are fine and miss things that aren't. That's the point of building in public. The feedback loop starts before the architecture calcifies.
The BIBFRAME bridge
I wrote a long piece about the MARC-to-BIBFRAME transition. The short version: the Library of Congress is already cataloging in BIBFRAME, and the rest of the supply chain will follow on its own timeline.
MarcForge is a MARC tool. It's not pretending to be a BIBFRAME editor. But the design decisions, authority linking via URIs, clean JSON representation of records, separation of intellectual content from carrier information, are all decisions that make the eventual bridge easier to build.
When the time comes to add BIBFRAME output, the records created in MarcForge will be better source material than records created in tools that treat headings as flat text and validation as an afterthought. Good MARC is the best preparation for good BIBFRAME, and MarcForge is designed to produce good MARC.
Why open source
Same reasoning as l/30. AGPL-licensed, because cataloging tools shouldn't require a license fee and shouldn't disappear when a company changes direction.
BTCat disappeared because it was a commercial product tied to a commercial company. When the company's business model changed, the tool went with it. Companies make business decisions, and an open-source alternative gives catalogers something that doesn't depend on any one company's roadmap.
An open-source cataloging tool that works well is infrastructure. Building on MarcEdit's legacy, with a bus factor greater than one and a web-native architecture that distributes the maintenance load beyond a single developer's shoulders.
What I'm looking for
I spent years on the vendor side of library technology. I know what catalogers ask for in support tickets, in feature requests, in the workarounds they build when the software doesn't do what they need. That's useful context, but it's not the same as watching someone use the thing I built.
If you're a cataloger and this sounds like something you've wanted, I'd like to hear from you. Not to sell you anything. There's nothing to sell. Just to understand what the core loop needs to feel like before I get too far down the road.
The code will be public when there's something worth reading. Right now it's Phase 0: proving the MARC21/MARCJSON round-trip works cleanly, then building the editor on top of that foundation. The building-in-public part starts here, with the decisions, and continues as the code catches up.
Filed · BLD-002 · 2026.05.10