Wordsmith Retreat
A personal book shelf that merges the read-only Open Library catalogue with your own Supabase-backed books and bookmarks into one list.

Problem
Personal book collections are easy to lose track of — what you own, what you’ve read, what’s worth re-reading. I wanted a proper catalog, not another spreadsheet.
Approach
The app reads from two sources at once and merges them onto a single shelf: Open Library supplies weekly trending books and title search across the public catalogue but is read-only, while Supabase holds the books you create and the books you bookmark. Your own books are listed first, then catalogue results. If one source is down the shelf still renders the other and says so.
Architecture
- Client: React 19 + Vite. Each route-level page owns its own fetching and page state; components below are driven entirely by props
- Data layer: a
utils/layer that talks to Supabase and Open Library and normalizes both into one book shape, so nothing downstream has to know which source a book came from - Database: Supabase Postgres with two tables —
booksfor what you create,favoritesfor the bookmark shelf — and row level security policies, without which every insert fails and the UI silently does nothing - Styling: design tokens in
styles/tokens.css; no hard-coded colours, spacing or type anywhere else
Key decisions
favoritesis a separate table that snapshots the book rather than a flag onbooks, so the bookmarks page renders in one query instead of one Open Library request per bookmark. ACHECKconstraint enforces that each row points at exactly one source — an Open Library work key or a local book- Open Library rate-limits browser clients to roughly one request per second
(the higher tier needs a custom
User-Agent, which browsers don’t allow), so searches are debounced and superseded requests are aborted - Book records are fetched rather than typed in, so adding a catalogue book is a search, not a form
Results
A working shelf with full CRUD over your own books, bookmarking across both sources, a details modal that fetches the full synopsis on demand, inline validation and duplicate detection when adding a book, light and dark themes, and distinct loading, empty, error and partial-outage states throughout.
What I’d do differently
The app has no login: its publishable key ships in the browser bundle
and the row level security policies grant that key full access, which is
fine for a demo and wrong for real user data — adding Supabase Auth and
scoping the policies to auth.uid() is the fix. I’d also reconcile the
bookmark snapshots, since editing one of your own books currently leaves an
existing bookmark showing the old record, and add a test suite: right now
npm run lint && npm run build is the whole definition of “not broken”.