CET 2026.04.21
Back to home

Case study

Ingram Micro CRM

Local-first desktop CRM I built solo for the Ingram Micro sales team — Next.js + Tauri, SQLite-backed offline-first sync with Microsoft Dynamics 365, Azure MSAL auth. In production use internally.

Role
Sole developer
Status
Private, in production at Ingram Micro
Stack
TypeScript Next.js 14 React 18 Tauri v2 (Rust) SQLite Zustand Radix UI + Tailwind CSS Azure MSAL (Entra ID) Microsoft Dynamics 365 Xvantage CLS
Timeline
~1.5 months

Overview

Ingram Micro CRM is a local-first desktop application for the Ingram Micro field sales team. It replaces a patchwork of slow web tooling with a single streamlined client for managing customer accounts, logging activities, tracking follow-ups, running pipeline reviews, and looking up invoices — with full offline support and two-way sync to Microsoft Dynamics 365.

Everyday surfaces include a Dashboard with a Belgium customer map and key counters, a Customers list with an automatic 0–100 health score per account, global Follow-Ups and Opportunities pages, a Revenue Overview (ARR) table with Excel export, an Analytics view across personal, pipeline, customer, and activity metrics, and a unified Timeline of every activity, follow-up, and deal across every account.

The problem

Field sales reps were spending too much of their day fighting their tools. The stock Dynamics 365 web interface is slow — especially on patchy connections at customer sites — and the data a rep actually needs to make a visit productive is scattered across D365, Xvantage CLS, and a handful of spreadsheets. Logging a single meeting meant clicking through several tabs, waiting for each to load, and then repeating the exercise the next time the same customer came up.

Fixing it wasn’t on anyone’s roadmap: this sat outside my assigned role and there was no internal budget for a CRM rebuild. I built it anyway because I was using the same tools my colleagues were complaining about, and a local-first client was the only realistic way to make the workflow feel instant — and to keep working when the Wi-Fi at a customer site drops.

Approach

The app is a Next.js 14 / React 18 frontend wrapped in Tauri v2 for the desktop shell. All data lives in a local SQLite database managed by Tauri’s Rust plugins; nothing reads straight from D365 at interaction time, so every click is instant regardless of network. Zustand holds UI and sync state, persisted so the app restarts into exactly where the user left off.

Sync is two-way and queue-based. A background pull hydrates customers, contacts, and opportunities from Dynamics 365; user-authored records — activities, follow-ups, opportunity edits, contact changes — go into a pending queue and get pushed on the next cycle. If a push fails, the item stays in the queue with its error and retries. The user can watch all of this from a Sync page with a live pending table and history log, and the whole app is fully usable with the network cable unplugged. Invoices come from a separate Xvantage CLS adapter, fetched on demand because that data is read-only.

I chose Tauri over Electron to get a small signed installer, a real auto-updater distributed through GitHub Releases, and proper access to the OS from Rust rather than Node — the kind of details that matter when you’re shipping a binary to a sales team on managed corporate laptops. Authentication runs on Azure MSAL with delegated permissions, so the app acts on behalf of the signed-in user and inherits whatever access they already have in the Microsoft tenant.

Screenshots

TODO: describe Ingram Micro CRM screenshot 1
TODO: caption for screenshot 1
TODO: describe Ingram Micro CRM screenshot 2
TODO: caption for screenshot 2
TODO: describe Ingram Micro CRM screenshot 3
TODO: caption for screenshot 3