Today I decided to switch focus away from hardware for a bit and spend some time improving my own internal business processes for managing my workshop. I’ve been meaning to do this for a while, but I’ve never quite seemed to find the time.

So today I decided to start work on a small software-based inventory system for my equipment.

I currently work across two locations: one where I mainly do design and development work, and another where I tend to do more testing and building. With equipment regularly moving between the two, keeping track of where everything is located can occasionally become a problem.

The recent disappearance of my PICkit — with a replacement now on order — made me realise that I could probably do with a better inventory management system in general.

Perhaps, if it proves useful for me, it might eventually be useful for other small workshops and businesses as well.

Keeping It Simple#

The idea is deliberately quite simple.

I’m not trying to build a replacement for a full ERP or MRP system. Instead, I want a clean and fast way of keeping track of equipment, materials and project-related items.

I regularly move tools and equipment between locations and occasionally forget where I last left something. The result is wasted time searching through boxes, shelves and workspaces for something I know I own.

If I can remove even some of that friction, the system will have achieved its main purpose.

The system is initially based around two main entities:

  • Containers
  • Items

Containers can contain other containers, while Items represent the physical things being stored and tracked.

Containers#

A Container represents any physical location capable of containing something else.

For example, a Container could represent:

  • A warehouse
  • A room
  • A rack
  • A shelf
  • A bin
  • A box
  • A toolbox
  • A vehicle

Containers can themselves belong to another Container, allowing the system to represent a hierarchy of physical locations.

For example:

Workshop
└── Shelving Unit A
    └── Shelf 2
        └── Component Box 4

The initial properties for a Container will probably look something like this:

  • Id - A unique identifier for the container, most likely a UUID.
  • ParentContainerId - The Id of the parent container, if one exists.
  • Name - The name of the container.
  • Description - A description of the container.
  • Type - A string used to categorise the container.
  • Code / Barcode / QR - A unique code used to identify the container when scanning it.
  • Metadata - A JSON object that can store additional information about the container.

The initial Container types will probably include things such as warehouse, room, rack, shelf, bin, box and vehicle, although additional types can easily be added later.

Items#

An Item represents something that is physically stored inside a Container.

This could be:

  • A tool
  • A piece of test equipment
  • A component
  • A material
  • A consumable
  • Almost any other physical item worth keeping track of

The initial properties for an Item will probably be:

  • Id - A unique identifier for the item, most likely a UUID.
  • ContainerId - The Id of the Container currently holding the item.
  • SKU - An optional stock keeping unit or product identifier.
  • Code / Barcode / QR - A unique asset or scanning code for the item.
  • Name - The name of the item.
  • Description - A description of the item.
  • Quantity - The quantity of the item held in the container.
  • Unit - The unit of measurement used for the quantity.
  • Metadata - A JSON object containing additional information about the item.

Separating the SKU from the unique scanning code should also allow the system to handle both individual assets and bulk stock.

For example, a PICkit programmer might be represented as an individual Item with a quantity of one and its own unique QR code.

A box containing 500 10 kΩ resistors, on the other hand, could be represented as a single Item with a quantity of 500 and a common SKU.

Nested Containers#

One of the useful consequences of allowing Containers to contain other Containers is that the location of everything inside them can be inferred automatically.

For example:

Vehicle
└── Toolbox
    └── PICkit

The PICkit only needs to know that it is inside the Toolbox.

The Toolbox then knows that it is inside the Vehicle.

If I move the Toolbox from the Vehicle into the workshop, I don’t need to update the location of every individual item inside it. Moving the parent Container effectively moves everything contained beneath it in the hierarchy.

That should make the system considerably easier to use in practice.

Keeping a Movement History#

Another feature that seems worth including fairly early is a simple history of movements.

The current location tells me where something is supposed to be, but it could also be useful to know where it was previously located and when it was moved.

A movement record could initially contain something along the lines of:

Item or Container
From Container
To Container
Timestamp

This would allow the system to answer questions such as:

  • Where is my PICkit?
  • Where was it before that?
  • When was this toolbox moved into the vehicle?
  • When was this equipment last seen in the workshop?

I don’t necessarily need to build a sophisticated history interface immediately, but recording the information from the beginning should make it much easier to add later.

Software Architecture#

With the basic model in mind, I decided to build a small C# API for managing the inventory.

The overall architecture should remain fairly straightforward:

                  ┌── Desktop Application
                  │
PostgreSQL → .NET Minimal API ── Android Application
                  │
                  └── MCP Server

PostgreSQL will provide the backend database and will initially run as a container on one of my mini PCs.

On top of that I’ll build a .NET Minimal API providing the basic REST-based CRUD operations for Containers, Items and their movements.

The API can then act as the common backend for several different interfaces.

Desktop and Mobile Clients#

The first proper user interface will probably be a desktop application built using Avalonia.

That should give me a relatively lightweight cross-platform desktop client while allowing me to remain in the .NET ecosystem.

If I get as far as building the Android application, I’ll probably use .NET MAUI.

The mobile application is potentially one of the more useful parts of the system because a phone already provides everything needed to scan QR codes while physically moving equipment around the workshop.

Entity Framework Core#

I’ll also be using Entity Framework Core as the ORM, with the Npgsql provider for PostgreSQL, along with EF Core’s migrations functionality.

This should make it considerably easier to evolve the database schema as the application develops.

This is a completely greenfield application, so I don’t have an existing database schema or compatibility requirements to worry about. Being able to change the model and generate migrations as the design develops should therefore be quite useful.

MCP and AI Integration#

Another interface I’m interested in experimenting with is an MCP server.

Rather than AI integration being the core purpose of the system, MCP would simply provide another way of interacting with the same inventory data.

An AI assistant could potentially query the system with questions such as:

Where is my STM32 programmer?

How many ISO1430s do I have?

What's currently stored in the test workshop?

What equipment is in the vehicle?

Which box contains the STM32 development boards?

That could make the inventory considerably easier to search without requiring every possible query to be explicitly implemented in the user interface.

The Actual Goal#

I don’t intend to make this overly complicated.

There are plenty of directions it could eventually expand into — projects, purchasing, suppliers, Bills of Materials, stock forecasting and so on — but doing all of that would rapidly turn this into an ERP system.

That’s not what I need.

For the first version, success is much simpler.

If I can put a QR code on a piece of equipment, scan it, scan the box I put it in, scan the shelf, vehicle or room where that box is stored, and then reliably find that equipment again several weeks later, the system will already have done its job.

For now, that’s enough.