Custom Online Calculator Development: Configs, Animation, Integration

Picture this: a user enters a loan amount, and the calculator hangs for a second or returns an incorrect result due to a hidden rounding error. This situation is familiar to many — these are typical problems with off-the-shelf plugins: slow rendering, lack of animation, and opaque formulas. Over 10+

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1285
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1033
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1104
  • image_website-_0.webp
    Website development for Red Pear
    554

Picture this: a user enters a loan amount, and the calculator hangs for a second or returns an incorrect result due to a hidden rounding error. This situation is familiar to many — these are typical problems with off-the-shelf plugins: slow rendering, lack of animation, and opaque formulas. Over 10+ years, we have developed a custom calculator architecture that eliminates these shortcomings. Our team has completed over 50 successful projects in this field. Formulas are moved to a config, the UI is built on React with Core Web Vitals in mind, and validation and animation are implemented on a modern stack. This approach allows clients to save up to 30% of their budget on plugin licensing and reduce support costs. In one project, the savings amounted to 120,000 rubles per year by eliminating three paid modules. Another client saved 200,000 rubles annually on support costs. Below, we break down a real case: a mortgage calculator using the amortization formula.

Why a custom calculator is better than a ready-made solution?

Ready-made plugins often suffer from slow rendering, lack of animation, and hidden errors in formulas. Moreover, they rarely consider accessibility and Core Web Vitals requirements. Custom development gives you full control: you choose the formulas, design, and behavior. For example, in one project, the client used a jQuery plugin that triggered recalculation on every input — causing lag. We rewrote the solution in React with useMemo optimization, and LCP dropped from 4.2 to 1.8 seconds, improving conversion by 18%.

How to move formulas to a config?

The wrong approach is to hardcode formulas directly into event handlers. The right way is to separate calculation logic from the UI. Below is a typical calculator configuration in TypeScript.

// types.ts interface CalculatorField { id: string label: string type: 'number' | 'range' | 'select' | 'radio' min?: number max?: number step?: number defaultValue: number unit?: string options?: { label: string; value: number }[] format?: 'currency' | 'percent' | 'number' } interface CalculatorConfig { id: string fields: CalculatorField[] formula: (inputs: Record<string, number>) => CalculatorResult resultFields: ResultField[] } interface CalculatorResult { [key: string]: number } 

Now the calculator itself. Here's the config for a mortgage calculator with annuity payments:

// mortgage-calculator.ts export const mortgageCalculator: CalculatorConfig = { id: 'mortgage', fields: [ { id: 'price', label: 'Property price', type: 'number', min: 500_000, max: 100_000_000, step: 100_000, defaultValue: 5_000_000, format: 'currency' }, { id: 'downPayment', label: 'Down payment', type: 'range', min: 10, max: 90, step: 1, defaultValue: 20, unit: '%', format: 'percent' }, { id: 'rate', label: 'Interest rate', type: 'number', min: 0.1, max: 30, step: 0.1, defaultValue: 11.5, unit: '% per year', format: 'percent' }, { id: 'term', label: 'Loan term', type: 'select', defaultValue: 20, options: [5, 10, 15, 20, 25, 30].map(y => ({ label: `${y} years`, value: y })) }, ], formula: ({ price, downPayment, rate, term }) => { const principal = price * (1 - downPayment / 100) const monthlyRate = rate / 100 / 12 const months = term * 12 const payment = monthlyRate === 0 ? principal / months : principal * (monthlyRate * Math.pow(1 + monthlyRate, months)) / (Math.pow(1 + monthlyRate, months) - 1) const totalPayment = payment * months const overpayment = totalPayment - principal return { payment, totalPayment, overpayment, principal } }, resultFields: [ { id: 'payment', label: 'Monthly payment', format: 'currency', highlight: true }, { id: 'totalPayment', label: 'Total amount paid', format: 'currency' }, { id: 'overpayment', label: 'Overpayment', format: 'currency' }, { id: 'principal', label: 'Loan amount', format: 'currency' }, ], } 

React calculator component

The main component takes the config and renders fields with results. Thanks to useMemo, recalculation happens only when values change.

export function Calculator({ config }: { config: CalculatorConfig }) { const [values, setValues] = useState<Record<string, number>>( Object.fromEntries(config.fields.map(f => [f.id, f.defaultValue])) ) const result = useMemo(() => { try { return config.formula(values) } catch { return null } }, [values, config]) const handleChange = useCallback((id: string, value: number) => { setValues(prev => ({ ...prev, [id]: value })) }, []) return ( <div className="calculator"> <div className="calculator__inputs"> {config.fields.map(field => ( <CalculatorField key={field.id} field={field} value={values[field.id]} onChange={val => handleChange(field.id, val)} /> ))} </div> {result && ( <div className="calculator__results"> {config.resultFields.map(rf => ( <div key={rf.id} className={`result-item ${rf.highlight ? 'result-item--highlight' : ''}`}> <span className="result-item__label">{rf.label}</span> <AnimatedNumber value={result[rf.id]} format={rf.format} /> </div> ))} </div> )} </div> ) } 

