All Projects
UI/UX Design Web Development Systems Engineering 2024

Sprintex
Calculator

Interpolation-Driven Product Selection Engine

UI / UX Design Web Dev Systems Architecture 2024
Client Sprintex
Year 2024
Timeline 6 Weeks
Role UI/UX Designer & Developer
TL;DR

I designed and built a product selection tool that reduced Sprintex's engineering workflow from 40 minutes to under a minute — and ensures every sales inquiry arrives with full technical specs pre-filled, automatically.

40 min → <1 min 100% leads pre-qualified <300ms interaction No backend needed
97% Faster product
selection
100% Leads arrive with
pre-qualified specs
<300ms Input-to-result
render time
0 Backend servers
required

Sprintex manufactures high-speed centrifugal air compressors for hydrogen fuel cells, wastewater aeration, and industrial e-boosting. Their product line spans dozens of models, each defined by complex performance curves that shift across RPM, flow rate, and pressure differentials. Engineers and OEMs needed a way to navigate that complexity instantly — without reading spec sheets, calling support, or doing math by hand. I was brought in to design and build the system from scratch.

00 — Business Goals

What Success
Had to Look Like

G.01

Self-Service Lead Qualification

Sales inquiries arrived with no technical context — just a name and email. Every lead required a follow-up call before anyone knew what product was actually needed. The goal: every inbound inquiry arrives with flow rate, pressure, RPM, and product model pre-attached. Zero manual qualification overhead.

G.02

Eliminate Pre-Sales Engineering Time

Engineers were spending 20–40 minutes per standard inquiry doing manual cross-referencing against printed spec tables. The tool had to make that loop unnecessary — so engineering time is reserved for complex, non-standard applications only a human can solve. Not for looking up numbers.

G.03

Technical Brand Positioning

Sprintex competes in a market where precision is the primary differentiator. A publicly accessible, interpolation-driven calculator signals engineering credibility before a sales conversation starts. The tool itself is a positioning statement — it shows what the company believes about how products should be specified.

00 — Constraints

Built
Within
Reality

Every architectural decision was shaped by real constraints — not hypothetical ones. These six defined what was possible before a single line of code was written.

  • C.01
    Client-Side Only

    No server, no database. All computation runs in the browser from a static JSON data file. Zero infrastructure overhead, zero latency from a round trip.

  • C.02
    Engineering Accuracy

    Output had to match Sprintex's verified physical data, not approximate it. Interpolated values were validated against known data points before the UI was built.

  • C.03
    Sub-300ms Interaction

    Every input change had to re-render results imperceptibly fast. Perceptible lag in a decision tool breaks trust. Target: <300ms from keystroke to full render.

  • C.04
    Non-Technical Users

    The tool is operated by sales reps, not engineers. No spec knowledge required. The interface had to surface technical precision without exposing technical complexity.

  • C.05
    Large, Irregular Dataset

    30+ product models, each with multi-dimensional performance curves measured at non-uniform RPM intervals. Interpolation had to handle irregular spacing without degrading accuracy.

  • C.06
    CRM via Form Bridge

    No custom API endpoint available. Lead data had to reach the CRM via WordPress's existing Fluent Forms setup — injected programmatically, not submitted through a dedicated backend.

01 — The Problem

The
Challenge

Sprintex's product data is inherently non-linear. Each blower model has performance curves measured at discrete RPM intervals — but engineers need predictions at any operating point, not just the ones in the dataset. When a user enters a flow rate and pressure that falls between two data rows, a simple lookup returns nothing useful. That gap was the core technical problem.

Compounding this: different products have different curve shapes. The interpolation logic couldn't be a one-size-fits-all formula — it had to operate across a two-dimensional space (pressure × flow), handle irregular data spacing, and produce engineering-grade accuracy. At the same time, results had to render in under 300ms and stay readable on any device.

The existing workflow was entirely manual: engineers cross-referenced printed spec tables, rounded their inputs to the nearest data row, then called the sales team to confirm. Every selection took 20–40 minutes and frequently produced sub-optimal recommendations. The system I was hired to replace wasn't a tool — it was an absence of one.

