Bits n Bobs
A clean and reliable inventory manager that organizes products into categories, tracks stock levels, flags low inventory, and stores pricing and product details.
Key features:
- Real time updates
- Password protected edits and deletions
- Filter and search functionality with substring matching
- REST API Backend hosted on self-managed linux VPS
Why this project?
My motivation for this project was to practice building a Node.js and Express application in a real-world context while also gaining a deeper understanding of relational databases and CRUD operations. When it came time to deploy, I used it as an opportunity to learn new skills by setting up a Linux VPS on DigitalOcean to host both the database and the app. The original idea for the project came from The Odin Project, which provided the foundation for its scope and direction.
How did you do it?
Express
Node.JS
PostgreSQL
Digital Ocean
HTML
CSS
Database Design
My first step was designing the database schema
I decided that products should only exist within a category, and that if a category is
deleted, then all products within that category are also deleted.
I added some bounding for field values to limit text length, and prevent unreasonable numerical
values, while also ensuring the critical stock warning value was atleast as small as the low
stock warning value.
Each product has a field for critical and low stock count warnings providing up to two visual
warnings on products as their stock depletes. These warnings can be seen on their respective
category and product cards.

Routes and API
I structured the backend using the Model-View-Controller (MVC) pattern, defining routes
for each page and every database interaction. It functions as a REST API, handling all
CRUD operations.
To ensure data integrity and security, I validated inputs at multiple levels:
- HTML form attributes for basic checks
- Express Validator for server-side validation
- SQL constraints in the database for enforcement
Additionally, destructive actions (deletes and edits) are password-protected to prevent
misuse.
In this example, trying to add a product with a duplicate title triggers validation errors
and displays them to the user.

Deployment
When it came time to deploy, I also experimented with hosting strategies. I spun up a
DigitalOcean VPS, set up dedicated app and database users to keep things separated, and
reserved root only for sudo access.
The app runs under pm2, while Postgres handles the database, both living on the same always-on
server.