
Overview
A complete bookstore backend built with Bun and Elysia. Customers can search the catalog by title, author, or ISBN, inspect a book, leave a rating, and place an order with home or bureau delivery. Behind the API is a full admin workflow for stock, orders, authors, and acquisition requests, plus a typed OpenAPI reference documented at /docs.
The API is intentionally small and typed end to end. Elysia route schemas validate query strings, params, and request bodies before a handler runs, while Mongoose models keep the library domain explicit. The server ships as a single Bun process with an OpenAPI reference at /docs.
Bun keeps the API, seed script, and Docker image small, and Elysia's schema-first routes gave me validation and the OpenAPI reference from one definition. MongoDB and Mongoose fit the document-shaped catalog and order data without needing a migration for every content change.
Catalog & discovery
The catalog endpoint resolves author matches first, then searches books by title, ISBN, or author reference. Results are paginated with total pages, next/previous flags, and author documents populated. A single book can be fetched by Mongo ID or ISBN, which keeps the storefront and admin views on the same route.
- Search by title, ISBN, or author name
- Pagination metadata for storefront and admin tables
- Book details with populated authors, stock, and ratings
- Author search with prefix matching
Orders & stock control
Placing an order validates every line against live stock before creating the customer and order. To avoid accidental duplicates, the same phone number cannot open a second pending order with an identical set of books. When an order moves through pending, sold, delivered, or canceled, inventory and reporting stay in sync.
export const orderRoutes = new Elysia({ prefix: "/orders" }) .post( "/", async ({ body, status }) => { for (const item of body.items) { const book = await Book.findById(item.bookId); if (!book) { return status(404, `Book ${item.bookId} not found`); } if (book.quantity < item.quantity) { return status( 409, `Not enough stock for "${book.title}", only ${book.quantity} left`, ); } } return createOrder(body); }, { body: t.Object({ phone: t.String(), items: t.Array( t.Object({ bookId: t.String(), quantity: t.Integer({ minimum: 1 }), }), ), }), }, );Acquisition requests
Customers can suggest a title that is missing from the catalog. The request records title, author, and notes, and warns when a matching title already has stock. Admins filter requests by status and mark them acquired or rejected, keeping the suggestion queue short and actionable.
Auth, uploads & tooling
The users plugin issues JWT cookies at register and login, keeps the token httpOnly, and exposes a /me endpoint for the current session, with passwords hashed using bcrypt. Cover images use a signed Cloudinary upload flow, and uploaded files are served through Elysia's static plugin. The project includes a seed script with authors, books, customers, orders, requests, and comments for local development.
- JWT cookie auth with /register, /login, and /me
- Signed uploads and static file serving
- OpenAPI reference at /docs
- Docker image based on oven/bun:alpine on port 8000
Screenshots








What it includes
- Paginated catalog search across title, author, and ISBN
- Stock validation and duplicate pending-order protection
- Order status transitions that adjust inventory
- Book acquisition requests with acquire/reject review
- Comments, ratings, and aggregated review scores
- Signed Cloudinary uploads for book covers
- JWT cookie authentication and OpenAPI documentation