The gap, in minutes

Before
Review printed spec sheets manually ~5 min
Cross-reference multiple data tables ~10 min
Round inputs to nearest available row ~5 min
Call sales team to confirm selection ~15 min
Total 20–40 min
After
Enter flow rate & pressure values ~10 sec
Calculator finds best-fit product instantly <0.3 sec
Review live performance chart & specs ~30 sec
Submit — CRM receives pre-qualified specs instant
Total <1 min
Main UI screen — 1400×880 — replace with screen-main.jpg
My Process

How I Architected It

01 Data Modeling

Audited Sprintex's raw dataset — RPM curves, pressure tables, and flow ranges across every model. Identified the structure needed for two-dimensional interpolation and normalized the data into interpolation-ready JSON.

02 Interpolation Architecture

Designed the two-level spline engine: first interpolating across pressure at fixed RPMs, then across flow bands. Validated output accuracy against known data points before hooking it into the UI.

03 State System Design

Built a centralized selection state object that drives all UI panels — result card, performance chart, energy module, and form pre-fill — with zero direct DOM coupling between components.

04 UI Design & Build

Designed the full interface in Figma, then built it in vanilla JavaScript modules. Chart.js renders live performance curves on every input change. Integrated into WordPress via Fluent Forms for CRM lead capture.

05 QA & Launch

Stress-tested edge cases — boundary inputs, out-of-range values, zero-pressure entries. Deployed with localized energy pricing for global markets. The tool replaced all manual selection workflows from day one.

My Role
Data Architecture & Normalization Interpolation Engine Design State Machine & Event System JavaScript Module Development Chart.js Visualization UI/UX Design (Figma) WordPress Integration CRM Form Bridge
02 — Solution

The
System
I Built

At its core, the Sprintex Calculator is an interpolation-driven selection engine. The user enters two values — flow rate and pressure — and the system computes precise RPM and power predictions using two-level cubic spline interpolation across Sprintex's full product dataset.

“This isn’t a lookup table. It calculates.”

The interpolation operates in two dimensions simultaneously: first resolving performance at each fixed RPM tier across the entered pressure, then resolving across flow bands to find the optimal operating point. Both levels use Numeric.js for matrix computation, producing engineering-accurate outputs even when the input falls between every row in the dataset.

All output panels — the result card, the live performance curve chart, the energy savings comparison, and the pre-filled inquiry form — are driven from a single selection state object. Input changes propagate through an event system. Components observe state; they don't talk to each other. This architecture made the system easy to extend and impossible to desync.

When a user's input falls outside all product ranges, fallback logic scores proximity across every model and surfaces the nearest viable match with a contextual warning. No dead ends. The tool always gives an answer — and tells you what it assumed.

03 — Architecture

Under the Hood

The calculator is six interconnected systems working as one. Each handles a distinct concern — from raw math to UI rendering to CRM data injection — and none of them are coupled directly to each other. Here's how the engine actually works.
sys / 001 Two-Level Spline Interpolation Engine

The selection core. For a given pressure input, the engine first interpolates performance values at each RPM tier using cubic splines. It then interpolates across those RPM results against the entered flow rate — returning an accurate operating prediction for any point in the product's physical envelope.

problem Performance data is discrete — measured at fixed RPM intervals. Engineers need predictions between rows, not just at them.
decision Two-level cubic spline: first interpolate across pressure at each RPM tier, then interpolate across flow bands to resolve the operating point.
tradeoff Heavier computation than a lookup table. Accepted for engineering-grade accuracy across the full operating envelope — not just at measured points.
cubic-spline Numeric.js 2D interpolation matrix-solve
sys / 002 Real-Time Performance Chart Renderer

Chart.js renders live performance curves on every valid input change. Datasets are pre-processed and cached per product ID on first load. The user's operating point is plotted as an overlay on the matching curve — giving engineers an instant visual of where they sit on the efficiency map.

