-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Browser ──HTTPS──► Express API (/api) ──► MongoDB Atlas
▲ │
└──── Socket.IO ─────┘ live chat messages and notifications
-
Client: React single-page app in
client/, built by Vite. All data fetching goes through TanStack Query hooks inclient/src/hooks/queries.ts. -
API: Express in
server/, one router and one controller per area: auth, books, catalogue, cart, wishlist, orders, returns, reviews, chat, notifications, users. -
Same origin: in production one process serves both the API (under
/api) and the built site. The refresh-token cookie depends on this; split across two hosts, it would not survive.
server/shared/api.d.ts
declares every request and response shape. The server and the client
(as @shared/*) both compile against it, so a response cannot change on one
side without the other failing to type-check. Every request is also validated
on arrival by a Zod schema in server/schemas/.
The server decides anything that costs money or grants access; pages only show what it will accept.
| Rule | File |
|---|---|
| Delivery charge, return window, seller fee, who may move or cancel an order | server/config/commerce.ts |
| Discounts and sale prices | server/config/pricing.ts |
| Promo codes | server/config/promotions.ts |
| What shoppers are told (the same figures, for display) | client/src/config/site.ts |
| The categories | client/src/config/categories.ts |
When you change a rule, change both the server file and site.ts.
POST /auth/signin returns a short-lived access token (15 minutes), sent as
Authorization: Bearer …, and sets a refresh token in an httpOnly cookie
(30 days). The client renews the access token on its own when it runs out.
Roles are user and admin; selling is decided by owning the book, not by a role.
One Socket.IO connection per signed-in tab, authenticated with the access token. Each user is placed in their own room. The server pushes two events:
| Event | Carries |
|---|---|
receive_message |
A new chat message |
notification |
A new item for the bell |
Browsers never send over it. A message is saved with POST /chat/message and
then delivered.
One collection per model: users, books (addbooks), carts, wishlists, orders
(one document per book in an order, grouped by orderNumber), returns,
reviews and seller ratings with their reports, chat messages, notifications (kept 90 days), and
refresh tokens.
Covers and photos go straight from the browser to Cloudinary when it is configured; otherwise they are stored inline.
| Server | Client | |
|---|---|---|
| Runner | Vitest + Supertest | Vitest + Testing Library |
| Database | A real in-memory MongoDB | none |
server/tests/regressions.test.ts holds one case for every bug that actually
shipped. If it fails, an old bug is back.
BookStoreBD · MIT License · Questions: support.utsha@gmail.com
Using the shop
Working on it
Links