contractor-calcs
v1.7.0
Published
57 construction calculators as pure functions. Takeoff: roofing squares, concrete yards, framing, drywall, tile, siding, pavers, brick, block, rebar, gravel, asphalt, insulation, flooring, decking, stairs, piers, sheathing, pool, sod and generator sizing.
Maintainers
Readme
contractor-calcs
Fifty seven construction calculators as pure functions.
Takeoff: roofing squares, concrete yards, framing, drywall, insulation, tile, siding, pavers, brick, block, rebar, gravel, asphalt, flooring, decking, fencing, stairs, footings and piers, plywood sheathing, pool volume, sod, mulch and generator sizing. Money: markup versus margin, labor burden, hourly rate, overhead and profit, job cost, late fees, retainage and draw schedules. Trade: HVAC sizing, voltage drop, roof pitch and OSHA trench sloping. US contractor tax: self-employment tax, quarterly estimated tax and the mileage deduction. Mechanics lien deadlines for fifteen states, each one counting from the statute it names.
No dependencies, one file, MIT.
npm install contractor-calcsimport { compute } from "contractor-calcs";
const r = compute("roofing", { len: 40, wid: 30, pitch: 6, waste: 10 });
r.headline; // { label: "Roofing squares needed", value: "14.8", unit: "squares" }
r.rows; // the working, line by line
r.items; // the material list, ready for an invoiceWhy this exists
Most construction calculators are a widget on a page. This is the calculation on its own, separated from the page, so you can put it in your own estimating tool, your own app, or a spreadsheet exporter, and so the formulas can be read and argued with.
It is the same file that runs the calculators on contractorhandbook.com, byte for byte. That is deliberate. The worked example printed on each of those pages is generated at build time by this code, so a wrong formula shows up as a wrong number on a public page rather than hiding inside a widget.
The API
Five functions and two objects, and nothing is async.
import { slugs, fields, defaults, assumptions, compute, calcs, fmt } from "contractor-calcs";
slugs(); // every calculator name, sorted
fields("concrete"); // [{ id, label, unit, def, step?, min?, max? }, ...]
defaults("concrete"); // { len: 10, wid: 12, thick: 4, waste: 10 } - a working input on its own
assumptions("roofing"); // the prose behind the numbers: 3 bundles a square, and so on
compute("concrete", {}); // run it. Missing fields fall back to that field's default.
calcs; // the raw record, if you want to build your own UI
fmt; // the formatters the engine used: n, num, usd, pct, upcompute returns:
{
headline: { label: String, value: String, unit: String }, // the one number the answer is
rows: [{ label: String, value: String, hint?: String }], // the working
items?: [{ desc: String, qty: Number, rate?: Number }], // material or payment list
warn?: String, // when an input is out of range
}Every value comes back formatted as a string, with thousands separators and a currency or
unit where one belongs, because the common case is putting it straight on a screen or a
document. If you want raw numbers, parse them back, or read the formulas in
calc-engine.js, which is about 7,000 lines of plain arithmetic with nothing clever in it.
compute is pure. It does not mutate the object you hand it, it touches no globals, and the
same input always gives the same output. That is enforced by a test.
What is in it
Material takeoff
| Slug | What it answers |
|---|---|
| roofing | squares, bundles, underlayment, starter, ridge cap, drip edge, nails |
| concrete | cubic yards with waste, the quarter yard you order to, the 60 and 80 lb bag counts, plus rebar and form lumber |
| square-footage | area of one or many rooms, in feet, square yards and square meters |
| paint | gallons by coat, from the room perimeter, less the doors and windows, plus primer and tape |
| flooring | boxes at the box coverage you give it, plus underlayment and transition strip |
| deck | board rows across the width, linear feet of decking, boards at your stock length, joists and hangers |
| fence | sections, posts including one per corner and gate, rails, pickets, and the concrete per hole |
| drywall | sheets, screws, joint compound, tape and corner bead |
| insulation | cavity area after the framing factor is taken off, then bags at the coverage you give it |
| mulch | cubic yards at the depth you want, 2 cu ft bags, and the weight, for mulch, soil, stone or sand |
| gravel | gravel, crushed stone, sand or road base for a rectangle or a circle: compacted volume in place, the swell to loose yards, tons at the published weight or at your own ticket, and what one ton covers |
| roof-pitch | pitch to slope multiplier, to angle in degrees, to rise and run |
| stairs | riser count and height, treads, total run, minimum stringer length and headroom |
| asphalt | tons of hot mix at a compacted depth, plus base stone and tack coat |
| board-foot | board feet and linear feet for a lumber order |
| tile | tiles counted on the tile plus joint cell, thinset bags at the trowel the tile size needs, grout by joint volume, backer board |
| siding | squares net of gables and half the openings, cartons, starter strip, J channel and corner posts |
| paver | pavers counted on the paver plus joint cell, base gravel in yards and tons, bedding sand, polymeric sand by joint volume, edge restraint |
| brick | brick per square foot from the actual face plus the joint, six brick sizes, mortar bags, wall ties at code spacing, weeps |
| block | CMU count at 1.125 per square foot, mortar face shell bedded, grout by the cell spacing, vertical rebar, joint reinforcement |
| rebar | bars each way, linear feet, lap splices, sticks nested out of stock length, weight in pounds and tons, ties and chairs |
| framing | studs counted position by position, field studs, corners, tees, kings, jacks and cripples, plate stock, header stock, the one stud per foot rule printed alongside |
| pier | round piers or square pads, concrete both ways, sonotube nested out of a 12 ft length, form board for pads, vertical rebar, bearing at presumptive soil |
| sheathing | 4 by 8 sheets for a wall, roof or subfloor, nails off the real fastener schedule, H clips at wide spacing, house wrap, underlayment, subfloor adhesive |
| pool | gallons from a rectangle, round or oval shape, hose fill time, turnover pump flow, heater BTU, liquid chlorine off the trade percent definition, salt to 3,200 ppm |
| sod | pallets with the leftover printed, pieces at any slab size, delivered weight, topsoil to spread rounded to the whole yard, starter fertilizer, water for the first week |
| generator | starting watts with the surge counted once rather than twice, running amps, the next standard inlet and transfer switch rating, fuel burn and runtime by fuel |
Money
| Slug | What it answers |
|---|---|
| markup-margin | the two numbers people confuse, side by side, in both directions |
| labor-cost | burdened hourly cost: taxes, insurance, workers comp, benefits |
| hourly-rate | the break even rate and the rate with profit, from what you want to earn and how much of your week is billable |
| overhead-profit | overhead recovered, profit kept, the price that does both, and what that is as a markup |
| job-cost | material, labor hours, subs, equipment, permits, overhead and profit into one quotable price |
| late-fee | interest on an overdue invoice, and the annual rate it really works out to |
| retainage | earned to date, held on this application, due now, and what is still held at completion |
| draw-schedule | deposit, progress draws and final payment, net of retainage |
Trade
| Slug | What it answers |
|---|---|
| btu | cooling BTU, tons and furnace input by the square foot method, with both of its limits stated |
| voltage-drop | drop in volts and percent, the smallest conductor that holds 3 percent, and the longest run at the size you picked |
| trench-slope | the OSHA Subpart P cut back for the soil type, the width you have to open at the top, how far spoil and gear have to sit back, and the extra soil that sloping costs you |
Tax, for a US contractor
Rates are the published IRS figures for the year you pass in, and a mid year rate change is handled as two halves rather than averaged.
| Slug | What it answers |
|---|---|
| se-tax | self-employment tax on a net profit: the 12.4 and 2.9 percent halves, the social security wage base already used up by a W-2 job, Additional Medicare Tax, the Schedule 1 deduction, and what that is each quarter |
| est-tax | the safe harbor for quarterly estimated tax: 100 or 110 percent of last year against 90 percent of this year, whichever is smaller, less withholding, split across the four due dates with the ones already past called out |
| mileage | the business mileage deduction at the IRS rate, with commuting miles taken back out, a mid year rate change counted properly, parking and tolls added, and what it saves at your bracket |
Mechanics lien deadlines
Thirteen states. Each one asks what you are on the job, which day the clock starts from and what has already been served or recorded, then prints every date the statute gives you and names the section it counted from. Read the paragraph under Accuracy before you rely on a date from one of these.
| Slug | State | What it answers |
|---|---|---|
| az-lien | Arizona | the preliminary twenty day notice and what a late one actually covers, the claim of lien, the proof of mailing, and the suit with the lis pendens |
| ca-lien | California | ninety days from completion against the shorter window a recorded notice of completion opens, which of the two controls, and the preliminary notice behind both |
| fl-lien | Florida | notice to owner by day 45 counted from first furnishing, claim of lien by day 90 counted from last, the two different clocks side by side, and the one year suit |
| ga-lien | Georgia | notice to contractor by day 30, claim of lien by day 90, the copy to the owner, the action to commence, the 395 day date and the shortened clock a notice of contest starts |
| il-lien | Illinois | the 60 day occupant notice, the 90 day notice, the two different recording windows against a lender and against the owner, and what a written demand to sue does to the schedule |
| ma-lien | Massachusetts | notice of contract, statement of account and the ninety day suit, driven off a section 2A substantial completion or a section 2B termination, plus the thirty days a laborer gets |
| mi-lien | Michigan | notice of furnishing counted from the notice of commencement, the claim of lien, the copy you have to serve, the laborer wage notice and the year to foreclose |
| mn-lien | Minnesota | the 514.011 prelien notice by day 45 from the first item and the ten day notice an owner's contractor gives when there is no written contract, the 120 day lien statement from the last item, the year to assert the lien in court and the twenty days to answer, all counted under 645.15 and 645.151 with the 645.44 holidays, and the two optional ones left as your choice |
| mo-lien | Missouri | the ten day notice, the six month lien account counted honestly, the notice of rights before an intended sale, and the consent of owner an owner occupied remodel needs |
| ms-lien | Mississippi | the 85-7-407(2) thirty day notice, the 85-7-409(2) pre lien notice, the ninety day claim of lien, the copy out within two business days, and what happens when the last day is a closed day |
| ny-lien | New York | the filing window for a notice of lien, which is shorter on a single family home, plus serving the owner, filing proof of service, when the lien expires and how it is renewed |
| tx-lien | Texas | the Texas calendar, which counts months rather than days: the notice to the owner and original contractor, the post date behind it, retainage, the affidavit and the suit |
| ut-lien | Utah | the twenty day State Construction Registry notice and what a late one costs, the lien from final completion, the copy to the owner, and the residence lien recovery fund |
| wa-lien | Washington | the RCW 60.04.031 notice to owner and the sixty day reach back from the day it is given, the ninety day claim of lien, the fourteen day copy to the owner, eight calendar months to sue and ninety days to serve, the thirty-five day notice to a construction lender, all counted under RCW 1.12.040 with the state legal holidays |
| wy-lien | Wyoming | the 29-2-112 preliminary notice, the twenty day notice of intention, the lien statement window, the owner notice that follows filing, and a recorded extension agreement |
| ms-waiver | Mississippi | the sixty day clock a signed lien waiver starts, when the affidavit has to be filed, the copy to the owner and the amount at risk if it is missed |
The formulas that people get wrong
Roof area is not footprint. A 6/12 roof is sqrt(6² + 12²) / 12 = 1.118 times the
ground it covers, so a 1,200 sq ft footprint is 1,342 sq ft of roof. That multiplier is the
single most commonly skipped step in a roofing takeoff.
Markup is not margin. 50 percent markup on a $10,000 cost is a $15,000 price, and the margin on that price is 33.3 percent. A contractor who marks up 20 percent thinking it is a 20 percent margin is running a 16.7 percent margin, and that gap is most of the reason small builders go under profitable-looking jobs.
A monthly late fee is an annual rate. 1.5 percent a month is 18 percent a year, which is
the number a state usury cap is written against. The late-fee calculator prints it for that
reason.
A concrete bag yield is not its weight. A 60 lb bag yields about 0.45 cubic feet and an 80 lb bag about 0.60, so an 88 cubic foot pour is 196 or 147 bags. Below about a cubic yard bagging is cheaper; above it, it is a bad afternoon.
In a browser
There is no build step. calc-engine.js is a classic script and assigns window.__CALCS.
<script src="https://cdn.jsdelivr.net/npm/contractor-calcs/calc-engine.js"></script>
<script>
var r = window.__CALCS["deck"].compute({ len: 16, wid: 12, joist: 16 });
document.querySelector("#out").textContent = r.headline.value + " " + r.headline.unit;
</script>Bundlers can import "contractor-calcs" as normal.
Accuracy, and what this is not
These are estimating calculators. They give you a number to order against and a number to price against, and they are written to round the way a supplier counts, which means up.
They are not engineering. Nothing here sizes a beam, checks a load, or replaces a structural
calculation, a local code, or a manufacturer's installation instructions. Where a rule of
thumb is doing the work it is written down in assumptions(slug) rather than buried, so you
can disagree with it before you order.
The lien and tax calculators are arithmetic on a statute, not legal or tax advice. The fifteen state lien calculators count the days the statute gives you and name the section they counted from, and the tax ones apply a published IRS rate to a number you type in. A real deadline can still turn on a fact the calculator never sees: which contract you are actually under, when completion legally occurred, whether a notice was validly served, or a local rule about a day the courthouse is shut. Treat the date as the date to work back from, and confirm it with a lawyer or a CPA before you rely on it.
Tests
npm testThirty tests, node --test, no framework. They cover the shape of every calculator, that
each one survives its own defaults and a row of zeroes without producing NaN, that
compute is pure and deterministic, and then a set of pinned answers with the arithmetic
written out in a comment next to each. The pinned ones are the point: they are what catches
a formula changing by accident.
Contributing
Fixes to the arithmetic are the most welcome kind of issue, especially with a citation. If a waste factor, a bag yield or a coverage rate is wrong for how it is actually done in your trade, open an issue and say what it should be and why. Calculators for new trades are welcome too, with the same rule the existing ones follow: the assumptions get written down in plain English, or it does not go in.
calc-engine.js is a classic script on purpose so that the same file can run in a browser
tag and be evaluated by a static site generator. Please do not convert it to modules.
License
MIT.
