Skip to content

KshitijAng/FlowVentry-Inventory-Management

Repository files navigation

FlowVentry — Inventory Management (Next.js + MongoDB)

A minimal full-stack inventory app: search, add, and adjust product stock backed by MongoDB Atlas, served through Next.js App Router API routes, and rendered with a single React 19 client component.

FlowVentry banner

What it does

  • Live search — typing into the search box queries MongoDB's $text operator (text index across name / quantity / price) and renders matches in a dropdown.
  • Inline quantity adjust+ / buttons in the dropdown call updateOne to change stock without leaving the page.
  • Add product form — name / quantity / price, posted to /api/product and persisted with insertOne.
  • Stock table — every product in the collection, with a running quantity total in the footer.

Tech stack

Layer Tool
Framework Next.js 15.5 (App Router)
UI React 19 + Tailwind CSS v4
Database MongoDB Atlas (SRV connection)
Driver mongodb v6.20 (official Node.js driver — not Mongoose)
Fonts Geist + Geist Mono (via next/font)
Hosting Vercel

Architecture

FlowVentry-Inventory-Management/
├── lib/
│   └── mongodb.js              Cached MongoClient singleton (env-var driven)
├── app/
│   ├── layout.js               Root layout + font setup
│   ├── page.js                 Single-page client UI (search, add, stock table)
│   ├── globals.css             Tailwind base + custom styles
│   ├── components/
│   │   ├── Header.js           Top nav
│   │   └── Footer.js           Footer with social icons
│   └── api/
│       ├── product/route.js    GET (list) + POST (insert)
│       ├── search/route.js     GET — `$text` aggregation search
│       └── update/route.js     POST — quantity +/− via `updateOne`
└── public/                     Static assets (logo, banner)

How it works

  • Cached MongoClient. lib/mongodb.js keeps one clientPromise at module scope and pins it on globalThis in development so Next.js HMR doesn't spawn a new client on every code edit. Production skips the global cache because modules load once. Replaces a previous per-request new MongoClient() pattern that opened and closed a TCP connection on every API call.
  • Search via $text aggregation. aggregate([{ $match: { $text: { $search: query } } }]) runs against a compound text index on name, quantity, and price. Using aggregation (instead of a plain find) leaves room to extend the pipeline later — sort by textScore, add fuzzy matching, filter by category — without reshaping the call site.
  • One client component. app/page.js carries the entire user-facing app: 8 useState slots for form state, loading flags, the dropdown, and the active query. Server components are used only for the layout shell, header, and footer.
  • No ORM. The MongoDB Node driver is used directly. The only enforced shape is the text index.
  • Env-var configuration. MONGODB_URI and MONGODB_DB are read from process.env. The check is deferred to first request, so next build succeeds without runtime env vars set (route handlers don't fire at build time).

API

Method Path Body / Query Returns
GET /api/product { success, allProducts: [] }
POST /api/product { name, quantity, price } { product, ok: true }
GET /api/search ?query=<term> { allProducts: [] } — matched via $text
POST /api/update { action: "plus"|"minus", name, initialQuantity } { success, message }

About

Next.js 15 + MongoDB inventory app - module-level cached MongoClient singleton, $text aggregation pipeline with a compound text index for relevance search.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors