
Capabilities
- Documented API
- File uploads
- JWT authentication
Frontend
Backend
NodePop
CompletedNodePop is a second-hand marketplace built as two separate projects: a REST API in Express with TypeScript and MongoDB, and a React SPA on Vite. Post, search, filter by tag and price range, upload photos and manage the session, with filtering resolved server-side.
The challenge
The listing had to scale without shipping the whole collection to the browser, and the SPA had to react to an expired session from any screen without coupling the network layer to the component tree.
Implementation
Server-side filtering, sorting and pagination
The listing accepts name search, multiple tags, price range, availability, sorting across several fields and pagination with a hard cap, so the client never downloads more than it shows.
Image upload and serving
Photos uploaded via multer over multipart, a dedicated endpoint serving them with 24-hour caching, and absolute URLs built from a configured public base URL so they behave identically locally and in production.
Session state propagated by events
A single Axios client owns the token and emits an event when the server answers 401. The React tree learns the session expired without the network layer knowing anything about the auth context.
Clean post-login redirect
The private-route guard remembers where the user was kicked out from and returns them exactly there after signing in, instead of dumping them on the home page.
Hardened API
Helmet, CORS restricted to an allow-list, a 20-requests-per-15-minutes limit on login and register, express-validator validation, and a refusal to boot in production without a JWT secret.
Passwords that never escape
The bcrypt hash is marked unselectable in the schema and additionally stripped during JSON serialisation, so no response can leak it by accident.
Documentation and translated messages
A Swagger spec generated from annotations in the code itself, and i18n on the API's error messages.