problem A numerical recommendation without visual context left engineers uncertain about where they were operating relative to the efficiency curve.
decision Chart.js scatter overlay on the live performance curve, with datasets pre-processed and cached per product ID on first render — not on every input change.
tradeoff Chart.js adds ~230KB to the bundle. Justified by eliminating the support calls that previously asked "is this input in range?"
Chart.js canvas rendering dataset cache scatter overlay
sys / 003 Centralized Selection State Machine

A single state object holds the current selection result. All UI panels — result card, chart, energy module, form fields — are observers. When inputs change, one state update dispatches to every panel simultaneously. No component speaks directly to another. No desync possible.

problem Early prototypes had chart, result card, and form pre-fill communicating via direct function calls. Adding the energy savings module broke three existing connections.
decision Single state object as the source of truth. All panels are observers — one input change dispatches to all simultaneously. Components never speak directly to each other.
tradeoff Slightly more upfront architectural overhead. Eliminated every class of sync bug permanently — and made every new panel a one-line subscriber, not a wiring project.
observer pattern event dispatch decoupled modules single source of truth
sys / 004 Fallback & Boundary Selection Logic

When user inputs fall outside the operating envelope of all products, a proximity scoring pass ranks every model by distance from the entered point. The nearest viable match is surfaced with a contextual warning state — so the tool always returns a useful answer, never a dead end.

problem Out-of-range inputs returned nothing. Users couldn't learn from an edge case — they simply hit a wall with no guidance on what to try next.
decision Proximity scoring ranks all products by Euclidean distance from the entered point. Nearest viable match surfaces automatically, with an explicit contextual warning state.
tradeoff The recommended product may not be the true optimum. Mitigated by the warning state, which tells the user exactly what was assumed and why.
proximity scoring range clamping warning state graceful fallback
sys / 005 Memoized Computation Cache

Interpolated curve results are computed once per product per session and stored in a keyed Map. Subsequent selections of the same product retrieve pre-computed values instantly — making repeat interactions effectively free and keeping the UI responsive even across the full product dataset.

problem Re-running cubic spline calculations on every input change across 30+ models would make the interface feel sluggish — particularly on mobile or lower-end hardware.
decision Keyed Map stores computed curve data per product ID on first selection. All subsequent interactions retrieve pre-computed values in sub-millisecond time.
tradeoff Session memory grows proportionally with products viewed. Acceptable given the bounded dataset size — no product was ever evicted from cache during a real session.
memoization Map keyed cache sub-ms lookup session scope
sys / 006 CRM Form Bridge & Lead Injection

On every selection, the state machine writes flow rate, pressure, RPM, power draw, and product model into hidden Fluent Forms fields via a form hook. When the user submits an inquiry, the CRM receives fully pre-qualified specs — not just a name and email.

problem No custom API endpoint was available. Lead data had to reach the CRM without a dedicated backend — the only option was the existing WordPress form infrastructure.
decision State machine writes flow, pressure, RPM, power, and model ID directly into hidden Fluent Forms fields via DOM injection on every selection update. Form submission carries full specs automatically.
tradeoff Tight coupling to Fluent Forms field IDs. Documented as a known dependency — migrating to a different form plugin requires updating the bridge map, not the state machine.
hidden field bridge Fluent Forms hook pre-qualified lead CRM injection

// Selection data flow

User Input
flow + pressure validated on change
Validate
range check clamp to envelope
Dataset Lookup
cache → JSON memoized per id
Spline Interpolate
2-level cubic 2-pass matrix solve
Score & Rank
proximity delta fallback if OOB
State Update
dispatch to all single source of truth
Render + CRM
chart · card · form observer chain

// Performance targets & methodology