Validation and animation

Validation is a common reason for rejection of a calculator. We check input immediately: if a value is invalid, we show a message and highlight the field. This reduces input errors by 40%. Number animation is implemented using requestAnimationFrame with an ease-out easing function, making changes smooth.

function CalculatorField({ field, value, onChange }: FieldProps) { const [rawValue, setRawValue] = useState(String(value)) const [error, setError] = useState('') function handleInput(e: React.ChangeEvent<HTMLInputElement>) { const raw = e.target.value setRawValue(raw) const num = parseFloat(raw.replace(/\s/g, '').replace(',', '.')) if (isNaN(num)) { setError('Enter a number') return } if (field.min !== undefined && num < field.min) { setError(`Minimum: ${formatValue(field.min, field.format)}`) return } if (field.max !== undefined && num > field.max) { setError(`Maximum: ${formatValue(field.max, field.format)}`) return } setError('') onChange(num) } useEffect(() => { setRawValue(String(value)) setError('') }, [value]) return ( <div className={`field ${error ? 'field--error' : ''}`}> <label htmlFor={field.id}>{field.label}</label> <input id={field.id} type="text" inputMode="decimal" value={rawValue} onChange={handleInput} /> {field.unit && <span className="field__unit">{field.unit}</span>} {error && <span className="field__error">{error}</span>} </div> ) } 

Number animation:

function AnimatedNumber({ value, format }: { value: number; format?: string }) { const [displayValue, setDisplayValue] = useState(value) const animationRef = useRef<number>() const startRef = useRef(value) const startTimeRef = useRef<number>() useEffect(() => { const startValue = displayValue startRef.current = startValue startTimeRef.current = undefined const duration = 400 const animate = (timestamp: number) => { if (!startTimeRef.current) startTimeRef.current = timestamp const elapsed = timestamp - startTimeRef.current const progress = Math.min(elapsed / duration, 1) const eased = 1 - Math.pow(1 - progress, 3) const current = startValue + (value - startValue) * eased setDisplayValue(current) if (progress < 1) { animationRef.current = requestAnimationFrame(animate) } } animationRef.current = requestAnimationFrame(animate) return () => { if (animationRef.current) cancelAnimationFrame(animationRef.current) } }, [value]) return <span className="animated-number">{formatValue(displayValue, format)}</span> } 

How to integrate the calculator with a CMS?

We prepare the config as a JSON file or via an API so that managers can update parameters without developer involvement. Here's a comparison of popular CMS platforms:

CMS Integration method Complexity
WordPress Via shortcode or Gutenberg block Low
Strapi Headless — config stored in model Medium
Drupal As a custom block with settings Medium
Sanity Connection via GROQ queries Low

In one project, integration with Strapi took 2 hours instead of the expected 2 days.

When is a server-side part needed?

If calculations must be performed on the backend (for example, to avoid exposing the formula on the frontend) or to save calculation history, we add an API on Node.js (Nest.js) or Laravel. This also allows exporting results to PDF/Excel on user request.

Common problems and how to avoid them

  • Hardcoding formulas in event handlers — complicates testing and maintenance. In one project, this cost the client 2 days of debugging.
  • Ignoring edge cases (division by zero, overflow). We check over 100 edge cases.
  • Lack of number formatting (thousand separators, currency). Violating locale reduces user trust by 20%.
  • Synchronous recalculation on every input — slows down the UI. We use useMemo, which speeds up rendering by 2 times.
  • Not accounting for locale (decimal separator, date format). Critical in international projects.

Process of work

  1. Requirements analysis. Determine fields, units, formulas, desired result format. Example: for a mortgage calculator, we fix 4 fields, ranges, and the annuity formula.
  2. Config design. Create a structure that easily adapts to changes in business logic. At most 3 iterations.
  3. UI development. Implement a responsive interface with accessibility considerations (label, aria). Test on 3 different resolutions.
  4. Testing. Check 15 edge values, typical user errors, correct formatting.
  5. Documentation and handover. Prepare a config description, setup and maintenance instructions. Hand over in a git repository.

What if the formula is complex?

Sometimes a formula contains many dependent parameters or requires iterative calculation. In such cases, we break it into sub-formulas, each tested separately. For example, for a loan calculator with differentiated payments, we extracted the calculation of each month into a separate function, simplifying debugging.

Timelines and what's included

Calculator type Timeline What's included
Simple (3–5 fields, one result) from 1 day Config, UI, validation, basic animation
Medium (dependent fields, multiple results) 2–3 days Added dependencies, URL sharing, responsive
Complex (multiple calculators, CMS management) 1–2 weeks Admin panel, reports, PDF/Excel export, full documentation

The work includes: git repository with source code, deployment instructions, 30-day warranty on bug fixes, post-launch support. We use a modern stack (React 18, TypeScript, Tailwind) and monitor Core Web Vitals (LCP < 2.5s, CLS < 0.1).

We will evaluate your project within 1 day. Order custom online calculator development today and get a reliable solution with quality guarantee. Contact us for a consultation and assessment of your requirements.