Smart Inventory & Auto-Merging Catalog API

By (author)Hafsa Yousuf

Tech stack:
Next.js
TS
Supabase
PG
TW
React

Production-ready Next.js 14 inventory system with real-time catalog search, quantity auto-merging logic, and Supabase RLS security.
AI Contributions:1
Published At:August 13, 2026
Files Included:1 file(s)
Updated At:October 22, 2026

Read Me

Smart Inventory & Auto-Merging Catalog API (Next.js 14 + Supabase SSR)

A premium, fully responsive, and generic smart inventory pantry and grocery catalog search system for Next.js 14 App Router projects.

Features

  • Smart Catalog Search: Real-time grocery/ingredient catalog search with dynamic category-based filtering.
  • Fallbacks to JSON Seed: The catalog search gracefully falls back to a 180+ standard item dataset if Supabase connectivity is offline or unconfigured.
  • Auto-Merge Quantity Logic: Intelligent duplicate handling that aggregates quantities for matching item names (case-insensitive) and units instead of creating messy duplicate records.
  • Full Pantry CRUD: Inline quantity drafting, fast updates on-blur, instant deletion actions, and organized category grouping badges.
  • Row-Level Security (RLS): Secure pantry entries isolated and scoped exclusively to authenticated users (user_id = auth.uid()).

Auto-Merging Mechanism

When a POST request is sent to /api/inventory with a payload of items, the server-side route handles processing in three clear steps:

  1. Query & Match: For each incoming item, the backend queries public.inventory_items filtered by user_id, comparing item_name (case-insensitive) and unit.
  2. Quantity Aggregation (If Match Found): If an entry exists, it updates the record by setting quantity = existing_quantity + new_quantity.
  3. Dynamic Insertion (If No Match Found): If no matching entry exists, it executes an insert query to create a clean new row.

Directory Structure

Ensure files are placed in your Next.js project according to this map:
 
your-project/
├── app/
│   └── api/
│       ├── catalog/
│       │   └── route.ts         <-- Copy from modules/smart-inventory/app/api/catalog/route.ts
│       └── inventory/
│           └── route.ts         <-- Copy from modules/smart-inventory/app/api/inventory/route.ts
├── components/
│   ├── catalog/
│   │   └── CatalogSearch.tsx    <-- Copy from modules/smart inventory/components/catalog/CatalogSearch.tsx
│   └── inventory/               <-- Copy from modules/smart-inventory/components/inventory/
│       ├── AddItemModal.tsx
│       ├── InventoryPanel.tsx
│       └── InventoryItemRow.tsx
├── lib/
│   ├── catalog.ts               <-- Copy from modules/smart-inventory/lib/catalog.ts
│   ├── catalog-seed.json        <-- Copy from modules/smart-inventory/lib/catalog-seed.json
│   ├── inventory-api-types.ts   <-- Copy from modules/smart-inventory/lib/inventory-api-types.ts
│   ├── types-snippet.ts         <-- Copy from modules/smart-inventory/lib/types-snippet.ts
│   └── supabase-server.ts       <-- Copy from modules/smart-inventory/lib/supabase-server.ts
└── supabase/
    └── schema.sql               <-- Setup tables using modules/smart-inventory/supabase/schema.sql
 

Installation Steps

Step 1: Execute SQL Setup

Run the SQL queries in supabase/schema.sql inside your Supabase project's SQL editor. This creates:

  1. public.catalog_items table with a public read-only RLS policy.

  2. public.inventory_items table with RLS scoped to auth.uid() = user_id.

Step 2: Seed the Catalog (Optional but Recommended)

To populate your catalog_items table with the prebuilt dataset:

  1. Copy the JSON array from lib/catalog-seed.json.

  2. Execute the following SQL query in your Supabase SQL Editor:

with seed_items as (

select * from jsonb_to_recordset($json$

[PASTE JSON SEED CONTENT HERE]

$json$::jsonb) as item(name text, category text, default_unit text)

)

insert into public.catalog_items (name, category, default_unit)

select lower(trim(name)), trim(category), trim(default_unit)

from seed_items

on conflict (name) do update

set category = excluded.category,

default_unit = excluded.default_unit;

Step 3: Environment Variables

Add the following keys to your local .env.local file:

NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url

NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key

Step 4: Import & Mount Components

Mount <InventoryPanel /> inside any authenticated dashboard page layout:

import { InventoryPanel } from '@/components/inventory/InventoryPanel';

export default function Dashboard() {

function handleSelectedAction(selectedIds: string[]) {

console.log("Selected IDs to process:", selectedIds);

}

return (

);

}

Loading

Loading

Loading

More like this View all

Auth Module with Supabase SSR + Optional 2FA

A production-ready, plug-and-play authentication module built with Next.js 14 App Router and Supabase SSR. Drop it into any Next.js project to get a fully working auth system in minutes.

  • 0

    Ratings

  • 1

    Files

    • TS
    • Supabase
    • +4

    Tech stack

Multi-Step Onboarding & Team Setup Engine

Middleware-protected Next.js 14 onboarding wizard with dynamic team/household inputs and relational Supabase DB inserts.

  • 0

    Ratings

  • 1

    Files

    • Next.js
    • TS
    • +4

    Tech stack

Supabase Auth + 2FA Kit for Next.js (TOTP, RLS)

Sign-up, sign-in and authenticator-app 2FA for Next.js + Supabase. Server-side 2FA check for API routes, Security page (2FA on/off), AuthGuard and an RLS template. Builds clean.

  • 0

    Ratings

  • 23

    Files

    • JS
    • TS
    • +7

    Tech stack