aryx.dev

Guides/005

Drone Lab Inventory System

deployed

A QR-based checkout platform that gave a drone lab full accountability for every asset it owns

logged
2026.07
timeframe
2026
role
Solo build — SAFCSP Drone Lab
stack
fastapipostgresqlreact 19vitedockerghcr + watchtowerqr/barcode scanning
source
The Drone Lab Inventory system showing the full asset list — codes, categories, locations, and availability
fig 01 — 87 units, 22 asset types, 9 categories — the real inventory, not a mockup

Why I built it

The drone lab holds high-value, safety-sensitive equipment — drones, cameras, sensors, LiPo batteries — spread across nine categories and multiple storage locations. Before this system, tracking it relied on memory and scattered notes: no reliable record of who took what, when it was due back, or how much was left on the shelf.

I built a QR-based platform to replace all of that. Every asset gets a permanent asset code and a QR sticker. A scan checks an item in or out in seconds; sensitive gear requires staff sign-off before it leaves; and every action is logged against a named user, a due date, and a signature.

It’s not a prototype. It’s loaded with the lab’s real inventory — 87 physical units across 22 asset types in 9 categories — and it’s been running in production since it shipped, on one dedicated lab PC with no cloud fees and no internet dependency.

The stack

bill of materials

itemqtynotes
FastAPI backend1Auth, asset codes, checkout/return logic, approvals, audit log — all REST.
PostgreSQL + SQLAlchemy/Alembic1System of record for every item, unit, user, and transaction.
React 19 + Vite frontend1Dashboard, checkout desk, inventory, and admin views.
QR generation + camera/hardware scanningper unitqrcode/Pillow on the backend; zxing-js and jsqr in the browser.
Docker Compose + GHCR1 stackBackend, frontend, and Postgres, built and published as images.
Watchtower1Polls GHCR every 5 minutes and redeploys the lab PC automatically.
Dedicated lab PC1Ubuntu + Avahi mDNS, reachable at inventory-server.local on the lab LAN.

The interesting constraint was self-sufficiency: everything runs on one Linux PC on the lab Wi-Fi, with no installs on anyone else’s device. Students and staff just open a browser to inventory-server.local — Avahi mDNS makes the hostname resolve on the lab LAN without any DNS setup. Docker Compose runs Postgres, the FastAPI backend, and the React frontend as three services; Watchtower polls GHCR for new images every five minutes and redeploys automatically, so pushing to GitHub is the entire release process.

One screen, total visibility

The dashboard turns “go check the shelf” into a glance: live counts, category breakdown, overdue loans, and pending approvals, all recalculated the instant anything is scanned.

Dashboard showing total, available, and checked-out units alongside inventory by category and a recent activity feed
fig 02 — Total, available, checked-out, and item-type counts, next to a named, timestamped activity feed
Dashboard category card showing a hover state with a category description
fig 03 — Category cards double as a quick reference — hovering surfaces what actually lives in each one

Every unit, accounted for individually

Each item carries a permanent asset code in the format TQ-{CAT}-{XXXXXX} — a lab prefix, a 2–6 letter category code set by an admin, and a random hex suffix guaranteed unique. High-value gear (drones, cameras, controllers) is tracked as individual serialized units, each with its own QR sticker and transaction history; consumables like batteries and cables are tracked as a pooled quantity instead.

Inventory table listing assets with asset codes, categories, locations, availability, condition, and status
fig 04 — 22 asset types, 87 units, searchable by asset code, name, or serial — filterable by status, category, and location

Scanning a unit’s QR code resolves straight to its detail page, but the lookup isn’t locked to the system’s own codes — an item can also be found by an external/IT barcode, a manufacturer part number, or a unit serial. That flexibility mattered the first week: half the existing gear already had someone else’s asset tag on it.

Check gear out in seconds

The checkout flow is built around scanning, not forms. Browse or search inventory, build a cart, and complete a checkout by scanning — a phone camera, a webcam, or a USB/Bluetooth hardware scanner all work interchangeably, with continuous multi-scan on any page.

Live camera scan adding a unit to the checkout cart by reading its QR code from a phone screen
fig 05 — Scan anywhere in frame — a unit's QR code adds it to the cart the moment the camera reads it

Once the cart is built, staff select the borrower, set a due date, add notes, and capture a digital signature on-screen before confirming.

Confirm checkout modal showing the unit, borrower, and due date before completing the transaction
fig 06 — Confirmation before it's final — unit, borrower, and due date, one last check before it leaves the shelf

Checkout generates a downloadable PDF receipt with the signature and asset codes attached. Returns work the same way in reverse: scan or look up the unit, log its condition as Good / Needs Repair / Damaged, and availability restores automatically.

Sign-off and access, built in

Sensitive gear doesn’t move without approval. Admins can flag a category — Drones, for example — as “Requires Approval,” and nothing in it can leave without staff sign-off: the request lands in a dedicated approvals queue, the item is reserved for the borrower while staff review it, and they approve or deny from there.

Access itself is role-based:

Role What they can do
Student Browse inventory, request checkouts, view their own loan history, update their profile.
Staff Everything a student can, plus process check-ins, manage inventory and categories, approve requests, view all transactions.
Admin Everything staff can, plus manage user accounts, locations, and the full audit log.

A permanent record of every movement

Nothing leaves or returns without a trace. Every checkout and return is tied to a specific student, staff member, or admin, stamped with the exact time it happened, and searchable in a filterable transaction log — by borrower, item, or date, down to the minute. Every change to inventory records is logged and visible to admins in a full audit trail.

Set up once, runs itself

The system is engineered to keep running with no babysitting: no installs on any client device, no manual maintenance, and no lost data.

  • Zero-install access — everyone else just opens a browser to inventory-server.local. Nothing to install anywhere but the lab PC.
  • 24/7 LAN access — available on the lab network from any browser, any time, with no dependency on an internet connection.
  • Self-updating deployment — pushing code to GitHub rebuilds the images and Watchtower redeploys the lab PC automatically, no on-site maintenance required.
  • Automated backups — the database backs up daily and is retained for 14 days, with no manual step.

That reliability bar is what separates a demo from a system a lab can actually depend on: one that survives a reboot, updates itself, and never loses its records.

What it’s worth

The value isn’t the software — it’s what stops going wrong once it’s in place.

Before: stock levels lived in people’s heads and scattered notes, there was no record of who borrowed what or when it was due, anyone could walk off with high-value gear with no sign-off, and lost or overdue items went unnoticed for weeks.

After: live counts across all 87 units, always current; every loan tied to a named user, a due date, and a signature; sensitive categories require approval before anything leaves; overdue loans and pending approvals surface on the dashboard; and the whole thing runs on one lab PC with zero installs, daily backups, and self-updating deploys.

What I’d do differently

  • Design the approval queue for scale from day one. It works well at the lab’s current volume, but the reservation logic while a request sits in review is the part I’d revisit first if checkout volume grew.
  • Add condition photos earlier. Damage is currently a status field (Good / Needs Repair / Damaged) with a notes box — a required photo on anything marked damaged is next on the roadmap, and it should have shipped with the first version.
  • Build the maintenance queue as part of the return flow, not after it. Right now a damaged return is just a flag; turning it into an open/resolved repair ticket automatically is planned next, and bolting it on after the fact means touching the return path twice.

Planned next: NFC tap-to-approve for staff, a per-drone flight log captured on return, required damage photos, an automatic maintenance queue, quarterly 9-point safety inspections, and a checkout receipt reformatted to match the lab’s official custody form.