Intelligent Inventory

Universidad Nacional de Colombia · 2026 - At present

Next.jsSupabasePostgreSQLMQTT

The Prototyping Center lends tools, components and materials out of a set of cabinets, and until now nobody could answer "who has the soldering station and since when?" without asking around. This full-stack application puts the cabinets, the inventory and the reservations in one place, records every movement, and can pop a cabinet open over MQTT from the same screen.

Architecture and Tech Stack

Core Architecture

  • Framework: Next.js 16 (App Router), server-first, with the React Compiler enabled
  • Language: TypeScript in strict mode
  • Backend platform: Supabase — PostgreSQL, Auth and Realtime
  • Validation: Zod schemas as the single input gate for every server action
  • Hardware bridge: MQTT over TLS against a managed broker
  • Tables and charts: TanStack Table for the admin grids, Recharts for the dashboard
  • Exports: jsPDF + jspdf-autotable for inventory reports
  • UI: shadcn/ui (Radix Nova) + Tailwind CSS 4, next-themes for light/dark

Layered Architecture

Reads and writes are separated at the architecture level, not by convention: mutations live in their own action layer and queries in a data layer. A page never queries the database inline, and a form never reads — which is what keeps every authorization check in exactly one place per operation.

Request Flow

Key Features

Features at a Glance

Cabinets and quick open

Each cabinet is modelled digitally with its contents and state. From the admin panel a cabinet can be opened directly: the action goes out through the hardware bridge with its own timeout and error handling, so an unreachable broker surfaces as a failed action instead of a spinner that never resolves.

Reservations

Students and staff request materials; the team approves or rejects from the same panel. The reservation carries its own lifecycle and shows up in the item's history, so a piece of equipment that is out on loan cannot be silently double-booked.

Roles and access

Authentication, profiles and role-based permissions separate what the team can do from what the rest of the campus can. Authorization is enforced server-side on every privileged operation, never only in the UI that renders it.

Access history and sessions

A full audit trail of cabinet openings and material usage, plus a session timeline view — who used what, when, and for how long.

Admin dashboard

KPIs plus five analytics tabs (overview, inventory, maintenance, operations, reservations) built on Recharts, with a data fallback so a failing analytics RPC degrades the numbers instead of taking the page down.

Maintenance

Items carry a maintenance record and history, so a tool that keeps coming back broken is visible as a pattern rather than as a series of unrelated incidents.

Technical Highlights

One cached resolver for the current user

The auth user + profile lookup is resolved once per request and cached, so a render tree that needs the user in the layout, the page and three components pays for exactly one lookup.

Actions return state, they don't throw

Every admin action returns a serializable result with its errors, field-level errors and success flag instead of throwing. Validation failures are data, not exceptions — which is what lets the same form component render field-level errors without a try/catch in the UI.

Read models composed in TypeScript

The data layer doesn't return raw rows: it composes an enriched view model out of several tables, so components render one typed object instead of stitching relations together in JSX.

Realtime as deltas, not refetches

The cabinet grid subscribes to change events and applies them as in-memory deltas. Two people working the same cabinet see each other's changes without either of them reloading.

One generic table for every admin module

A single generic table component carries filtering, sorting and pagination once; each module (cabinets, inventory, users, maintenance, reservations, activity, sessions) only declares its typed columns.

Impact and Scalability

  • Every material movement is traceable: who, what, when and for how long.
  • The hardware bridge is in production code, so wiring a new cabinet is a hardware task, not an application change.
  • The read/write split and the generic table make a new admin module mostly a matter of declaring schema, fetcher, action and columns.

Notes

Built with Next.js 16, Supabase (PostgreSQL, Auth, Realtime), MQTT, TanStack Table, Recharts and shadcn/ui. The repository is private — it belongs to the Centro de Prototipado at the National University of Colombia.

🖼️ IMAGE PLACEHOLDER — the cabinet grid on the home screen

🖼️ IMAGE PLACEHOLDER — the admin dashboard with its KPIs and analytics tabs

🖼️ IMAGE PLACEHOLDER — the inventory table with filters and PDF export

🖼️ IMAGE PLACEHOLDER — the access history / session timeline

🖼️ IMAGE PLACEHOLDER — a physical cabinet with its ESP32 lock


© 2026 Felipe Giraldo