SaaS · Inventory management

ShelfIt: an inventory SaaS that survives other people's spreadsheets

A multi-tenant inventory platform for Enigmex Technologies: folders, plan quotas, concurrent editors, and bulk spreadsheet imports that fail politely.

The story behind

The platform's database is Firestore, and Firestore cannot search text. No LIKE, no contains, no full-text index. The fix is decided at write time: every item name is broken into a token array and stored alongside the record, so a search is an indexed lookup instead of a scan, batched ten ids at a time around the query limits. The database never got faster. The questions got better.

The other half of the work was bulk import, because inventory arrives as a spreadsheet and spreadsheets arrive wrong. A 624-line validator checks every row against field limits, duplicate folders, and the customer's plan quotas, and when a file fails, the system writes the errors into a copy of the spreadsheet, highlights them, and hands it back. It is the politest failure mode we have shipped. Deletes are just as careful: a trash bin with restore, emptied by a scheduled Durable Functions orchestration instead of a hopeful cron job.

Business value

  • Ops teams import thousands of rows in one file instead of typing them in.
  • A failed import comes back as a highlighted spreadsheet, not a support ticket.
  • Plan tiers enforce themselves; quotas live in the data layer, not in a PDF.

Project scope

  • The Azure Functions backend, twelve endpoints with Durable orchestrations.
  • The XLSX import and export pipeline, validation included.
  • Search indexing and chunked queries over Firestore.
  • Roles, per-folder access control, and concurrent-editor counters.
  • Trash, restore, and scheduled cleanup.

Deliverables

  • Twelve .NET Azure Function endpoints on the isolated worker model.
  • An import validator and a styled XLSX writer as a shared library.
  • Angular panel features across six lazy-loaded modules, about 71 components.
  • A Firestore data model spanning eleven collections.

Tech stack

Angular 11TypeScript.NET 8Azure Functions v4Durable FunctionsGoogle FirestoreFirebase FunctionsSendGridPollyExcelJS

Frequently asked

The product is retired. Why is it on your case study list?

Because the engagement was real and the engineering outlives the product. The client's five-star review is public on our Upwork profile, and the site's years of operation are verifiable in the Internet Archive. Products get retired for business reasons; the patterns we built there still ship in our work today.

Why keep Firestore if it cannot search?

It was the platform's existing database, with live customers on it. The honest job was making it fast, not replacing it: a token index computed at write time costs nothing to query and nothing to migrate. Swapping the data layer would have been a bigger invoice for the same user experience.

Our bulk import keeps corrupting data. Is this fixable?

Usually, and the fix is rarely glamorous. Validate before you write, check quotas and duplicates row by row, and give the user their own file back with the problems marked. Most import pain is a missing validation layer, not a broken database.

Azure Functions and Firebase together. Why both?

Because real systems are inherited, not designed from scratch. Firestore was the source of truth; the heavy lifting (bulk operations, orchestrated cleanup, Excel generation) wanted .NET. We added the Azure layer where it earned its place and left the rest alone. Integration over rewrite, the same call we make in healthcare.

Have a workflow that needs this?

Tell us the shape of the problem. Scoped estimate, usually within 3 to 5 business days. No card, no obligation.

Estimate this buildor email business@highcraft.io