Bookshelf

Barcode to catalog in under 10 seconds. A metadata aggregation platform for independent bookshops — scan, enrich from five sources, publish to WooCommerce.

Solo developer · Libreria Rotondi, Rome · 2025-present · live
Python FastAPI SQLite Vanilla JS Jinja2 pyzbar Docker Render
Bookshelf

The Problem

Independent bookshops run on WooCommerce but their catalogs are a disaster. Every new book means five minutes of manual data entry — publisher, year, page count, subjects, description, cover image — copy-pasted from wherever Google leads.

Libreria Rotondi in Rome has 18,000 published products with significant data gaps. 2,545 items filed under "Senza categoria." A category tree 280 nodes deep with no consistency. Adding a shelf of fifty new books is a full day gone.

5 Sources merged per scan
<10s Barcode to catalog
18K+ Products managed
0 Manual data entry

Scan, Enrich, Publish

Point your phone at the barcode. Five sources are queried simultaneously — OPAC SBN (Italian national catalog), IBS.it, OpenLibrary, Maremagnum, and ViaLibri. Each returns different data. The system merges them intelligently: OPAC SBN for authoritative bibliographic records, IBS for Italian descriptions and cover images, OpenLibrary for English-language metadata. Authors are deduplicated across name variants ("Evola, Julius" and "Julius Evola" become one entry).

One click pushes the enriched record to WooCommerce with field-level diff detection. Only changed fields are sent.

Scan, Enrich, Publish

Works in the Shop

A mobile barcode scanner that works on an iPhone in a dimly lit bookshop is harder than it sounds. The solution: auto-zoom at 3.7×, capture-and-crop to the barcode area, server-side multi-pass decoding via pyzbar with grayscale, sharpen, and contrast enhancement. If the camera can see it, pyzbar reads it.

For counter setups, a standard laser scanner gun works natively — it emulates a keyboard, types the ISBN, hits Enter. Scan, beep, next book.

Works in the Shop

Source Merging

lookup.py
# Five sources return different data for the same ISBN.
# Smart merge picks the best value per field, deduplicates
# authors across name variants, respects source priority.

record = merge_sources([opac, ibs, openlibrary, maremagnum, vialibre])

# "Evola, Julius" + "Julius Evola" → one author
# IBS description preferred (Italian store)
# OPAC SBN publisher name = authoritative
# Cover: IBS first, OpenLibrary fallback

Multi-Store, Profile-Driven

Every bookshop organizes differently. Rotondi uses a custom autore taxonomy with 11,000+ entries and a dozen libro_* meta keys. Another shop might use WooCommerce attributes, tags, or completely different field names.

Nothing is hardcoded. A JSON profile defines how each field maps to the store — native field, meta key, taxonomy term, or skip. Adding a new store means writing one JSON file. The metadata aggregation layer is designed to serve any application that needs bibliographic intelligence.

Multi-Store, Profile-Driven

Built With a Real Shop

Every feature was tested on real hardware with real data — iPhone 14 in the shop, laser scanner at the counter, 18,000 products with real data gaps. Libreria Rotondi is an esoteric bookshop with one of the largest collections of occult, hermetic, and Eastern philosophy titles in Italy. If it works here, it works anywhere.

Bookshelf is in pilot with independent bookshops on board. If you run an online store and spend too much time on catalog data entry — get in touch.