myKaarma · 2026 · Case study · 8 min
RecLink is the recommendation-and-estimate tool a service advisor works from on the shop floor, and the part of ServiceCart most often called confusing. I rebuilt it as a working prototype: Good/Better/Best pricing tiers, itemised parts and tire sales on a single estimate, with every change traced through the three screens that render the same data.
Pricing
1 → 3price tiers per recommendation, tagged in the shop's own vocabulary
Surfaces kept in sync
3advisor, technician and parts views of the same data
Shipped
19commits, each with the reasoning written in
Regression
40browser-driven test scripts written along the way
If you only read one section: what I decided the world how it was built against the live tool what happened differently
01 · The world
A multi-point inspection produces a list of recommendations. The technician edits them, the advisor prices and presents them, and the parts counter sources what gets approved. myKaarma shows each of those people a different tab, but the tabs are all rendering the same underlying record.
That is what made the project interesting and what made it dangerous. A change that reads correctly on the advisor's tab has to stay correct on the other two. Most of the bugs in this story were only visible by holding two tabs next to each other.
Scoped on purpose
The real screen carries a lot of operational chrome. The prototype deliberately leaves it behind so the estimate model could be iterated fast, in one file, without dragging the rest of the app along for every change.
02 · How it was built
I designed in the live prototype with an AI pair-engineer rather than in static mocks. Every change moved through the same loop: a specific note, sometimes a screenshot with an arrow at the exact pixel, implemented directly, verified in a headless browser, committed with the reasoning written out.
feature and fix commits, each with its reasoning in the message
parallel initiatives on isolated branches
automated browser-driven regression scripts
console errors tolerated in a shippable state, checked every time
03 · What I decided
Each change below traces one idea through every place the data already lived. The pattern repeats: a first pass that looked right in one tab, caught by comparison with another.
Decision 1 · Pricing
Every recommendation could only ever carry a single price. The estimate section gained a proper multi-option mode: a tab strip of priced alternatives, each with its own labour, parts and tags, tagged against the shop's real vocabulary (Recommended, On your car now, Good, Better, Best, Best warranty, OEM, Aftermarket) with multi-select.
One option is always the default the customer sees first. It's tracked by its own id, not its tab position, so it survives a tab being reordered or deleted, and there's an explicit "Make default" control rather than leaving it implicit.
An early review surfaced a second bug by accident: a leftover coach-mark overlay dimmed the whole estimate panel every time an existing rec was opened. Fixed in the same pass.
Decision 2 · Parts
A dealer can keep the simple flat "parts estimate $" field, or switch the whole shop to line-by-line itemised parts. The toggle lives in the settings menu next to the existing Phase 1 / Phase 2 switch it actually relates to, not as a new piece of chrome.
Following the data further: pre-approved lines gained the same itemised option, with their total deferring to the itemised subtotal the moment it has real rows. And the Parts tab, previously a static mock that rendered two blank rows no matter what, got wired to the same real data with its own tab per pricing tier.
Decision 3 · New capability
The brief was simple to state and easy to get wrong: let an advisor add tires suggested from the vehicle's tread-depth readings, without inventing a parallel "tire card" system that the Parts tab, the customer total and the estimate maths don't know about. Every version kept one constraint: a selected tire becomes a normal itemised parts row.
The first version worked but invented its own interaction pattern. Once pointed at the mobile "Recommend Tires" screen the techs already use, it was rebuilt to mirror that directly: per-axle size and quantity, front/rear install pricing, real SKUs and rebates. Selecting a tire also seeds the ancillary parts a tire sale needs (valve stems, disposal fee, TPMS kit) so one choice produces a complete, editable ticket instead of one suspiciously round number.
Decision 4 · Interaction
The trickiest interaction problem was small. When front and rear tires differ, how does an advisor say which axle they're choosing for right now, versus see which axle already has a tire? The first pass tangled those into one value, so a button could read "selected" while describing the wrong thing.
They became two independent states: one drives the target button and where a catalogue click lands, the other drives whether an axle card renders as a dashed placeholder or a solid, priced block. Picking a front tire now hands targeting to Rear automatically, and the card control lets you switch back by hand.
Decision 5 · Tiers of complexity
RecLink already draws a line between a Phase 1 experience for simpler shops and a fuller Phase 2. Estimate Options were built as Phase 2. The first pass only hid the entry point for creating options; a rec that already carried saved options still rendered its full breakdown in Phase 1's lists, because the list view had its own ungated check.
Same pattern as the Pre-Approved bug in Edit MPI, which opened a plausible-looking modal with the wrong data because its click handler passed arguments in the wrong order and dropped a flag. Both were invisible in isolation and obvious by comparison.
Stripping colour out of the rows and only adding it back on headers and status was the last change, and the one people commented on most. Nobody said "it's calmer." They said "I can see what matters."
04 · Against the live tool
The real per-line editor is one unified modal for every status. Splitting it into a Recommendation editor and a Pre-Approved editor is what made room for tiering. The trade-offs are listed honestly, because the next step is closing them.
05 · What happened
Tested with dealerships and myKaarma's own customer-service staff, who have been asking when it ships. One test group responded poorly; the signal pointed at recent onboarding and change fatigue rather than the design, and didn't replicate. Reported as it is.
Shipped as
Working prototypeTiered pricing, itemised parts and tire sales on one estimate, across all three tabs, with 40 regression scripts protecting it. The thing people clicked in testing was the thing that would ship.
Dealers
Loved itin several pilot dealerships, especially the tier tabs.
Internally
"When?"Customer-service staff kept asking when it would go live.
Test groups
[n]dealerships in usability testing; one poor result, not replicated.
Iterations
100sof design iterations across several directions before the build.
Methods: user interviews, usability tests, research review of support tickets and dealership visits, Playwright regression on every change. Figures in brackets are for Ruth to confirm.
06 · Differently
I'd have written the cross-surface check before the first feature, not after the first bug. Every defect in this project had the same shape: correct in one tab, wrong in another. A script that opens the same rec in all three tabs and diffs what it sees would have caught the Pre-Approved and Phase 1 bugs before anyone did.
I'd also have started the tire flow from the techs' mobile screen on day one instead of designing a fresh pattern first. The rebuild cost a day; the comparison to the real reference was the design.
And I'd have asked the test group that struggled what else had changed for them that month, before reading their results as a verdict on the screen.
Sections 05 and 06 are drafts in Ruth's voice to confirm or rewrite. Screens are from the prototype and from myKaarma's live tool; the live-tool screens may need redacting before publishing.