Hi, I'm Rahkel. I'm a backend developer, and I'm building a software project solo, in public.
This series is the log of that build — twice a week, what I shipped, the design decisions behind it, what broke, and what's next. No highlight reel. If a test fails on a Saturday and I have to leave for work before I can fix it, that goes in the log too. (That has already happened. More than once.)
The idea
I'm turning my old Library Management System into a peer-to-peer library platform.
Instead of one library owning every book, individuals catalog their own personal collections. Other members can discover those books and borrow the copies the owners choose to make public. Owners will also be able to give books away to interested members, or donate them to an actual library. And libraries and organizations can run the same lending functionality for their own patrons.
That's the destination. This series is about the unglamorous part: rebuilding the foundation so that destination is actually possible.
Where it started
Honestly? I cringe a little looking at the original code — and I've learned to take that as a good sign. It means my standards moved.
🔴 Before:
A console app built around one massive Library class
Borrowing, duplicates, genres, and limits all handled in the same place
Books tracked in in-memory lists and maps — close the app, lose the state
No separation between a book title and the physical copies of it
It worked as a learning project. It could never work as a platform where real people lend each other real books.
Where it is now
🟢 Now:
Rebuilt on Java 21 + Spring Boot, and the app actually boots and runs
A layered architecture: dedicated services (BookService, BorrowService, LibraryMemberService), Spring Data JPA repositories, DTOs for requests, and @Transactional workflows
Books modeled as titles with multiple physical copies, each tracked on its own
Tests at every step — 47 and counting
The part I just finished: ownership and visibility
Here's something I didn't appreciate until I started building it: a peer-to-peer library is impossible until the code knows who owns what.
When I started this phase, my book copies belonged to nobody and were effectively visible to everybody — exactly backwards for a platform where people lend out their own collections. So the most recent chapter of the build (Step 2, just completed) was:
A new LibraryMember entity — the platform member who owns book copies, with a MemberType of INDIVIDUAL or ORGANIZATION, because a person and a library won't use this the same way
A member-creation path with proper validation and a case-insensitive email lookup
CopyVisibility on every copy:
public enum CopyVisibility {
PRIVATE,
PUBLIC
}
PRIVATE is the default — owner only, cannot be borrowed. PUBLIC means other members can discover the copy and borrow it. Privacy first, sharing by choice.
A discovery query that only ever surfaces available PUBLIC copies — private copies don't just fail to borrow, they don't show up at all
One design decision I made on purpose, and would defend: the owner is not the existing Borrower entity. A member owns and lends copies. A borrower is an external patron of a library — a different job. Collapsing those two into one entity would have been faster for a week and messier forever.
What happens in this series
Every post follows the same simple shape:
Shipped: what actually landed in the code, with the PR to prove it
Decided: one design call, and why I made it
Next: what I'm building next
I'm doing this for three reasons: to hold my own standards up where people can see them, to find a community of developers building similar things, and because I'm open to collaborations — feedback on the design is genuinely welcome, especially when you think I got a call wrong.
What's next
Ownership and visibility were groundwork. The platform layer they were groundwork for — exposing this as a real API with real persistence, so members can actually use it — is the next chapter, and I'm deciding the exact order of that work right now.
So I'll end with the question I'm actually sitting with:
If you were building this, would you put the REST controllers on top of the current service layer first, or lock down the persistence/database layer first — and why?
Follow the series if you want to watch a legacy monolith become a platform, one decision at a time.
Code, if you want to follow along or tell me what you'd do differently: github.com/Pekins1/LibraryManagementSystem
Top comments (0)