CRM

Custom CRM Platform

Drop the platform screenshot
ASP.NET Core
React
SQL Server
Azure
Microsoft Graph
Client
Northfield Instruments
Engagement
Project, then retainer
Duration
14 weeks
Users
62 across 3 sites

The problem

Northfield sells and services laboratory instruments. Sales and service are the same relationship to the customer, and were two entirely separate systems internally — a licensed CRM for the pipeline, a service desk for maintenance contracts, and no link between them.

An engineer visiting a site could not see the account was mid-renewal. A salesperson quoting a new instrument could not see three unresolved service tickets. Both teams built spreadsheets to compensate, and neither trusted the other numbers in the Monday meeting.

The trigger was a lost renewal worth about eleven percent of annual recurring revenue, on an account with an open complaint nobody in sales had seen.

Constraints we designed around

Four years of history

Deduplicating accounts across two systems with inconsistent naming took longer than building the pipeline module.

Engineers work offline

Site visits happen in basements. The service view had to function without a connection and reconcile afterwards.

No retraining budget

Sixty-two people had to move systems without formal training, which shaped every interface decision.
Drop the architecture diagram

Architecture

One ASP.NET Core application with a single customer record at its centre. Sales and service are views over the same account, not separate entities that sync — the integration problem was the actual problem, so we removed it rather than automating it.

The offline service view is a local-first React client with a queued write model; conflicts surface to the engineer rather than resolving silently. Calendar and email flow through Microsoft Graph, so activity logs itself.

Outcome

One record
Sales and service see the same account. The Monday meeting argues about strategy rather than whose number is right.
2 spreadsheets
Retired, three months after launch. That was the real measure of adoption, not login counts.
94% renewal
Up from 87% the prior year. Attribution is imperfect and they would say the same — but nobody has lost a renewal to an unseen ticket since.

What we would do differently

We built the offline service view in week nine. It should have been week two — it was the feature with the most unknowns and the least precedent in our own codebase, and discovering that late compressed everything after it. Highest-uncertainty work belongs early, and we knew that.

Sales and service on different systems?

Send us how the two teams hand over today. We will map what one record changes.

Request similar solution