Skip to content
Anvil HUD

How we do the math

The math.

No black box. Anvil HUD runs three engines: a maker engine that prices a unit you make and sell (most of this page), a trade engine that builds a job bid bottom-up, and a digital engine that amortizes design time over a run. Here is every step each one takes between your inputs and “here is what to charge.”

Maker engine

Prices a unit you make and sell: material + machine + labor become a loaded cost, then a price with channel fees and shipping. Twelve crafts share it.

The maker math ↓

Trade engine

Bids a job bottom-up: line items, then general conditions, contingency, and overhead plus profit. No marketplace tail. Eighteen trades share it.

The trade math ↓

Digital engine

Amortizes one-time design time over the sales you expect, adds the channel fees (and POD base), then shows break-even units and projected profit.

The digital math ↓

The shape, before we get into it

Pricing anything you make is layered. Raw cost → buffered cost → suggested price. Each layer answers a different question:

material + machine + labor + packaging + the rest = raw

raw × (1 + failure%) × (1 + overhead%) = loaded

(loaded + flat fees) ÷ (1 − channel fee% − target margin%) = suggested price

Then we round to the nearest dollar (or whatever step you set). That's the headline number on the breakdown screen. The same shape prices every craft; only the raw lines differ. The walk-through below uses 3D printing as the worked craft; laser cutting, resin casting, candle making, soap making, vinyl cutting, and machine embroidery share everything from the failure buffer down and have their own sections at the end.

Material

Your slicer stamps the printed weight in the G-code header. Anvil HUD reads that and multiplies it by two waste factors:

grams × purgeMultiplier × wasteMultiplier × (spool$ ÷ spoolGrams)

Purge multiplier = 1 + (colors used − 1) × purge-per-color. Single-color prints pay zero purge tax. A two-color print at the default 12% per added color pays 12% more filament. Four colors → 36% more. Note: it's colors used, not loaded. We count non-zero entries in the per-extruder weight breakdown, not the AMS slot count.

Waste multiplier = 1 + slicer-invisible loss (default 2%). Skirts, brims, supports, dust in the spool. Things that happen even on a single-color print. If you track physical spools and weigh them now and then (Spools → Weigh & reconcile), Anvil measures your real drift rate — what the scale finds missing beyond the gcode — and the Waste % field in Settings shows it with a one-click fill. Like the learned failure rate, it is a signal: nothing changes until you apply it and save. Multi-color purge is never part of that number; the purge multiplier above already prices it.

Which spool$? A listing is priced before you know which color will print, and one listing usually covers every color you offer. So the listing price uses the average cost per gram across every active spool of the same material type (all your PLA spools, say), weighted by what you have actually been printing when there is recent history. The breakdown shows you that pool (how many spools, the average, and the cheapest-to-priciest range) right under the Material line, so the number is never a mystery. The job you actually print still costs its real spool: dashboards and inventory use the exact filament the job consumed.

Electricity

hours × (watts ÷ 1000) × rate$/kWh

The slicer stamps the print time. Watts come from your printer settings (default 95 W for the Bambu A1, 120 W for the Anycubic Kobra S1, both verified against manufacturer specs). Rate-per-kWh defaults to the US national average (~$0.106) but you should override it with your actual rate; some markets are triple this.

Machine depreciation

hours × (purchase$ + lifetime maintenance$) ÷ lifetime hours

Your printer is wearing itself out a tiny bit every hour it runs. The depreciation cost per print is the printer's purchase price plus expected lifetime maintenance, divided by its expected lifetime hours, multiplied by this print's hours. Default lifetime is a conservative 3,000 hours; bump it once you have real wear data.

Labor

(setup minutes ÷ 60) × labor rate$/hr

Setup is per-print: load the file, kick it off, monitor the first layer. Default is 15 minutes at your stated rate. The engine assumes the print itself runs unattended.

Packaging + customization

Packaging is per order, not per part. Customization is per part. So a 3-part Silo project ships in one box (one packaging cost) but charges three customization premiums.

When a project is grouped in the catalog and sold as one listing, the engine refunds the extra boxes from the math so you're not triple-charged for shipping. Sold individually, each part pays its own packaging.

Failure buffer

