DEV Community

Clarity With AI
Clarity With AI

Posted on Originally published at claritywithai.org

I Built a Free Remote-Work Tax Calculator Because Nobody Was Answering the Real Question

Cross-posted from Clarity With AI, where the original lives.

The problem

Someone takes a fully remote job, moves from a high cost-of-living state to a cheaper one, and two things happen to their paycheck at once:

Their employer applies a geographic pay-band adjustment (a base salary cut, commonly 5–20%)
Their state tax residency changes — which can raise or lower net pay depending on the two states

And because federal tax is progressive, a geo-pay cut that lowers gross salary can also drop the person into a lower federal bracket, partially offsetting the cut. Almost nothing online shows all three effects combined into one number.

So I built a small client-side tool to do it: Remote Work Out-of-State Tax & Salary Calculator. Vanilla JS, no backend, no dependencies, nothing leaves the browser.

The interesting part: why "just multiply by the top tax rate" is wrong

The first version of this tool (and most similar calculators I looked at) modeled state tax as:

js
var stateTax = grossIncome * topMarginalRate;

That's badly wrong for most incomes. If California's top rate is 9.3%, applying it flat to a $70k salary massively overstates the real bill — most of that income sits in California's 1–8% brackets and never touches the top rate.

I don't have full bracket tables for all 50 states (that's a lot of data to maintain accurately year over year), so instead I built a synthetic progressive curve scaled to each state's top rate:

js
var STATE_BRACKET_SHAPE = [
{ upTo: 20000, mult: 0.00 },
{ upTo: 50000, mult: 0.30 },
{ upTo: 100000, mult: 0.55 },
{ upTo: 250000, mult: 0.80 },
{ upTo: Infinity, mult: 1.00 }
];

function calcStateTax(grossIncome, topRate) {
if (!topRate) return 0;
var tax = 0;
var lowerBound = 0;
for (var i = 0; i < STATE_BRACKET_SHAPE.length; i++) {
var tier = STATE_BRACKET_SHAPE[i];
var amountInTier = Math.min(grossIncome, tier.upTo) - lowerBound;
if (amountInTier > 0) {
tax += amountInTier * (topRate * tier.mult);
}
if (grossIncome <= tier.upTo) break;
lowerBound = tier.upTo;
}
return tax;
}

Result on a $70k CA salary: the flat-rate model said ~$6,510 in state tax. The scaled progressive model says ~$1,860 — much closer to real-world effective rates. Still an estimate (not the actual published bracket table for every state), but it stops the tool from being wildly wrong for anyone under six figures.

FICA: don't forget the Social Security wage cap

The original version also applied a flat 7.65% FICA rate to all income. That's two components bundled together — 6.2% Social Security (which is capped at an annual wage base, ~$176,100 for 2026) and 1.45% Medicare (uncapped). Above the cap, only the Medicare portion should keep applying:

js
var SS_RATE = 0.062;
var MEDICARE_RATE = 0.0145;
var SS_WAGE_BASE_2026 = 176100;

function calcFICA(grossIncome) {
var ssWages = Math.min(grossIncome, SS_WAGE_BASE_2026);
return (ssWages * SS_RATE) + (grossIncome * MEDICARE_RATE);
}
Federal tax was already fine

Federal bracket math was already implemented correctly as real marginal calculation (loop through brackets, tax only the marginal amount in each), so no changes needed there — it's the reference implementation for how the state tax function should have worked from the start.

Try it / poke holes in it

Live tool here — no signup, fully client-side. If you spot a state where the synthetic bracket shape produces a number way off from the real published brackets, or you think of an edge case I'm not handling (local/city taxes, non-standard filing status, etc.), I'd genuinely like to hear it.

Top comments (0)