Skip to content

ADI-2707/Stockyard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

67 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“¦ Stockyard

Offline-first desktop inventory tracker for panel & body manufacturing component tracking.

Built with Electron, React, and a local SQLite database β€” no server, no internet connection, no monthly bill. Just fast, indexed, reliable inventory control that lives on the shop floor's own machine.

Platform Electron React TypeScript SQLite License


Overview

Stockyard was built to replace manual spreadsheet reconciliation for tracking physical components on a manufacturing floor β€” panels, body parts, fasteners, sub-assemblies β€” with a single-file, installable desktop application that works entirely offline. It reduced manual reconciliation effort by up to 66% by moving stock counts, low-stock alerts, and bill-of-materials coverage checks out of shared spreadsheets and into a real, indexed, transactional database with a purpose-built UI.

It runs as a native Windows desktop app: double-click, no login, no cloud dependency, no internet required. All data lives in a single SQLite file on the machine it's installed on.


Why it exists

Spreadsheet-based inventory tracking on a manufacturing floor breaks down in predictable ways:

  • No enforced structure β€” two people can name the same SKU differently, or overwrite each other's edits.
  • No real audit trail β€” "who took the last 10 units, and when?" has no good answer.
  • No automatic alerting β€” stockouts get discovered when someone walks to the shelf, not before.
  • No fast lookup β€” searching a 5,000-row spreadsheet by SKU or location is slow and error-prone.

Stockyard solves each of these directly: every stock change is a recorded transaction (not an overwritten cell), every search hits an indexed SQL query instead of scanning rows in memory, and a background engine continuously watches stock levels so shortages surface automatically instead of being discovered on the floor.


Features