Things fail. A print jams, a cut chars, a pour traps bubbles. Every successful sale is silently subsidizing the ones you ate. The failure buffer multiplies the raw cost up by your expected failure rate.

raw × (1 + failure%). Default failure% = 10% until you have data.

Here's where it gets interesting: the moment one of your saved products has 5 logged jobs (success + failure) in the recent window, the default 10% gets replaced by your shop's actual observed rate. If your Silo Pot has 12 jobs and 2 failures, the buffer becomes 16.7% on that specific product. Not because we guessed, but because that's what your shop actually does.

Only the recent window counts (90 days by default; you can set 30, 60, or 90 on the Assumptions form). A rough patch you have since fixed (a warped bed, a bad spool) ages out of the rate instead of taxing that product's price forever, and if a product drops under 5 recent jobs the assumed buffer takes back over until there is fresh data. A shorter window reacts faster to a new problem and forgets an old one sooner.

Whether that learned rate is actually used in your price is your call. On the Assumptions form you can switch it to a signal only: with it off, every price uses your assumed failure buffer while the catalog card still shows the real observed rate, so a rough patch never quietly moves a product's price. A sale recorded while the switch is off freezes the assumed-buffer numbers, matching the catalog. On (the default) is exactly the behavior above.

Learned labor

Labor works the same way the failure rate does. When you save a product you estimate the hands-on minutes it takes. That estimate is a guess until you have receipts.

On every finished job there's a "hands-on minutes" field. Once a product has 5 jobs with a real time logged, Anvil prices it at the median of those times instead of your original estimate. Median, not average, so one nightmare custom order doesn't drag every future quote up. The number you saved stays put for you to see; only the price uses the learned figure, and only on the crafts where labor is a per-product input (every maker craft except 3D printing, which prices labor from your setup time).

Overhead

raw × (1 + failure%) × (1 + overhead%) = loaded

Overhead is the rent, insurance, accountant, internet, business license, software (yes, including this one). Costs that don't scale with any one print. Express it as a percent of raw cost. Default 0% so you can model with vs without it consciously.

The price solver

This is where most calculators get it wrong. They take your loaded cost and divide by (1 − margin%). That gives the right price if you sell direct, with no fees. On Etsy, you're paying ~9.5% in transaction + payment percentage fees, plus $0.45 in flat fees, on every sale. If you divide by (1 − margin%) and then ship on Etsy, you're quietly eating that cut.

Anvil HUD solves the price so the math hits your target margin after the channel takes its cut:

suggested = (loaded + flat fees) ÷ (1 − variable fee% − target margin%)

Where variable fee% is the sum of transaction% + payment% + ads% (the percentage cuts), and flat fees is listing fee + payment flat (the per-sale dollar cuts). A $4 loaded cost item at 50% target margin on a no-fee channel lists at $8. The same item on Etsy lists at ~$9.49, and the extra $1.49 is exactly what Etsy takes, so your take-home is the same $4 either way.

Wholesale

Selling into a boutique is different math. There's no marketplace cut to solve around, and you take a lower margin because the shop needs room to mark it up. Set a shop's channel to Wholesale and Anvil drops the fee tail and targets your wholesale margin instead of your retail one:

wholesale price = loaded ÷ (1 − wholesale margin%)

The default wholesale margin is 50% (the classic "wholesale is your cost times two" rule), tunable per shop. A $4 loaded cost item lists wholesale at $8, with no Etsy cut layered on, so it undercuts what you'd charge a retail buyer for the same piece.

Anvil also suggests an MSRP for the shop to resell at, your wholesale price times a keystone multiplier (2× by default):

MSRP = wholesale price × keystone

So an $8 wholesale piece carries a suggested $16 shelf price. The MSRP is a reference for you and the buyer, not a price Anvil charges anyone.

Frozen at sale time

Everything above prices what you're making now. But a sale that already happened is history. When you record a sale, Anvil snapshots its whole build-up that day, the cost to make it, the price it sold for, and the channel's fees, and stores it on the sale.

From then on your dashboards read that frozen snapshot for the sold item, not a fresh re-price. So when you raise your overhead, bump a labor rate, or a material gets more expensive, your catalog prices and your next sales move, but the margin and take-home on work you already sold stay exactly what they were the day money changed hands. Assumptions price the future, not the past.