Target <300ms Input-to-render latency Memoized spline cache + debounced input handler eliminates re-computation on every keystroke
Budget ~290KB Total JS (unminified) Chart.js ~230KB + Numeric.js + custom engine — loaded deferred, non-blocking page paint
Strategy 0 req Network calls at interaction Full product dataset pre-loaded in JSON on page init — zero API calls during selection, zero latency from network
Loading Deferred Script execution order Calculator JS loads after DOM paint via defer — page content renders immediately, tool initialises in background
05 — Input Intelligence

Why It
Never
Dead-Ends

Most product selectors fail silently — enter an out-of-range value and you get a blank screen with no guidance. The Sprintex Calculator was architected to eliminate that entirely. Eight fallback layers fire in sequence, each handling a different failure mode, until a useful answer is always returned.

Users never see the chain. They just never hit a wall.

F.01
Exact Match → instant result, no math
F.02
Interpolation → estimated operating point
F.03
Near-Match ±20% → closest viable option
F.04
Single Field → auto-fills the other field
F.05
Blank-State Auto-Fill → pre-fills both from BEP
↳ Always running in parallel
F.06 · State Memory F.07 · Validation Guard F.08 · Popup Feedback
Search Layer // fires on every search, in sequence
F.01
Exact Match Conditional

If your numbers land exactly on a measured data point, the result is returned immediately — no interpolation, no estimation. Skips every subsequent layer.

Fires when: both inputs exactly match a data row
F.02
Interpolation Engine Conditional

When your input falls between two measured points, the engine runs two-level cubic spline interpolation to estimate exactly what the blower would do there. Engineering-grade results for any point in the operating envelope — not just the ones the dataset happened to measure.

Fires when: input lands between dataset values
F.03
Near-Match ±20% Conditional

If no product covers your exact values, the search expands to ±20% tolerance on both axes — surfacing the nearest viable options instead of an empty screen. Results are tagged "Close Match" so you always know what the system assumed.

Fires when: no product covers the entered range
Input Layer // how fields behave based on what you fill in
F.04A
Pressure Only Conditional

Enter a pressure value, leave flow blank. On card select the calculator reads the product's best operating point and fills flow automatically. Your pressure is never touched on product switch.

Fires when: pressure entered, flow is blank
F.04B
Flow Rate Only Conditional

Enter just the flow rate and the calculator auto-fills pressure from the product's BEP data. Useful when flow is the fixed constraint and pressure is flexible. Same preservation rule applies.

Fires when: flow entered, pressure is blank
F.05
Blank-State Auto-Population Conditional

When a product card is selected with both fields empty, the calculator reads that product's best-efficiency operating point and pre-fills both inputs. The tool always shows a meaningful, working state — never blank fields with no context.

Fires when: both fields are empty on card select
F.06
State Memory Always On

Switch between products freely and anything you typed stays locked. Only auto-filled fields update on card switch. The system tracks which values are user-entered versus auto-populated and treats them differently — a distinction most tools don't make at all.

Always active during product switching
Guard Layer // always-on protection running silently in the background
F.07
Validation Guard Always On

The min and max on both fields aren't hardcoded — they're computed dynamically from the full product dataset at load time. It's impossible to type a value no product supports. Invalid inputs can't reach the interpolation engine or produce NaN errors.

Always active — validates every input change
F.08
Popup Feedback Always On

After each search or card action, a contextual notification explains what happened — exact match found, estimate generated, close alternative shown, or nothing available. No silent failures. No wondering why the result is different from what you expected.

Fires after every search and card selection

Tech Stack

Figma
Vanilla JS (ES6+)
Chart.js
Numeric.js
WordPress
Fluent Forms
Custom JSON Data Layer
Data Layer

Built to
Scale

The calculator's product data is a single structured JSON file — one object per model. Each object defines the model ID, operating envelope bounds, and a nested array of RPM tiers, each holding measured pressure/flow/power point pairs. The interpolation engine is schema-driven: it reads the file at runtime and builds the full selection dataset dynamically. No hardcoded product logic anywhere in the codebase.

