Stock & Warehouse Inventory Management System - Next.js, TypeScript, Prisma, MongoDB FullStack Project (including Business-Insights & Admin, Client, Supplier Dashboard)
A full-stack warehouse and stock inventory management system built with Next.js, React, Prisma, and MongoDB. It helps store owners, suppliers, and clients manage products, orders, invoices, warehouses, and support tickets with role-based access, analytics dashboards, QR codes, payments (Stripe), shipping (Shippo), and email (Brevo). This README is written for learning, reuse, and deployment—with project structure, API reference, environment setup, and usage walkthroughs.
- Live Demo: https://stockly-inventory.vercel.app/
- Project Overview
- Features & Functionality
- Technology Stack
- Getting Started
- Environment Variables
- Project Structure
- Application Routes
- API Endpoints
- Backend & Database
- Key Components & Reuse
- Keywords
- License
- Happy Coding
Stockly is a role-based inventory and order management platform. It supports three roles:
- Admin (store owner): Full access to products, categories, suppliers, warehouses, orders, invoices, analytics, user management, support tickets, and client/supplier portal views.
- Supplier: Own products, orders containing their products, revenue, and support tickets.
- Client: Browse catalog, place orders, view invoices, pay via Stripe, and open support tickets.
The app uses Next.js 16 App Router, Prisma with MongoDB, JWT auth, TanStack Query for server state, shadcn/ui + Tailwind for UI, and optional integrations: Stripe (payments), Shippo (shipping), Brevo (email), ImageKit (images), Upstash Redis (cache), Sentry (monitoring), and OpenRouter (AI insights). All features are designed so you can run the core app with minimal env vars and add integrations as needed.
- Products: CRUD, SKU, categories, suppliers, stock levels, status (available / stock low / out), QR codes, import (CSV/Excel), export.
- Categories & Suppliers: CRUD with status; used for filtering and reporting.
- Orders: Create/edit orders with line items, tax/shipping/discount rules, status and payment status; client vs admin views.
- Invoices: One per order; status (draft, sent, paid, overdue, cancelled); PDF, send email, Stripe payment link.
- Warehouses: CRUD, types, status; used for organization and future stock allocation.
- Payments: Stripe Checkout for orders/invoices; webhook for fulfillment.
- Shipping: Shippo labels, rates, tracking; webhook for status.
- Admin: Dashboard (counts, revenue, trends), business insights (charts), admin panel (orders, invoices, products, categories, suppliers, warehouses, users, support tickets, activity history, import history, product reviews, settings). Client and supplier portal “overview” pages for monitoring.
- Supplier: Supplier dashboard (products, orders, revenue, low stock), products/orders/support scoped to their data.
- Client: Client dashboard (orders, spending, invoices), catalog (suppliers, categories, products), orders, invoices, support tickets; checkout and payment flows.
- Support tickets: Create, reply, status/priority; assigned to product owner (admin); client/supplier see their own.
- Product reviews: Customers can leave reviews; admin approves/rejects; eligibility by order.
- Analytics & insights: Charts (revenue, orders, categories, etc.), forecasting section, AI insights (optional OpenRouter).
- API docs & status: In-app API documentation and health/status page.
- Notifications: In-app notifications; optional email (Brevo) for invoices and reminders.
- Theme: Light/dark with system preference; persisted.
| Layer | Technologies |
|---|---|
| Framework | Next.js 16 (App Router), React 19 |
| Language | TypeScript 5 |
| Database | MongoDB via Prisma ORM |
| Auth | JWT (cookie), bcryptjs; optional Google OAuth |
| State | TanStack Query (server), Zustand (client), React state |
| UI | Tailwind CSS, shadcn/ui (Radix), Lucide icons, Recharts |
| Forms | React Hook Form, Zod |
| Payments | Stripe (Checkout, Payment Intents, webhooks) |
| Shipping | Shippo (labels, rates, tracking) |
| Brevo (transactional, reminders) | |
| Images | ImageKit (optional) |
| Cache | Upstash Redis (optional) |
| Monitoring | Sentry (optional) |
| AI | OpenRouter (optional, insights) |
- Node.js 18+ (recommended 20+)
- npm or yarn
- MongoDB (local or Atlas)
# Clone the repository
git clone <your-repo-url>
cd stock-inventory
# Install dependencies
npm install
# Copy environment template and set the three required variables (see below)
cp .env.example .env
# Edit .env: set DATABASE_URL, JWT_SECRET, and NEXT_PUBLIC_API_URL (e.g. http://localhost:3000)
# Generate Prisma client (runs automatically on postinstall)
npx prisma generate
# Run development server
npm run devOpen http://localhost:3000. All other variables in .env.example are optional and enable extra features (Stripe, Brevo, etc.).
Default scripts:
| Script | Command | Description |
|---|---|---|
| Dev | npm run dev |
Next.js dev server (Turbopack) |
| Build | npm run build |
Prisma generate + production build |
| Start | npm run start |
Production server |
| Lint | npm run lint |
ESLint |
The app uses three required variables (validated in lib/env.ts). Everything else is optional and enables specific features. Use .env.example as a template: copy it to .env and set at least the required ones to run locally.
| Variable | Description | Example for localhost |
|---|---|---|
DATABASE_URL |
MongoDB connection string | mongodb://localhost:27017/stockly or Atlas mongodb+srv://user:pass@cluster.../stockly?retryWrites=true&w=majority |
JWT_SECRET |
Secret for signing JWT session cookies | Any long random string (e.g. 32+ characters) |
NEXT_PUBLIC_API_URL |
Base URL of the app (emails, redirects, API base) | http://localhost:3000 for local; your production URL in prod |
Uncomment and set in .env only if you need the feature:
| Variable | Purpose |
|---|---|
| ImageKit | IMAGEKIT_PUBLIC_KEY, IMAGEKIT_PRIVATE_KEY, IMAGEKIT_URL_ENDPOINT, NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY, NEXT_PUBLIC_IMAGEKIT_URL_ENDPOINT — Product image uploads |
| Google OAuth | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, NEXT_PUBLIC_GOOGLE_CLIENT_ID — Sign in with Google |
| Brevo | BREVO_API_KEY, BREVO_SENDER_EMAIL, BREVO_SENDER_NAME, BREVO_ADMIN_EMAIL — Transactional email (invoice send, reminders) |
| Sentry | SENTRY_DSN, NEXT_PUBLIC_SENTRY_DSN — Error monitoring |
| Upstash Redis | UPSTASH_REDIS_URL, UPSTASH_REDIS_TOKEN (or UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN) — Caching, rate limiting |
| QStash | QSTASH_URL, QSTASH_TOKEN, QSTASH_CURRENT_SIGNING_KEY, QSTASH_NEXT_SIGNING_KEY — Background job queue (e.g. email) |
| OpenRouter | OPENROUTER_API_KEY — AI insights feature |
| Stripe | STRIPE_API_KEY, STRIPE_WEBHOOK_SECRET, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY — Payments (checkout, webhooks) |
| Shippo | SHIPPO_API_KEY, and optionally SHIPPO_FROM_NAME, SHIPPO_FROM_STREET1, SHIPPO_FROM_CITY, SHIPPO_FROM_STATE, SHIPPO_FROM_ZIP, SHIPPO_FROM_COUNTRY, SHIPPO_FROM_PHONE, SHIPPO_FROM_EMAIL — Shipping labels, rates, tracking |
| App URL | NEXT_PUBLIC_APP_URL — Metadata and some redirects (defaults to Vercel URL if unset) |
| Internal API | INTERNAL_API_KEY — Bearer token for server-to-server calls (e.g. cron hitting /api/invoices/reminders) |
DATABASE_URL="mongodb://localhost:27017/stockly"
JWT_SECRET="your-super-secret-jwt-key-min-32-chars"
NEXT_PUBLIC_API_URL="http://localhost:3000"Below is the complete .env.example file so you can see exactly what to set. Copy the repo’s .env.example to .env, then fill in the required values (first three). Optional variables are commented out; uncomment and set them only if you need those features.
# =============================================================================
# REQUIRED – Set these three so the app can start (see lib/env.ts).
# Copy this file to .env and fill in your values. Never commit .env to git.
# =============================================================================
# MongoDB connection string (local or Atlas).
# Local: mongodb://localhost:27017/stockly
# Atlas: mongodb+srv://USER:PASSWORD@cluster.mongodb.net/stockly?retryWrites=true&w=majority
DATABASE_URL="mongodb://localhost:27017/stockly"
# Secret used to sign JWT session tokens. Use a long random string in production.
JWT_SECRET="your_super_secret_jwt_key_here_change_this_in_production"
# Base URL of this app (used for emails, redirects, API base). Use http://localhost:3000 for local.
NEXT_PUBLIC_API_URL="http://localhost:3000"
# =============================================================================
# OPTIONAL – App works without these. Uncomment and set to enable features.
# =============================================================================
# Environment (development | production). Usually set by the runner.
# NODE_ENV="development"
# Used in metadata and some redirects. Defaults to Vercel URL if unset.
# NEXT_PUBLIC_APP_URL="http://localhost:3000"
# --- ImageKit (product images, uploads) - https://imagekit.io ---
# IMAGEKIT_PUBLIC_KEY=
# IMAGEKIT_PRIVATE_KEY=
# IMAGEKIT_URL_ENDPOINT=
# NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY=
# NEXT_PUBLIC_IMAGEKIT_URL_ENDPOINT=
# --- Google OAuth - https://console.cloud.google.com/apis/credentials ---
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=
# NEXT_PUBLIC_GOOGLE_CLIENT_ID=
# --- Brevo (transactional email, invoice send, reminders) - https://www.brevo.com ---
# BREVO_API_KEY=
# BREVO_SENDER_EMAIL=
# BREVO_SENDER_NAME=
# BREVO_ADMIN_EMAIL=
# --- Sentry (error monitoring) - https://sentry.io ---
# SENTRY_DSN=
# NEXT_PUBLIC_SENTRY_DSN=
# --- Upstash Redis (caching, rate limit) - https://upstash.com ---
# UPSTASH_REDIS_URL=
# UPSTASH_REDIS_TOKEN=
# Or: UPSTASH_REDIS_REST_URL= and UPSTASH_REDIS_REST_TOKEN=
# --- QStash (background jobs, e.g. email queue) - https://upstash.com/qstash ---
# QSTASH_URL=
# QSTASH_TOKEN=
# QSTASH_CURRENT_SIGNING_KEY=
# QSTASH_NEXT_SIGNING_KEY=
# --- OpenRouter (AI insights) - https://openrouter.ai ---
# OPENROUTER_API_KEY=
# --- Stripe (payments – checkout, webhooks) - https://dashboard.stripe.com/test/apikeys ---
# STRIPE_API_KEY=sk_test_...
# STRIPE_WEBHOOK_SECRET=whsec_... (Stripe Dashboard → Webhooks → add /api/payments/webhook)
# NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
# --- Shippo (shipping labels, rates, tracking) - https://goshippo.com/dashboard/apikeys ---
# SHIPPO_API_KEY=shippo_test_...
# Sender address for labels (optional):
# SHIPPO_FROM_NAME=
# SHIPPO_FROM_STREET1=
# SHIPPO_FROM_STREET2=
# SHIPPO_FROM_CITY=
# SHIPPO_FROM_STATE=
# SHIPPO_FROM_ZIP=
# SHIPPO_FROM_COUNTRY=
# SHIPPO_FROM_PHONE=
# SHIPPO_FROM_EMAIL=
# --- Internal API (e.g. cron calling /api/invoices/reminders with Bearer token) ---
# INTERNAL_API_KEY=
# =============================================================================
# Instructions:
# 1. cp .env.example .env
# 2. Set DATABASE_URL, JWT_SECRET, and NEXT_PUBLIC_API_URL at minimum.
# 3. Uncomment and set any optional vars you need. Never commit .env.
# =============================================================================Or copy the project’s .env.example to .env and leave the optional variables commented out; the app will start with only the three required ones set.
- MongoDB: Local:
mongodb://localhost:27017/stockly. Cloud: mongodb.com/atlas - Stripe: dashboard.stripe.com → API keys; Webhooks → add endpoint for
/api/payments/webhook - Shippo: goshippo.com → API keys (use test key for development)
- Brevo: brevo.com → API key and sender/admin email settings
- ImageKit: imagekit.io → keys and URL endpoint
- Upstash Redis / QStash: upstash.com
- Sentry: sentry.io
- OpenRouter: openrouter.ai
stock-inventory/
├── app/ # Next.js App Router
│ ├── layout.tsx # Root layout, metadata, providers
│ ├── page.tsx # Home (store overview for admin)
│ ├── login/ # Login page
│ ├── register/ # Registration
│ ├── products/ # Products list & detail
│ ├── orders/ # Orders list & detail
│ ├── invoices/ # Invoices list & detail
│ ├── categories/ # Categories list & detail
│ ├── suppliers/ # Suppliers list & detail
│ ├── warehouses/ # Warehouses list & detail
│ ├── client/ # Client portal dashboard
│ ├── supplier/ # Supplier portal dashboard
│ ├── support-tickets/ # Support tickets (all roles)
│ ├── business-insights/ # Business insights (charts)
│ ├── api-docs/ # API documentation page
│ ├── api-status/ # API status page
│ ├── settings/ # User settings (e.g. email preferences)
│ ├── admin/ # Admin panel (layout + nested routes)
│ │ ├── dashboard-overall-insights/
│ │ ├── products/, orders/, invoices/, categories/, suppliers/, warehouses/
│ │ ├── client-orders/, client-invoices/, client-portal/, supplier-portal/
│ │ ├── support-tickets/, user-management/, activity-history/
│ │ ├── history/ (import history), product-reviews/, my-activity/
│ │ └── settings/
│ └── api/ # API route handlers (see API Endpoints)
├── components/ # React components
│ ├── ui/ # shadcn-style primitives (button, dialog, table, etc.)
│ ├── layouts/ # Navbar, AdminSidebar, PageWithSidebar, etc.
│ ├── Pages/ # Page-level components (HomePage, LoginPage, etc.)
│ ├── home/ # Statistics cards, sections for home
│ ├── products/ # ProductList, ProductTable, dialogs, filters
│ ├── orders/ # OrderList, OrderDialog, filters, shipping
│ ├── invoices/ # InvoiceList, InvoiceDialog, filters
│ ├── category/, supplier/, warehouses/ # List, table, dialog, filters
│ ├── payments/ # PaymentButton, PaymentDialog
│ ├── support-tickets/ # Ticket list, detail, dialog
│ ├── product-reviews/ # Reviews section, dialogs
│ ├── admin/ # Admin-only content (tables, details, settings)
│ ├── shared/ # ErrorBoundary, PaginationSelector, etc.
│ ├── providers/ # ThemeProvider, KeyboardShortcutsProvider
│ ├── forms/, dialogs/ # Shared form and dialog building blocks
│ └── ...
├── lib/ # Shared backend/utility code
│ ├── api/ # API client, endpoints, CORS, rate limit
│ ├── auth/ # OAuth helpers
│ ├── cache/ # Redis cache utils
│ ├── email/ # Brevo send, templates, queue
│ ├── server/ # Server-side data (dashboard, invoices, orders, etc.)
│ ├── react-query/ # Query client, keys, provider, invalidate-all
│ ├── validations/ # Zod schemas (product, order, invoice, etc.)
│ ├── stripe/, shippo/ # Payment & shipping
│ ├── imagekit.ts # ImageKit client
│ ├── env.ts # Env validation
│ └── ...
├── hooks/queries/ # TanStack Query hooks (useProducts, useOrders, etc.)
├── contexts/ # Auth context
├── types/ # TypeScript types (dashboard, product, order, etc.)
├── prisma/
│ ├── schema.prisma # MongoDB models (User, Product, Order, Invoice, etc.)
│ ├── client.ts # Prisma client singleton
│ └── *.ts # Repository-style helpers (product, order, invoice, etc.)
├── utils/ # auth (JWT, session), axiosInstance
├── middleware.ts # Next.js middleware (e.g. auth redirects)
└── public/ # Static assets (favicon, SVGs)| Path | Who | Description |
|---|---|---|
/ |
Admin | Store overview (state cards) |
/login, /register |
All | Auth |
/products, /products/[id] |
All | Products list & detail |
/orders, /orders/[id] |
All | Orders list & detail |
/invoices, /invoices/[id] |
All | Invoices list & detail |
/categories, /categories/[id] |
All | Categories |
/suppliers, /suppliers/[id] |
All | Suppliers |
/warehouses, /warehouses/[id] |
All | Warehouses |
/client |
Client | Client dashboard |
/supplier |
Supplier | Supplier dashboard |
/support-tickets, /support-tickets/[id] |
All | Support tickets |
/business-insights |
Admin | Business charts |
/api-docs, /api-status |
All | API docs & status |
/settings/email-preferences |
All | Email preferences |
/admin/* |
Admin | Admin panel (dashboard, products, orders, invoices, users, etc.) |
All under /api, authenticated via cookie session_id (JWT) unless noted.
POST /api/auth/register— RegisterPOST /api/auth/login— LoginPOST /api/auth/logout— LogoutGET /api/auth/session— Current sessionGET /api/auth/oauth/google,GET /api/auth/oauth/google/callback— Google OAuth
GET|POST /api/products,GET|PATCH|DELETE /api/products/[id]GET|POST /api/categories,GET|PATCH|DELETE /api/categories/[id]GET|POST /api/suppliers,GET|PATCH|DELETE /api/suppliers/[id]GET|POST /api/orders,GET|PATCH|DELETE /api/orders/[id]GET|POST /api/invoices,GET|PATCH|DELETE /api/invoices/[id]GET|POST /api/warehouses,GET|PATCH|DELETE /api/warehouses/[id]
GET /api/products/import— Import (CSV/Excel)POST /api/products/image— Image upload (e.g. ImageKit)GET /api/products/qr-code— QR code for product
GET /api/invoices/[id]/pdf— PDFPOST /api/invoices/[id]/send— Send emailPOST /api/invoices/reminders— Send reminders (optionalINTERNAL_API_KEY)
POST /api/payments/checkout— Create Stripe Checkout sessionPOST /api/payments/webhook— Stripe webhookPOST /api/shipping/labels— Shippo labelGET /api/shipping/rates— Shippo ratesGET /api/shipping/tracking— Tracking
GET /api/dashboard— Admin dashboard statsGET /api/portal/client— Client dashboard (client only)GET /api/portal/client/catalog— Client catalog (client only)GET /api/portal/client/browse-meta,GET /api/portal/client/browse-products— Browse (client)GET /api/portal/supplier— Supplier dashboard (supplier only)GET /api/admin/client-orders,GET /api/admin/client-invoices— Admin client dataGET /api/client-portal,GET /api/supplier-portal— Admin overview (admin only)GET /api/admin/counts— Admin sidebar counts
GET|POST /api/support-tickets,GET|PATCH /api/support-tickets/[id]POST /api/support-tickets/[id]/repliesGET /api/support-tickets/product-ownersGET|POST /api/product-reviews,GET|PATCH|DELETE /api/product-reviews/[id]GET /api/product-reviews/by-product/[productId],GET /api/product-reviews/eligibility
GET|POST /api/users,GET|PATCH|DELETE /api/users/[id]— Admin onlyGET|PUT /api/user/email-preferencesGET|PATCH /api/notifications/in-app,GET /api/notifications/in-app/unread-count, etc.GET /api/import-history,GET /api/import-history/[id]GET /api/audit-logs— Admin onlyGET|PATCH /api/system-config— Admin onlyGET /api/forecasting,GET /api/ai/insightsGET /api/stock-allocationsGET /api/health— Health checkGET /api/openapi— OpenAPI spec
- Schema:
prisma/schema.prisma(datasourcemongodb). - Models: User, Category, Supplier, Product, Order, OrderItem, Invoice, Warehouse, SupportTicket, SupportTicketReply, ProductReview, ImportHistory, Notification, etc. Relations and indexes are defined in the schema.
- Client: Singleton in
prisma/client.ts; used by API routes andlib/server/*andprisma/*.tshelpers.
- Dashboard:
lib/server/dashboard-data.ts— admin dashboard aggregates (counts, revenue, trends, recent activity). - Client dashboard:
lib/server/client-dashboard.ts— client stats and catalog. - Supplier dashboard:
lib/server/supplier-dashboard.ts— supplier stats. - Invoices/orders:
lib/server/invoices-data.ts,lib/server/orders-data.ts, etc. — used for SSR and API.
- Login/register set a JWT in cookie
session_id. utils/auth.ts:getSessionFromRequest(request)reads cookie, verifies JWT, loads user from DB.- API routes call
getSessionFromRequest(request)and checksession.roleandsession.idfor authorization.
Most UI primitives live under components/ui/ (button, dialog, input, table, badge, etc.). They are built for Tailwind and can be reused in any page or component.
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
<Button variant="default">Save</Button>
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent>...</DialogContent>
</Dialog>Data fetching is centralized in hooks/queries/. Use the hooks in components; they handle loading, error, and cache.
import { useProducts, useCategories } from "@/hooks/queries";
function MyComponent() {
const { data: products, isLoading } = useProducts();
const { data: categories } = useCategories();
// ...
}import { useAuth } from "@/contexts";
function MyComponent() {
const { user, isLoggedIn, logout, isCheckingAuth } = useAuth();
if (isCheckingAuth) return <Skeleton />;
if (!isLoggedIn) return <Redirect to="/login" />;
return <div>Hello, {user?.name}</div>;
}- Copy
components/ui/*and any Tailwind/shadcn config and dependencies. - Copy
lib/utils.ts(e.g.cn()). - Copy specific feature folders (e.g.
components/products/,hooks/queries/use-products.ts) and adapt API client and types to your backend. - Reuse
lib/validations/*(Zod schemas) and align with your API payloads.
import { StatisticsCard } from "@/components/home/StatisticsCard";
<StatisticsCard
title="Total Products"
value={count}
description="Products in catalog"
variant="violet"
badges={[
{ label: "Active", value: activeCount },
{ label: "Inactive", value: inactiveCount },
]}
/>;import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const schema = z.object({ name: z.string().min(1) });
type FormData = z.infer<typeof schema>;
const form = useForm<FormData>({
resolver: zodResolver(schema),
defaultValues: { name: "" },
});- Setup: Set
DATABASE_URL,JWT_SECRET, andNEXT_PUBLIC_API_URLin.env, then runnpm installandnpm run dev. - Register: Open
/register, create an admin user (first user can act as store owner). - Login: Go to
/login, sign in; you land on/(store overview). - Products: Go to
/products, add categories and suppliers, then add products. - Orders & invoices: Create an order at
/orders, then create or view its invoice at/invoices. - Roles: Create users with roles
clientorsupplier(e.g. via admin user management); log in as them to see client portal (/client) or supplier portal (/supplier). - Optional: Add Stripe, Shippo, or Brevo env vars to enable payments, shipping, or email.
Stockly is a full-stack example of a role-based inventory and order management app with Next.js 16, React 19, Prisma, and MongoDB. It demonstrates App Router structure, API route design, JWT auth, TanStack Query, and optional third-party integrations. Use this README as a map to the codebase, env setup, APIs, and components so you can run, extend, or reuse parts of the project in your own applications.
stock inventory, inventory management, warehouse management, stock management system, Next.js, React, Prisma, MongoDB, product catalog, orders, invoices, suppliers, categories, JWT authentication, Stripe payments, Shippo shipping, Brevo email, role-based access, admin dashboard, client portal, supplier portal, TanStack Query, TypeScript, Tailwind CSS, shadcn/ui, Arnob Mahmud
This project is licensed under the MIT License. Feel free to use, modify, and distribute the code as per the terms of the license.
This is an open-source project — feel free to use, enhance, and extend this project further!
If you have any questions or want to share your work, reach out via GitHub or my portfolio at https://www.arnobmahmud.com.
Enjoy building and learning! 🚀
Thank you! 😊