Fixed a setting that was genuinely wrong and want a past sale to reflect the correction? Each recorded sale has a Recost button that re-snapshots it at today's assumptions on purpose. Sales recorded before this existed price live until you recost them, so none of your history quietly shifted under you.

Refunds use the same frozen split. On a full refund Etsy credits your fees back in full (transaction and payment processing, flats included: verified against a real payment statement), so a refunded sale hands its fees back too. A goods-lost refund still counts what the refund cannot undo: the cost you sank making the item and any carrier label you already paid for. A partial refund keeps fees on the kept amount only. Selling on your own site through Stripe or PayPal? Those processors typically keep their processing fee on refunds; per-channel refund fee behavior is a planned setting.

Shipping

Shipping is its own line, charged to the buyer separately from the item (the way Etsy splits item price and shipping price). It never touches the numbers above: no failure buffer, no overhead, no product margin. We only recover what it costs you to post the order.

base rate + (item weight + packaging weight) ÷ 1000 × rate$/kg = shipping cost

The weight is the item weight (the filament a print used, the sheet or parts a cut used, the resin in a pour), plus the packaging weight you set on the shipping profile. If an order goes over an optional weight cap, the per-kilo rate stops and we show the base rate only, flagged so you quote a real freight rate by hand.

A bulky 3D product can be told it ships in more than one box (the "Ships in" field on its Edit details). Each box pays the base rate and carries its own packaging weight, so a two-box order costs 2 × base rate + (item weight + 2 × packaging weight) at the per-kilo rate, and the weight cap is checked per box. The setting covers the whole product: on a multi-part product, set it on any one part and the highest value across the parts counts (parts left at one box never add boxes). Which parts sit in which box does not matter to the math, so we do not ask. One box (the default) is the formula above, unchanged.

Box size matters too, through dimensional weight. Carriers bill the greater of an item's actual weight and its volumetric weight, which is the box volume divided by a carrier divisor (length × width × height in inches ÷ 139 for UPS/FedEx, ÷ 166 for USPS). So a light but bulky product (a big hollow print) ships as if it weighed more. Give a 3D product its box size on Edit details and set the divisor on the shipping profile, and the estimate bills on whichever is greater, per box. Leave the box size blank and it stays purely weight-based, unchanged to the cent. Either way this only moves the shipping line, never the item price.

The price the buyer pays is the cost grossed up for the channel's percentage fee on shipping (Etsy and the like charge their cut on shipping too), so you net back the cost, not less:

shipping price = shipping cost ÷ (1 − variable fee%)

Free shipping is the one exception. Set a free-shipping threshold and any item that lists at or above it ships free (or half-price) to the buyer, while you absorb the carrier cost. That is the first thing that actually comes out of your take-home, so we show it plainly: the dollars you absorb, your new take-home, and the price you would list at to earn it back and stay whole.

absorbed = shipping cost (or half) · stay-whole price = listed + absorbed ÷ (1 − variable fee%)

One honest caveat: this is a close estimate, not a live carrier quote. Real postage shifts with destination, box size, and the carrier's current pricing, so treat it as a starting point and confirm the real rate before you list.

Laser cutting

Anvil HUD prices laser cutting through the same engine. The loaded cost, the price solver, the channel fees, and the shipping line all work exactly as above. Only the raw inputs change, because a laser meters sheet area and beam time, not filament grams. You drop an SVG (the file Glowforge, xTool, and LightBurn all import) and the engine reads the cut length and the footprint straight off the geometry.

Material is sheet stock, charged one of two ways you choose per product:

area used ÷ sheet area × sheet$ × wasteMultiplier

sheets per item × sheet$ (when a cut claims a whole sheet)

The footprint is the SVG bounding box; area used is the slice of a full sheet your cut occupies. The waste multiplier is the same slicer-invisible loss factor as 3D (offcuts you cannot reuse).

Machine time is computed from the geometry and your speeds, not stamped by a slicer. Glowforge is cloud-based and no standard file records job time, so the engine derives it and labels it an estimate you tune to your machine:

(cut length ÷ cut speed) × passes + (engrave area ÷ engrave speed) = minutes

Cut speed comes from your machine and material together (acrylic cuts slower than plywood, so each material carries a speed factor). Passes handle thick stock. Engrave time only counts when you are rastering a filled area.

Electricity and machine depreciation use that time exactly like a print. Depreciation folds the tube or diode replacement cost in next to the purchase price, because that consumable is the laser's real wear item:

hours × watts ÷ 1000 × rate$/kWh, and hours × (purchase$ + tube/diode$) ÷ lifetime hours

Labor is your hands-on minutes (setup, masking, weeding, finishing) at your rate. Sum the pieces and you have the laser raw cost:

material + electricity + machine + labor + packaging = raw

From there it is identical to a print: the failure buffer (learned from your own logged cuts once a product has five), overhead, the after-fees price solver, and the shipping line all apply unchanged. Cut time is the one number worth sanity-checking against your real machine. Power, focus, air assist, and material brand all move it, so we show it as an estimate and let you tune the speeds.

Resin casting

Resin runs through the same engine, with one honest difference: there is nothing to drop. There is no G-code or SVG for a pour, so the resin estimate is form-driven (you enter the grams and pick the mold). And curing is passive, ambient, often overnight, so there is no electricity line and no metered machine time. The reusable mold takes the machine's place: it is the tool that wears out, amortized over the pours it lasts.

Material is the resin you poured, by weight, plus colorant and any inclusions:

grams ÷ 1000 × resin$/kg × wasteMultiplier

Weigh it on a scale (most accurate), or let the built-in volume calculator work it out from the mold's dimensions. The waste multiplier is the same slicer-invisible loss factor as the other crafts (resin left in the cup, a botched mix).

Mold is the tooling line, the resin analogue to machine depreciation. A mold survives a finite number of pours, so its cost per piece is its price spread over those pours (and its cavities, if it makes several at once):

mold$ ÷ expected pours ÷ cavities

Equipment is optional: a pressure pot or vacuum chamber, durable over thousands of pours, so its per-piece depreciation is small but real. We meter it rather than bury it, the same honesty as everything else:

equipment$ ÷ lifetime pours

Labor is your hands-on minutes (mix, pour, debubble, demold, sand, finish) at your rate. Cure time is passive and is not billed as labor. Add small per-pour consumables (cups, sticks, gloves, mold release) and you have the resin raw cost:

material + mold + equipment + labor + consumables + packaging = raw

From there it is identical to a print: the failure buffer (learned from your own logged pours once a product has five, because bubbles, soft spots, and demold breaks are real), overhead, the after-fees price solver, and the shipping line all apply unchanged.

Candle making

Candles run through the same engine and are the simplest raw cost of any craft. Like resin there is nothing to drop, so the estimate is form-driven. And like resin there is no electricity line and no metered machine time: melting is a few passive minutes. But candles go one step further: there is also no tooling line. The vessel is not a reusable mold, it is sold with the candle, so it is counted as material at full price.

Wax is by weight; fragrance is a load percent of the wax weight, then by weight too:

wax grams ÷ 1000 × wax$/kg × wasteMultiplier

(wax grams × load%) ÷ 1000 × fragrance$/kg × wasteMultiplier

The built-in wax calculator sizes the pour from the vessel and your load. Vessel is the jar or tin at full cost, dye and wick are small per-candle adds, and labor is your hands-on minutes (mix, pour, wick, label, pack) at your rate. Melting is passive and not billed:

wax + fragrance + vessel + dye + wick + consumables + labor + packaging = raw

From there it is identical to a print: the failure buffer (learned from your own logged candles once a product has five, because sinkholes, frosting, and cracked glass are real), overhead, the after-fees price solver, and the shipping line all apply unchanged.

Soap making

Cold process soap shares the engine with one structural twist: it is made in batches. You cannot make a single bar, so a recipe plus a mold describe a loaf, and the per-bar price is the batch cost divided by the bars the mold yields. Like candles there is no electricity and no machine time (curing is passive, weeks on a rack), and the mold is cheap and reused for hundreds of bars, so it is overhead, not a metered tooling line. Its only job in the math is the bars-per-batch divisor.

Oils are your recipe, by weight, summed across every oil in the batch:

Σ (oil grams ÷ 1000 × oil$/kg) × wasteMultiplier

Lye is not a saved ingredient, it is derived. Every oil has a saponification (SAP) value, the milligrams of KOH that saponify a gram of it; the engine sums that across the recipe, converts KOH to the NaOH bar soap uses (× 0.713), and applies your superfat (the lye discount that leaves some oils unsaponified for a gentler bar):

Σ (oil grams × SAP) × 0.713 × (1 − superfat) ÷ 1000 × lye$/kg

Fragrance is a load percent of the oil weight, by weight. Those three are batch costs, so they are divided by the mold's bars to get a per-bar figure. The built-in lye + batch calculator works the lye, water, and fragrance out for you (always confirm your lye before mixing). Then per bar you add colorant, packaging, and your hands-on labor (batch minutes ÷ bars):

(oils + lye + fragrance) ÷ bars + colorant + labor + packaging = raw

From there it is identical to a print: the failure buffer (learned from your own logged batches once a product has five, because lye-heavy bars, false trace, and the dreaded orange spots are real), overhead, the after-fees price solver, and the shipping line all apply unchanged.

Vinyl cutting

Cut vinyl (Cricut / Silhouette) runs through the same engine. Like laser it is metered by area, but like candles and soap it is a simplest-tier craft: the cutter is cheap, low-power, and fast, so it is overhead, with no machine-time or electricity line. Form-driven: you enter the finished design size, not a file (a decal is sized to a physical dimension).

Vinyl is your design's area at your price per square inch (work that out from the sheet or roll you buy):

width × height × quantity × vinyl$/sq in × wasteMultiplier

Transfer tape is a small derived line on decals (HTV is pressed directly, no tape), priced off the same area. The blank (the tee, mug, or tumbler an HTV design presses onto) is full-cost material sold with the item, like the candle vessel; a sticker or wall decal has none:

design area × tape$/sq in (decals), + blank$ at full cost (HTV)

Labor is your hands-on minutes (weeding, masking or pressing, trimming, packing) at your rate. The cutter runs fast and unattended, so its time is not billed. Add per-item consumables (backing board, envelope) and you have the vinyl raw cost:

vinyl + tape + blank + labor + consumables + packaging = raw

From there it is identical to a print: the failure buffer (learned from your own logged cuts once a product has five, because a torn weed or a crooked press is real), overhead, the after-fees price solver, and the shipping line all apply unchanged. Vinyl spoilage tends to run 5-10%, so it is worth setting your waste percent there.

Machine embroidery

Machine embroidery runs through the same engine and, like laser and 3D, it is a machine-time craft: the machine ties up real run-time and wears down. The master number is the design's stitch count, which drives both the thread and the run-time. Form-driven: you enter the stitch count (your digitizing software lists it).

Thread (with bobbin) is charged per 1000 stitches:

(stitches ÷ 1000) × thread$/1000 × wasteMultiplier

Machine time is the run-time, and electricity + depreciation meter over it exactly like a print:

minutes = stitches ÷ machine speed (spm)

hours × watts ÷ 1000 × rate$/kWh, and hours × purchase$ ÷ lifetime hours

Stabilizer (backing + needles) is a small per-item cost. The blank (the garment, cap, or towel) is full-cost material sold with the item, like the candle vessel; a loose patch has none. Digitizing (the one-time art→stitch-file cost) is entered per item, amortized over your run. Labor is your hands-on minutes (hooping, thread changes, trimming) at your rate, kept separate from the machine run-time so neither is double-counted:

thread + stabilizer + blank + electricity + machine + digitizing + labor + packaging = raw

From there it is identical to a print: the failure buffer (learned from your own logged stitch-outs once a product has five, because thread breaks and birdnests are real), overhead, the after-fees price solver, and the shipping line all apply unchanged. The industry's $1-3 per 1000 stitches is a useful cross-check on the result, not an input.

A worked example (3D printing)

Bambu A1, default everything. You drop a G-code for a 47 g, 8 h 30 m, 2-color print.

  • Material: 47 × 1.12 × 1.02 × ($22.99 ÷ 1000) = $1.23
  • Electricity: 8.5 × 0.095 × $0.106 = $0.09
  • Machine: 8.5 × ($300 + 0) ÷ 3000 = $0.85
  • Labor: (15 ÷ 60) × $20 = $5.00
  • Packaging: $1.50
  • Customization: 1 × $0.50 = $0.50
  • Raw: $9.17
  • × (1 + 10%) failure: $10.09
  • × (1 + 0%) overhead: $10.09
  • Loaded: $10.09
  • ÷ (1 − 0% − 50%) for Direct: $20.18 → $20 listed
  • ÷ (1 − 9.5% − 50%) + flat $0.45 for Etsy: $25.06 → $25 listed

At $20 on your site you take home $9.91 net of cost. At $25 on Etsy you take home $9.93 net of cost and fees. Same margin, different sticker. Buyers pay the channel's tax; you don't.

The other engine

The trade engine: bidding a job

Everything above prices a unit you make and sell. The trades ( renovation, painting, roofing, and the rest) do something different: they BID A JOB. So they run on a separate engine, built bottom-up, with no marketplace tail (no channel fee, no Etsy, no per-item shipping). A bid is assembled from line items, not metered off a file.

Each line item is one of three shapes:

quantity × material × (1 + waste%) + quantity × labor

or a flat allowance (a fixture the client hasn't picked yet)

or a subcontractor's bid × (1 + your markup%)

Sum the lines and you have the bare cost. Then the build-up adds the things a job carries that a single line doesn't:

bare cost + general conditions (permits + dumpster + equipment rental) = direct cost

direct cost × (1 + contingency%) = loaded cost

loaded cost × (1 + overhead% + profit%) = bid price

The contingency covers what you can't see until you open the wall; overhead and profit go on as a percent of the loaded cost, so your target profit is the number you actually keep, not a markup that quietly comes up short. Building and pricing a bid is free; exporting the client-facing proposal is the one Pro piece.

One honest difference worth stating: markup is what you add to cost, margin is what you keep out of the price. A 20% markup is about a 17% margin. The trade engine applies overhead and profit on price, so a target profit means what it says.

Services run on this same engine.

Web design and other creative services aren't trades, but they bid a project the same way, so they share this exact build-up with a few tweaks. The line items are labor by the page or phase, since a website has no per-unit material. The general conditions become your tools, subscriptions, and hosting instead of permits and a dumpster. The contingency covers revisions and scope creep. And a recurring care plan is quoted alongside the one-time build (the build is $X, then $Y a month), the recurring revenue most freelancers leave on the table. The math underneath is identical.

The digital engine

A file is copied for free, so a digital product has no per-unit material or machine cost. The only real cost is the one-time work to create it, and the honest question is how many sales recoup that. The digital engine amortizes your design time over the run you expect, then prices for fees and margin on top.

designInvestment = design hours × your rate

perSaleDesign   = designInvestment ÷ expected sales

raw/unit       = perSaleDesign + POD base + other

loaded/unit    = raw × (1 + buffer%) × (1 + overhead%)

price = (loaded + flat fees) ÷ (1 − channel fee% − margin%)

Digital vs print-on-demand. A pure download has no per-unit cost, so the whole price is your amortized design plus fees and margin. Print-on-demand adds the partner's per-order base (a $9 tee, an $8 mug) as a real per-unit cost on top, so a POD product is priced to cover the partner, your time, and your margin.

The two numbers that matter. From the price the engine derives the net per sale (after channel fees) and your contribution (net minus any per-unit cost), then two headline figures: break-even units (how many sales recoup the design investment, designInvestment ÷ contribution) and projected profit (contribution × expected sales − designInvestment). Everything past break-even is profit, and the estimator shows you exactly where that line falls.

There is no shipping line in the digital engine: a download has none, and print-on-demand shipping is the partner's, set on their side. The refund/chargeback buffer reuses the same failure-buffer field as the maker engine, and fees reuse the same fee profiles, so Etsy, Gumroad, or your own store all price the same honest way.

Why we publish this

The math should be auditable. If a number on your breakdown screen looks wrong, you should be able to argue with it. Point at the line that's off and either fix the input or tell us our formula is broken. Black-box pricing tools make you trust them. We'd rather you trust the math.