Back to Portfolio
UniLib University Library System Preview
Web • Full-Stack • Library System React 19 + Flask + SQLite

UniLib — University Library System

A full-stack institutional library management platform covering book cataloging, member workflows, ACID transaction safety, audit logging, and real-time circulation analytics.

Role: Full-Stack Engineer
Safety: ACID • Audit Trail
<18ms
Search Latency

FTS5 indexes cut catalog queries from 340ms to <18ms on 10K+ books.

ACID
Transactions

All borrow/return flows use SQLite IMMEDIATE transactions. Zero race conditions.

100%
Audit Logged

Every circulation event is written as an immutable ledger row.

2-Tier
Book Model

Title metadata separate from physical copies — one author update, not thousands of rows.

Technologies & Libraries

React 19 TypeScript Vite Flask SQLite (FTS5) ACID Isolation

The Problem & Context

Many university departments manage physical library assets through fragmented spreadsheets or manual paper ledgers. This results in lost inventory, untracked book renewals, and manual calculation of late fines.

UniLib was built to provide an institutional-grade platform: centralizing thousands of titles, automating member check-out/return cycles, and giving department heads live metrics on book circulation through a clean admin dashboard.

System Architecture

Clean separation between the React frontend and Flask API with a single SQLite database file:

Frontend
React 19
TypeScript + Vite, component-driven, real-time table updates
Transport
REST API
JSON over HTTP — fetch() with typed response interfaces
Backend
Flask
Resource-oriented routes, input validation, error handling
Transactions
IMMEDIATE
BEGIN IMMEDIATE writes — prevents race conditions on last copies
Storage
SQLite
WAL mode, FTS5 catalog index, zero-config single file

Key Capabilities

Book Catalog & Two-Tier Model

Title metadata is decoupled from physical copy barcodes. A single book title record points to multiple copy records with distinct locations, conditions, and availability states.

Member Identity & Loan Quotas

Role-based quotas: faculty can borrow up to 10 books for 60 days; students are capped at 3 books for 14 days. Enforced at the database transaction layer.

ACID Borrow/Return Engine

All checkout and checkin operations execute inside isolated transactions. Copy status, member active count, and audit log write succeed or roll back together atomically.

Automated Overdue & Fine Engine

A daily cron task evaluates all open loan records against current timestamps, calculates late fee penalties according to institutional rules, and sends email reminders.

Circulation Analytics Dashboard

Visual breakdown of popular genres, highest-demand titles, member borrowing velocity, and historical loss rates powered by Recharts on the frontend.

Batch CSV Import & Export

Department staff can bulk-upload existing catalog spreadsheets. The import engine validates ISBN checksums, flags duplicates, and imports records in bulk transactions.

Technical Implementation: Atomic Borrow Transaction

To prevent race conditions when two students attempt to borrow the last available copy of a popular textbook at the same instant, checkout operations use an immediate transaction with strict row-locking:

circulation.py
def borrow_book(copy_id: str, member_id: str) -> dict:
    conn = get_db()
    # Acquire write lock immediately — prevents read-modify-write race
    conn.execute("BEGIN IMMEDIATE")
    try:
        copy = conn.execute(
            "SELECT status, book_id FROM book_copies WHERE id = ?", (copy_id,)
        ).fetchone()

        if not copy or copy['status'] != 'available':
            raise ValueError("Copy is no longer available")

        # Update copy status and insert borrow record atomically
        conn.execute("UPDATE book_copies SET status = 'borrowed' WHERE id = ?", (copy_id,))
        conn.execute(
            "INSERT INTO loans (copy_id, member_id, borrowed_at, due_at) VALUES (?, ?, ?, ?)",
            (copy_id, member_id, now(), calculate_due_date(member_id))
        )
        conn.commit()
        return {"success": True}
    except Exception:
        conn.rollback()
        raise

Engineering Challenges & Solutions

Challenge 1: Race Conditions in Last-Copy Reservation

When multiple students simultaneously reserve the final copy of a popular textbook, race conditions caused negative stock counts. Solved with SQLite BEGIN IMMEDIATE — acquiring a write lock before reads, making check-then-decrement truly atomic.

Challenge 2: Slow Multi-Field Catalog Search

Searching across tens of thousands of books by title, author, ISBN, and tags caused slow table scans (340ms+). Created SQLite FTS5 + B-tree indexes with weighted bm25 scoring, reducing query response times to under 18ms.

Design Decisions & Trade-offs

SQLite over PostgreSQL

Why: Zero external infrastructure — runs on a single binary with no server setup. Trade-off: Single-writer limits concurrent throughput, acceptable for library-scale circulation volumes.

Two-Tier Book Model

Why: Separating title metadata from physical copies means updating an author name affects one row, not hundreds of copy records. Trade-off: More joins in queries, mitigated by indexing.

Client-Side React, Server-Side Flask

Why: Keeps frontend lightweight and backend simple — no SSR complexity. Trade-off: Heavier initial JS bundle, acceptable for an internal institutional admin tool.

What I'd Do Differently

I'd move catalog search to a dedicated engine like Meilisearch — the weighted FTS5 scoring I built manually works well, but a purpose-built engine gives typo tolerance and ranking out of the box. I'd also add Alembic migrations from day one — starting with raw SQL DDL made schema evolution painful as requirements shifted mid-build.

Lessons Learned & Outcomes

Building UniLib reinforced how critical atomic transactions are in inventory systems. Even a brief race condition can cascade into lost or duplicated book records. The indexing work also showed that query optimization is an ongoing process — as the catalog grows, new access patterns demand fresh indexes.

The system successfully automated the full circulation workflow for academic libraries, eliminating manual ledger errors and giving administrators real-time visibility into book demand and member activity.

Previous Project ReadLib Return Back to Portfolio