Unit converters are everywhere online, but they all seem to either require an account, run ads that cover half the screen, or send your input to a server for no reason. I built one that runs entirely in your browser, with no dependencies, no tracking, and no round-trips.
👉 https://unit-converter-dev.pages.dev
Seven conversion categories, 70+ units, real-time bidirectional conversion:
| Category | Example units |
|---|---|
| Length | |
| mm, cm, m, km, in, ft, yd, mi, nmi, light-year | |
| Weight | |
| mg, g, kg, t, oz, lb, st, short ton | |
| Temperature | |
| °C, °F, K, °R | |
| Volume | |
| ml, l, m³, fl oz, cup, pint, quart, gallon, tbsp, tsp | |
| Area | |
| mm², cm², m², km², ha, acre, ft², in², mi², yd² | |
| Speed | |
| m/s, km/h, mph, ft/s, knot, Mach | |
| Data | |
| bit, byte, KB/KiB, MB/MiB, GB/GiB, TB — both SI and binary |
Features:
Most unit conversions are linear: multiply by a factor to get to the base unit, divide by another factor to get to the target. The approach:
function convert(catKey, fromUnit, toUnit, value) {
const base = toBase(catKey, fromUnit, value); // → base unit
return fromBase(catKey, toUnit, base); // base unit → target
}
function toBase(catKey, unit, value) {
const u = CATEGORIES[catKey].units[unit];
if (u.toBase) return u.toBase(value); // non-linear (temperature)
return value * u.factor;
}
Temperature is the classic non-linear case. You can't just multiply to convert between Celsius, Fahrenheit, and Kelvin — you need offset arithmetic:
temperature: {
units: {
C: {
toBase: v => v + 273.15, // °C → K
fromBase: v => v - 273.15, // K → °C
},
F: {
toBase: v => (v - 32) * 5/9 + 273.15, // °F → K
fromBase: v => (v - 273.15) * 9/5 + 32, // K → °F
},
K: { toBase: v => v, fromBase: v => v },
R: { toBase: v => v * 5/9, fromBase: v => v * 9/5 },
}
}
The data category includes both SI prefixes (1 KB = 1000 bytes) and binary prefixes (1 KiB = 1024 bytes). Both are represented with the same factor-based approach, just stored as separate units:
data: {
units: {
kB: { factor: 8e3 }, // Kilobyte = 8000 bits
kiB: { factor: 8192 }, // Kibibyte = 8192 bits (= 8 × 1024)
mB: { factor: 8e6 }, // Megabyte = 8,000,000 bits
miB: { factor: 8388608 }, // Mebibyte = 8,388,608 bits (= 8 × 1024²)
// ...
}
}
The tricky part is displaying results cleanly. 1.6093440000000001
is ugly; 1.609344
is what you want. toPrecision(10)
then parseFloat
removes trailing zeros while keeping enough precision:
function formatNum(n) {
if (!isFinite(n)) return '';
if (n === 0) return '0';
const abs = Math.abs(n);
if (abs >= 1e-3 && abs < 1e13) {
return parseFloat(n.toPrecision(10)).toString();
}
return n.toExponential(6); // very large or very small → scientific notation
}
165 tests, all passing, using only Node.js assert
:
§1 Length conversions (17 tests)
§2 Weight conversions (12 tests)
§3 Temperature conversions (13 tests)
§4 Volume conversions (11 tests)
§5 Area conversions (10 tests)
§6 Speed conversions ( 9 tests)
§7 Data conversions (12 tests)
§8 formatNum (15 tests)
§9 convert edge cases ( 8 tests)
§10 Roundtrip conversions (13 tests)
§11 Category structure (12 tests)
§12 Known reference values (13 tests)
§13 Additional coverage (20 tests)
Highlights from the test suite:
-40°C = -40°F
(the only point where Celsius and Fahrenheit are equal)0 K = -459.67°F
(absolute zero)1 mi = 5280 ft = 1760 yd = 1.609344 km
1 GiB = 1024 MiB = 8589934592 bits
👉 https://unit-converter-dev.pages.dev
Part of devnestio — a collection of free, zero-dependency developer tools that run entirely in your browser.