πŸ“‹ Inventory management

  • Full component catalog with SKU, name, category, quantity, unit, location, cost per unit, supplier, and free-form notes.
  • Configurable low-stock threshold and optional max stock per item, with category-level aging windows (flag components that haven't moved in N days).
  • Soft-delete support β€” items are archived, not destroyed, so historical transactions stay intact.
  • Barcode scanner support out of the box: keyboard-wedge scanners are detected by keystroke timing (fast bursts terminated by Enter), distinguishing a scan from normal typing without any special hardware driver.

πŸ“ˆ Live dashboard

At-a-glance KPI cards β€” total SKUs, out-of-stock count, low-stock warnings, aging components, and total inventory valuation β€” plus a critical-shortages table so the most urgent items are always visible first.

πŸ”” Background alert engine

A scheduled job (interval configurable in Settings) continuously scans inventory and raises alerts with severity levels:

Alert type Severity Trigger
OUT_OF_STOCK Critical Quantity reaches zero
LOW_STOCK Warning Quantity falls at/below the item's threshold
AGING Info No recorded movement within the category's aging window

Alerts can be acknowledged (snoozed) or resolved, and trigger native OS notifications so a shortage doesn't sit unnoticed in a background window.

🧾 Full transaction ledger

Every stock change β€” receipt, issue, adjustment, or initial count β€” is written as an immutable transaction row with the quantity delta, the quantity before the change, the operator who performed it, and an optional reference (PO number, build name). Nothing is ever silently overwritten.

🧩 Bill of Materials (BOM)

Define BOM templates (a named list of components + required quantities) and instantly check coverage β€” how many complete units can be built right now given current stock β€” without manually cross-referencing the inventory sheet.

πŸ“€ Exports & operational tooling

  • One-click CSV export (native OS save dialog) for inventory, transactions, or alert history.
  • One-click raw .sqlite database backup.
  • Factory reset / wipe for a clean slate on a new install.

Architecture

Stockyard follows a multi-process local client–server pattern β€” the same shape as a web app's frontend/backend split, just running entirely on one machine. This keeps the UI thread free of database work and keeps filesystem/database access out of the (sandboxed) renderer entirely.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       RENDERER PROCESS (React UI)     β”‚
β”‚  - Captures filters and input search   β”‚
β”‚  - Debounces input state (250ms)        β”‚
β”‚  - Renders paginated data tables          β”‚
β”‚  - Sandboxed: no direct filesystem access  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
                   β”‚  Asynchronous IPC Bridge (contextBridge, contextIsolation: true)
                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       MAIN PROCESS (Node.js)           β”‚
β”‚  - Receives IPC requests (API gateway)  β”‚
β”‚  - Handles file I/O (CSV export, backup) β”‚
β”‚  - Runs the background alert engine       β”‚
β”‚  - Fires native OS notifications           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚
                   β”‚  Drizzle ORM β†’ indexed SQL queries
                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       SQLITE DATABASE (single file)    β”‚
β”‚  - better-sqlite3, synchronous, in-process β”‚
β”‚  - Indexed on sku, name, category, location, β”‚
β”‚    deletedAt, createdAt                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core design decisions

  1. Process isolation. The renderer runs contextIsolation: true, nodeIntegration: false, sandbox: true. It has zero direct filesystem or Node.js access β€” every operation crosses through a typed preload.ts bridge into ipcMain handlers in the main process. A compromised or buggy UI can't touch the database or disk directly.
  2. Server-side filtering & pagination. Search, category filters, and status calculations run as SQL in SQLite, not as array filtering in React state β€” results are paged with LIMIT/OFFSET (100 rows/page) to keep memory flat regardless of catalog size.
  3. Indexed reads. Explicit indexes on the columns actually used for filtering and sorting (sku, name, categoryId, location, deletedAt, createdAt) keep lookups fast even as the transaction ledger grows into the tens of thousands of rows.
  4. Debounced input. Search inputs debounce at 250ms client-side before dispatching a query, avoiding a database round-trip on every keystroke.
  5. Background scheduled services. The alert engine runs on a timer inside the main process (independent of whether a UI window has focus), so alerts stay current even if the user is on a different tab.
  6. Append-only transactions. Stock changes are never in-place updates to a "current quantity" field alone β€” every change is logged as a new transactions row with a before/after delta, making the transaction ledger a true audit trail.

Tech stack

Layer Technology Purpose
Desktop shell Electron 31 Cross-platform native desktop runtime
Frontend UI React 18 + TypeScript Component-based renderer
Build system Vite 5 + vite-plugin-electron Bundling & hot-reload for both processes
State management Zustand 4 Lightweight global store (inventory, alerts)
ORM Drizzle ORM + drizzle-kit Type-safe schema, queries, and migrations
Database SQLite via better-sqlite3 Synchronous, in-process, single-file storage
Charts Recharts Dashboard visualizations
Icons Lucide React Icon set
Packaging electron-builder (NSIS) Windows installer generation

Data model

Five tables, fully typed end-to-end via Drizzle's inferred select/insert types:

Table Purpose
categories Component categories, each with a configurable aging window (days) and a UI badge color
items The component catalog β€” SKU, quantity, threshold, location, cost, supplier, soft-delete flag
transactions Append-only stock movement ledger β€” type, quantity delta, before-quantity, operator, reference
alerts Generated by the alert engine β€” type, severity, active/acknowledged/resolved state
bom_templates / bom_items Named BOM configurations and their required component quantities (composite PK)

Inter-Process Communication (IPC) API

All communication between the UI and the database goes through a fixed set of asynchronous IPC channels exposed via the preload bridge β€” effectively the app's internal API surface.

Categories
  • categories:getAll β€” fetch all categories
  • categories:create / categories:update / categories:delete
Items / Inventory
  • items:getAll β€” raw dump
  • items:getFiltered β€” paginated + filtered (used by tables)
  • items:searchAutocomplete β€” quick SKU/name lookup
  • items:getLocations β€” distinct warehouse/shelf locations
  • items:getSimpleList β€” minimal metadata (ID, SKU, name)
  • items:getById β€” full detail
  • items:create / items:update / items:delete
  • items:adjustStock β€” register a stock adjustment transaction
Transactions
  • transactions:getAll / transactions:getFiltered
  • transactions:getOperators β€” distinct operator list
  • transactions:getByItem β€” history for one item
Alerts
  • alerts:getActive / alerts:getResolved
  • alerts:acknowledge / alerts:resolve
  • alerts:updated β€” event fired when the background engine raises new alerts
Bill of Materials
  • bom:getAll / bom:getDetails
  • bom:create / bom:update / bom:delete
  • bom:checkCoverage β€” compare a BOM against current stock to compute buildable quantity
Export & Settings
  • csv:export β€” native save-dialog export to CSV
  • settings:getSchedulerInterval / settings:setSchedulerInterval
  • settings:runAlertScan β€” force an immediate scan
  • settings:backupDB β€” raw .sqlite file backup
  • settings:resetData β€” factory reset

Project structure

Stockyard/
β”œβ”€β”€ build/                     # App icons & packaging static assets
β”œβ”€β”€ dist-installer/            # Packaged Windows installer output (generated)
β”œβ”€β”€ drizzle/                   # SQL migrations (generated by drizzle-kit)
β”œβ”€β”€ electron/                  # Main process (Node.js)
β”‚   β”œβ”€β”€ database/
β”‚   β”‚   β”œβ”€β”€ connection.ts       # DB connection init + migration runner
β”‚   β”‚   β”œβ”€β”€ schema.ts            # Table schemas, indexes, inferred types
β”‚   β”‚   └── queries/               # Query handlers (items, transactions, alerts, bom, categories)
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ alertEngine.ts        # Stock-level scan β†’ alert generation
β”‚   β”‚   β”œβ”€β”€ scheduler.ts           # Interval-based background scheduling
β”‚   β”‚   β”œβ”€β”€ notifier.ts             # Native OS notification dispatch
β”‚   β”‚   └── csvExport.ts             # CSV export via native save dialog
β”‚   β”œβ”€β”€ main.ts                    # Entrypoint, window creation, IPC registration
β”‚   └── preload.ts                   # contextBridge β€” the only surface the renderer can call
β”œβ”€β”€ src/                        # Renderer process (React)
β”‚   β”œβ”€β”€ components/layout/       # App shell / navigation layout
β”‚   β”œβ”€β”€ hooks/                     # useInventory, useAlerts, useBOM, useScanner
β”‚   β”œβ”€β”€ lib/                         # Typed IPC client wrapper
β”‚   β”œβ”€β”€ pages/                         # Dashboard, Inventory, Transactions, Alerts, BOM, Settings
β”‚   β”œβ”€β”€ store/                           # Zustand stores (inventory, alerts)
β”‚   └── main.tsx                           # React bootstrap
β”œβ”€β”€ docs/                        # Technical specification
β”œβ”€β”€ package.json
└── tsconfig.json

Getting started

Prerequisites

  • Node.js β‰₯ 18
  • npm
  • Windows (current packaging target β€” see Platform support)

Development

# install dependencies
npm install

# run the Vite dev server + hot-reloaded Electron shell
npm run dev

Database

# generate a new migration after editing electron/database/schema.ts
npm run db:generate

# open Drizzle Studio to inspect the local database
npm run db:studio

Production build

# compile TypeScript and bundle optimized assets
npm run build

# package into a standalone Windows installer (.exe) β€” runs the build step automatically
npm run electron:build

The installer is emitted to dist-installer/.


Data storage

Stockyard stores everything in a single SQLite file inside the OS application-data directory β€” no external database, no network calls, and no telemetry:

OS Path
Windows C:\Users\<Username>\AppData\Roaming\stockyard\inventory.db

Use Settings β†’ Backup Database to copy this file out for safekeeping, and Settings β†’ Reset Data to wipe it and start clean.


Platform support

Current electron-builder configuration targets Windows x64 (NSIS installer) only, matching where it's deployed today. The Electron/React/Drizzle core has no Windows-specific code paths, so macOS/Linux targets could be added to electron-builder.config.js without core changes if ever needed β€” just untested today.


Security notes

  • Renderer runs fully sandboxed (sandbox: true, contextIsolation: true, nodeIntegration: false) β€” the UI cannot touch the filesystem, spawn processes, or access Node APIs except through the explicit, typed IPC surface documented above.
  • Operator names are trimmed and capped at 100 characters before being written to the transaction ledger.
  • All queries go through Drizzle's parameterized query builder β€” no raw string-concatenated SQL.

License

Internal tool β€” Β© Aditya Singh. Not currently published under an open-source license.

About

Material logistics, inventory tracking, and yard management system (YMS) to monitor stock status, warehouse allocations, and supply chain flow.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages