DEV Community

Știuriuc Sorin-Marian
Știuriuc Sorin-Marian

Posted on

Modeling Romania's salary taxes in TypeScript: lessons from building salariile.ro

I spent the last few weeks building salariile.ro, a salary calculator for Romania. It sounds like a weekend project: take the gross salary, subtract three percentages, show the net. It was not. Here is what made it interesting, and what I would tell anyone who needs to model payroll or tax rules in code.

The domain is the hard part

Romanian salary math in 2026 looks simple on paper: 25% pension contribution (CAS), 10% health insurance (CASS), 10% income tax after deductions, plus 2.25% paid by the employer on top (CAM). The complexity hides in the details:

  • The personal deduction is not a constant. It is a curve that depends on income and the number of dependents, and it phases out completely above a threshold.
  • Meal vouchers are taxed differently from cash. CASS and income tax apply to their value, but the tax money is withheld from your cash salary while the full nominal value lands on the card. Many calculators get this subtly wrong, and people then wonder why the payslip does not match the estimate.
  • Sector rules (construction, agriculture) and the minimum wage facility change the formula depending on contract details.
  • The rules change constantly. The minimum wage changes again on July 1, 2026, and several thresholds are indexed to it.

My main takeaway: encode rules as data, not as ifs. Every fiscal period is a config object with rates, thresholds, deduction tables and links to the legal source. The calculation engine is a pure function from (config, input) to a payslip breakdown. When the July 2026 rules land, that will be a new config entry plus a set of tests, not a refactor.

Test against official examples

The Romanian tax authority publishes norms for Declaration 112 with worked examples. Every rule I implement gets a test case traced back to an official source, and where two sources disagree, a comment links the exact article of law I followed. For a YMYL topic this is the only thing that keeps the project honest.

The web part: boring on purpose

Next.js 16 App Router, React 19, TypeScript, deployed on Vercel. Server Components everywhere, with the calculator as the only real client component. No cookies, no ads, no tracking scripts. For search visibility the unglamorous things mattered most: correct JSON-LD (Person, FAQPage), a sitemap that actually updates, llms.txt for AI crawlers, and pages that each answer one question instead of one page trying to answer everything.

What surprised me

While researching the niche I found that the sites ranking top 3 for "calculator salariu" include one with almost zero backlink authority and another still showing rules that expired in 2024. In this niche, search engines seem to reward being current and precise more than raw link mass. Encouraging, if you are building something accurate.

The calculator is live at salariile.ro and I am happy to answer questions about modeling tax rules in TypeScript. It is a surprisingly fun domain once you accept the chaos.

Top comments (0)