// products.json — simplified schema (one product object)
{
  "id":       "SPX-22HFCs",
  "envelope": { "flowMin": 20, "flowMax": 340, "pressMax": 1.8 },
  "curves": [
    { "rpm": 15000, "points": [
        { "flow": 20,  "pressure": 1.6, "power": 4.2 },
        { "flow": 80,  "pressure": 1.4, "power": 3.8 },
        // ... more measured points at this RPM tier
    ]},
    { "rpm": 20000, "points": [ /* ... */ ]}
  ]
}

Adding a new product requires one new JSON object matching the schema. The engine detects it on next page load — no code changes, no deployment beyond updating the file.

Irregular curve spacing is supported natively. RPM tiers and measurement points don't need to be uniform across models. The spline engine adapts to whatever spacing the physical data provides.

Roadmap: A WordPress admin interface to manage product JSON from the dashboard — removing the need for file access and making product updates possible for non-technical team members.

Engineering & Design Thinking

Tradeoff Analysis

Decision 01

Why two-level interpolation instead of a lookup table or single-axis spline?

Blower performance is defined by two independent axes: pressure and flow rate. A single-axis spline could handle one dimension, but it would lose accuracy on the other. A lookup table would require exact data matches — useless for the 95% of real-world inputs that fall between rows. Two-level cubic interpolation was the only approach that gave engineering-grade accuracy across the entire operating space without requiring a pre-computed grid.

Decision 02

Why a centralized state machine instead of direct component communication?

Early prototypes had the chart, result card, and form pre-fill talking directly to each other via function calls. Adding the energy savings module broke three things. Centralizing all output into one state object made the system fundamentally extensible — new panels just subscribe to state. It also made debugging trivial: one place to inspect, one place to update, zero sync bugs.

Decision 03

Why build an energy savings module in a product selector?

Industrial blower purchases are financial decisions, not just technical ones. By adding a localized savings comparison — factoring annual runtime, electricity pricing by country, and blower type — the tool gives sales teams an instant ROI argument. The selection system selects the right product. The energy module sells it. They share the same state, so they always agree.

split-1.jpg — Input screen (empty state)
split-2.jpg — Live results + chart
split-3.jpg — Result card + specs
split-4.jpg — Energy savings module
fullwidth-1.jpg — Full-page horizontal strip — 1920×960
04 — Result

The
Outcome

“We no longer guess specs or send the wrong blower. Everything’s aligned now — from engineering to sales.”

Sprintex Engineer

The calculator eliminated the manual selection workflow entirely. Engineers get accurate results in seconds instead of 20–40 minutes. Sales inquiries arrive with flow rate, pressure, power draw, and product model already attached — the team acts on specs, not on guesses.

What started as a product selection tool became a core business system: it qualifies leads, reduces support overhead, and positions Sprintex as a technically credible, engineer-first brand. Upcoming roadmap includes PDF performance report export, multi-language support, and CRM analytics dashboarding.

View the live calculator
detail-wide.jpg — Desktop full layout — 1920×816
detail-left.jpg — Mobile + Desktop mockup — 1200×675
detail-right.jpg — Performance chart detail — 1200×675
What This Shows

How I
Work

This project is the clearest demonstration of how I operate at the intersection of design and engineering — and why that combination produces something neither discipline achieves alone.

“Great interfaces hide their complexity. The harder the math, the simpler the UI has to feel — especially when your users are selling, not engineering.”
Design Thinking

Translating Complexity

A system backed by matrix algebra and cubic spline math presents as a two-field form. Understanding what users actually need — and aggressively hiding everything they don't — is what made that possible.

Engineering Ownership

End-to-End Delivery

I researched the data model, designed the interpolation algorithm, built the UI, wired the CRM bridge, and shipped it. Solo. Not just the screens — the entire product. That kind of scope is only possible when design and engineering fluency genuinely overlap.

Product Intuition

Beyond the Brief

The energy savings comparison module wasn't in the original scope. I added it because I recognized the difference between a technically correct tool and a commercially persuasive one. The feature that gets the deal signed isn't always the one in the spec.

Next Project See All Work UI/UX Design · Web Development · App Design