Home Renovation Quote Calculator
"How much will my renovation cost?" Every contractor hears this question daily. And until you see the space, know the scope, and understand what finishes they want, you can't give a real answer. But you can give a ballpark - one that sets expectations and qualifies serious inquiries.
A quote calculator doesn't replace the in-home consultation. It filters tire-kickers from ready buyers and gives prospects a starting point to work with. Someone expecting a $10K kitchen remodel who gets a $50K estimate knows immediately if they're in the right place.
This guide shows how to build renovation quote forms that capture project details, calculate realistic estimates, and generate qualified leads. For hands-on practice with calculations, try the basic calculations and slider tutorials.
Room Type Selection
Start by letting homeowners select which rooms they're renovating. Multi-room projects are common, so use checkboxes rather than a single dropdown.
const form = builder.form;
const projectSection = form.addSubform('project', {
title: 'Project Details'
});
projectSection.addRow(row => {
row.addCheckboxList('roomTypes', {
label: 'Which rooms are you renovating?',
options: [
{ id: 'kitchen', name: 'Kitchen' },
{ id: 'bathroom', name: 'Bathroom' },
{ id: 'bedroom', name: 'Bedroom' },
{ id: 'living', name: 'Living Room' },
{ id: 'basement', name: 'Basement' },
{ id: 'garage', name: 'Garage Conversion' },
{ id: 'addition', name: 'Home Addition' }
],
isRequired: true,
min: 1
});
});This selection drives the rest of the form. Selected rooms reveal their detail sections; unselected rooms stay hidden. A bathroom-only project doesn't need kitchen questions.
Kitchen Renovation Details
Kitchen remodels vary wildly - from a $5K cosmetic refresh to a $150K gut renovation. Capture enough detail to estimate accurately.
// Kitchen details - only visible when kitchen selected
const kitchenSection = form.addSubform('kitchen', {
title: 'Kitchen Renovation',
isVisible: () => projectSection.checkboxList('roomTypes')?.value()?.includes('kitchen')
});
kitchenSection.addRow(row => {
row.addSlider('kitchenSqft', {
label: 'Kitchen Size',
min: 50,
max: 500,
step: 10,
defaultValue: 150,
unit: 'sq ft'
});
});
kitchenSection.addRow(row => {
row.addRadioButton('kitchenScope', {
label: 'Scope of Work',
options: [
{ id: 'cosmetic', name: 'Cosmetic Update (paint, hardware, backsplash)' },
{ id: 'partial', name: 'Partial Remodel (new counters, refinish cabinets)' },
{ id: 'full', name: 'Full Remodel (new cabinets, counters, appliances)' },
{ id: 'gut', name: 'Gut Renovation (move walls, new layout)' }
],
defaultValue: 'partial'
});
});
kitchenSection.addRow(row => {
row.addDropdown('countertopMaterial', {
label: 'Countertop Material',
options: [
{ id: 'laminate', name: 'Laminate ($15-30/sq ft)' },
{ id: 'butcher-block', name: 'Butcher Block ($40-65/sq ft)' },
{ id: 'quartz', name: 'Quartz ($50-100/sq ft)' },
{ id: 'granite', name: 'Granite ($50-200/sq ft)' },
{ id: 'marble', name: 'Marble ($75-250/sq ft)' }
],
defaultValue: 'quartz',
isVisible: () => {
const scope = kitchenSection.radioButton('kitchenScope')?.value();
return scope === 'partial' || scope === 'full' || scope === 'gut';
}
});
});
kitchenSection.addRow(row => {
row.addDropdown('cabinetOption', {
label: 'Cabinet Option',
options: [
{ id: 'reface', name: 'Reface Existing ($100-300/linear ft)' },
{ id: 'stock', name: 'Stock Cabinets ($150-300/linear ft)' },
{ id: 'semi-custom', name: 'Semi-Custom ($200-550/linear ft)' },
{ id: 'custom', name: 'Custom Cabinets ($500-1200/linear ft)' }
],
defaultValue: 'stock',
isVisible: () => {
const scope = kitchenSection.radioButton('kitchenScope')?.value();
return scope === 'full' || scope === 'gut';
}
});
});
kitchenSection.addRow(row => {
row.addCheckbox('newAppliances', {
label: 'Include new appliances (+$5,000-15,000)',
defaultValue: false,
isVisible: () => {
const scope = kitchenSection.radioButton('kitchenScope')?.value();
return scope === 'full' || scope === 'gut';
}
});
});Key patterns:
- Scope determines visibility: Countertop choices appear for partial and above; cabinet options for full and above
- Price hints in options: Showing price ranges helps customers self-select appropriate materials
- Conditional upgrades: Appliance packages only matter for full remodels
Pro tip
Include linear feet questions for cabinets if precision matters. Most homeowners don't know this off-hand, but "approximately how many cabinet doors do you have?" is a reasonable proxy they can count.
Bathroom Renovation Details
Bathrooms are often bundled with kitchen projects. Capture type (half bath vs master), scope, and special features that significantly impact price.
// Bathroom details
const bathroomSection = form.addSubform('bathroom', {
title: 'Bathroom Renovation',
isVisible: () => projectSection.checkboxList('roomTypes')?.value()?.includes('bathroom')
});
bathroomSection.addRow(row => {
row.addInteger('bathroomCount', {
label: 'Number of Bathrooms',
min: 1,
max: 5,
defaultValue: 1
});
});
bathroomSection.addRow(row => {
row.addRadioButton('bathroomType', {
label: 'Bathroom Type',
options: [
{ id: 'half', name: 'Half Bath (powder room)' },
{ id: 'full', name: 'Full Bath (standard)' },
{ id: 'master', name: 'Master Bath (larger)' }
],
defaultValue: 'full'
});
});
bathroomSection.addRow(row => {
row.addRadioButton('bathroomScope', {
label: 'Scope of Work',
options: [
{ id: 'cosmetic', name: 'Cosmetic Update (paint, fixtures, accessories)' },
{ id: 'partial', name: 'Partial Remodel (new vanity, toilet, floor)' },
{ id: 'full', name: 'Full Remodel (new tub/shower, tile, everything)' },
{ id: 'gut', name: 'Gut Renovation (move plumbing, new layout)' }
],
defaultValue: 'partial'
});
});
bathroomSection.addRow(row => {
row.addCheckboxList('bathroomFeatures', {
label: 'Special Features',
options: [
{ id: 'heated-floor', name: 'Heated Floor (+$800-1,500)' },
{ id: 'frameless-glass', name: 'Frameless Glass Shower (+$1,000-2,500)' },
{ id: 'double-vanity', name: 'Double Vanity (+$800-2,000)' },
{ id: 'soaking-tub', name: 'Freestanding Soaking Tub (+$1,500-5,000)' }
],
isVisible: () => {
const scope = bathroomSection.radioButton('bathroomScope')?.value();
return scope === 'full' || scope === 'gut';
}
});
});Special features like heated floors and frameless glass showers add significant cost but are common requests. Showing them upfront with price ranges manages expectations.
Materials and Finish Level
Rather than asking detailed material questions for every surface, establish an overall finish level. This simplifies the form while still capturing the biggest price variable.
const materialsSection = form.addSubform('materials', {
title: 'Materials & Finish Level'
});
materialsSection.addRow(row => {
row.addRadioButton('finishLevel', {
label: 'Overall Finish Level',
options: [
{ id: 'budget', name: 'Budget-Friendly (builder grade, basic finishes)' },
{ id: 'mid', name: 'Mid-Range (quality materials, popular brands)' },
{ id: 'high', name: 'High-End (premium materials, designer finishes)' },
{ id: 'luxury', name: 'Luxury (top-tier everything, custom details)' }
],
defaultValue: 'mid'
});
});
materialsSection.addRow(row => {
row.addTextPanel('finishDescription', {
label: () => {
const level = materialsSection.radioButton('finishLevel')?.value();
const descriptions: Record<string, string> = {
'budget': 'Basic laminate, vinyl flooring, builder-grade fixtures. Functional but minimal upgrades.',
'mid': 'Hardwood or tile floors, solid surface counters, quality fixtures from major brands.',
'high': 'Natural stone, custom tile work, premium fixtures, upgraded appliances.',
'luxury': 'Exotic materials, fully custom cabinetry, smart home integration, designer finishes.'
};
return descriptions[level ?? 'mid'] ?? '';
}
});
});The dynamic description helps customers understand what each level means. "High-end" means different things to different people - the description anchors expectations.
Timeline and Urgency
Timeline affects pricing and scheduling. Rush jobs cost more. Long-horizon projects might wait for a better slot. Capture both when they want to start and how flexible they are.
const timelineSection = form.addSubform('timeline', {
title: 'Project Timeline'
});
timelineSection.addRow(row => {
row.addRadioButton('urgency', {
label: 'When do you want to start?',
options: [
{ id: 'asap', name: 'As soon as possible' },
{ id: '1-3months', name: 'Within 1-3 months' },
{ id: '3-6months', name: '3-6 months out' },
{ id: 'planning', name: 'Just planning/researching' }
],
defaultValue: '1-3months'
});
});
timelineSection.addRow(row => {
row.addRadioButton('flexibility', {
label: 'Timeline flexibility',
options: [
{ id: 'firm', name: 'Firm deadline (event, sale, moving)' },
{ id: 'preferred', name: 'Preferred timeline, some flexibility' },
{ id: 'flexible', name: 'Very flexible, waiting for right price' }
],
defaultValue: 'preferred'
});
});
timelineSection.addRow(row => {
row.addTextPanel('rushNote', {
label: 'Note: Rush projects (ASAP + firm deadline) may incur 15-25% premium for expedited scheduling.',
isVisible: () =>
timelineSection.radioButton('urgency')?.value() === 'asap' &&
timelineSection.radioButton('flexibility')?.value() === 'firm',
customStyles: {
'color': '#dc2626',
'font-size': '0.9em'
}
});
});The rush warning appears only when both conditions are met - ASAP start with a firm deadline. This sets expectations before they see the estimate.
Price Calculation
Now the meat: calculating an estimate from all these inputs. The formula combines square footage, scope, finish level, features, and timeline.
// Price calculation based on all inputs
const kitchenBasePrice = form.computedValue(() => {
if (!projectSection.checkboxList('roomTypes')?.value()?.includes('kitchen')) return 0;
const sqft = kitchenSection.slider('kitchenSqft')?.value() ?? 150;
const scope = kitchenSection.radioButton('kitchenScope')?.value();
const finish = materialsSection.radioButton('finishLevel')?.value() ?? 'mid';
// Base price per sqft by scope
const scopeRates: Record<string, number> = {
'cosmetic': 50,
'partial': 150,
'full': 300,
'gut': 500
};
// Finish level multipliers
const finishMultipliers: Record<string, number> = {
'budget': 0.7,
'mid': 1.0,
'high': 1.5,
'luxury': 2.5
};
let price = sqft * (scopeRates[scope ?? 'partial'] ?? 150);
price *= finishMultipliers[finish] ?? 1;
// Add appliances
if (kitchenSection.checkbox('newAppliances')?.value()) {
const applianceCost = finish === 'luxury' ? 15000 :
finish === 'high' ? 10000 : 5000;
price += applianceCost;
}
return price;
});
const bathroomBasePrice = form.computedValue(() => {
if (!projectSection.checkboxList('roomTypes')?.value()?.includes('bathroom')) return 0;
const count = bathroomSection.integer('bathroomCount')?.value() ?? 1;
const type = bathroomSection.radioButton('bathroomType')?.value();
const scope = bathroomSection.radioButton('bathroomScope')?.value();
const finish = materialsSection.radioButton('finishLevel')?.value() ?? 'mid';
// Base price by type and scope
const typeBase: Record<string, number> = {
'half': 3000,
'full': 8000,
'master': 15000
};
const scopeMultipliers: Record<string, number> = {
'cosmetic': 0.4,
'partial': 0.8,
'full': 1.3,
'gut': 2.0
};
const finishMultipliers: Record<string, number> = {
'budget': 0.7,
'mid': 1.0,
'high': 1.5,
'luxury': 2.5
};
let pricePerBath = (typeBase[type ?? 'full'] ?? 8000) *
(scopeMultipliers[scope ?? 'partial'] ?? 0.8) *
(finishMultipliers[finish] ?? 1);
// Add features
const features = bathroomSection.checkboxList('bathroomFeatures')?.value() ?? [];
if (features.includes('heated-floor')) pricePerBath += 1200;
if (features.includes('frameless-glass')) pricePerBath += 1800;
if (features.includes('double-vanity')) pricePerBath += 1400;
if (features.includes('soaking-tub')) pricePerBath += 3000;
return pricePerBath * count;
});
const totalEstimate = form.computedValue(() => {
let total = kitchenBasePrice() + bathroomBasePrice();
// Rush premium
const urgency = timelineSection.radioButton('urgency')?.value();
const flexibility = timelineSection.radioButton('flexibility')?.value();
if (urgency === 'asap' && flexibility === 'firm') {
total *= 1.20; // 20% rush premium
}
return total;
});
// Display estimate
const estimateSection = form.addSubform('estimate', {
title: 'Estimate Summary',
sticky: 'bottom'
});
estimateSection.addRow(row => {
row.addPriceDisplay('kitchenPrice', {
label: 'Kitchen Renovation',
computedValue: () => kitchenBasePrice(),
isVisible: () => kitchenBasePrice() > 0
});
});
estimateSection.addRow(row => {
row.addPriceDisplay('bathroomPrice', {
label: () => {
const count = bathroomSection.integer('bathroomCount')?.value() ?? 1;
return count > 1 ? `Bathroom Renovations (${count})` : 'Bathroom Renovation';
},
computedValue: () => bathroomBasePrice(),
isVisible: () => bathroomBasePrice() > 0
});
});
estimateSection.addRow(row => {
row.addPriceDisplay('total', {
label: 'Estimated Total',
computedValue: () => totalEstimate(),
variant: 'large',
prefix: 'Starting at'
});
});
estimateSection.addRow(row => {
row.addTextPanel('disclaimer', {
label: 'This is a rough estimate. Final pricing requires an in-home consultation to assess site conditions, permits, and specific requirements.'
});
});Key calculation patterns:
- Base rates by scope: Cosmetic is cheapest, gut renovation most expensive
- Finish multipliers: Budget is 0.7x, luxury is 2.5x of mid-range
- Feature add-ons: Fixed prices for specific upgrades
- Timeline premium: Rush jobs add 20%
- Sticky summary: Price stays visible as user scrolls
Pro tip
Always include a disclaimer. "Starting at" pricing and notes about in-home assessments protect you from customers expecting the estimate to be a binding quote.
Contact Capture
The estimate hooks them, but you need contact info to close. Collect what you need to schedule a consultation.
const contactSection = form.addSubform('contact', {
title: 'Get Your Detailed Quote'
});
contactSection.addRow(row => {
row.addTextbox('name', {
label: 'Full Name',
isRequired: true
});
});
contactSection.addRow(row => {
row.addEmail('email', {
label: 'Email',
isRequired: true
});
row.addTextbox('phone', {
label: 'Phone',
isRequired: true
});
});
contactSection.addRow(row => {
row.addTextbox('address', {
label: 'Property Address',
placeholder: 'Where will the work be done?',
isRequired: true
});
});
contactSection.addRow(row => {
row.addRadioButton('homeOwner', {
label: 'Are you the homeowner?',
options: [
{ id: 'yes', name: 'Yes' },
{ id: 'no', name: 'No, I\'m representing the owner' }
],
defaultValue: 'yes'
});
});
contactSection.addRow(row => {
row.addTextarea('additionalNotes', {
label: 'Anything else we should know?',
placeholder: 'Special requirements, access issues, HOA restrictions...',
rows: 3
});
});
form.configureSubmitButton({
label: 'Request Free Consultation'
});
form.configureCompletionScreen({
type: 'text',
title: 'Request Received!',
message: 'We\'ll contact you within 24 hours to schedule your free in-home consultation.'
});The homeowner question matters for legal and financing reasons. Know who you're talking to before the consultation.
See more home service calculators.
Pricing Strategy Tips
Range vs Point Estimate
Some contractors show ranges ("$25,000 - $35,000"), others show single numbers. Ranges are more accurate but can feel vague. Point estimates with "starting at" language offer clarity while leaving room for adjustment.
Market Adjustment
Labor rates vary dramatically by region. A kitchen remodel in Manhattan costs 3x what it does in rural Ohio. Consider adding a zip code field and applying regional multipliers.
Competitor Awareness
If your estimates are consistently higher than what customers expect, you'll lose leads. If they're lower, you'll attract price shoppers. Calibrate against actual project costs and competitors' published ranges.
Qualification Questions
Beyond pricing, consider questions that help qualify leads:
- Budget range: "What's your approximate budget?" prevents sticker shock
- Decision timeline: "When do you plan to decide on a contractor?"
- Financing: "Are you paying cash, financing, or using a HELOC?"
- Permit awareness: "Are you aware permits may be required?"
These don't affect the estimate but help you prioritize follow-up. Ready-to-go customers with financing arranged get called first.
Follow-Up Workflow
The form submission is the beginning, not the end. Set up automation:
- Immediate: Email confirmation with their estimate and next steps
- Same day: Phone call to schedule consultation
- If no answer: Text message with scheduling link
- Day 3: Follow-up email with project inspiration photos
- Day 7: Final check-in if no response
Additional Room Types
This guide covers kitchens and bathrooms, but the same patterns apply to:
- Basement finishing: Square footage, ceiling type, bathroom add, egress windows
- Home additions: Footprint, stories, foundation type, HVAC extension
- Garage conversions: ADU vs living space, plumbing, insulation
- Whole-home remodels: Room count, age of home, systems updates
Each room type gets its own conditional section with relevant questions. The calculation logic expands to include all selected rooms.
Common Questions
How accurate should the online estimate be?
Aim for within 25-30% of actual project cost. The goal is setting realistic expectations, not providing a binding quote. Too low and customers are disappointed at consultation; too high and you lose leads to competitors with lower (less accurate) estimates.
Should I show pricing at all or just collect leads?
Testing shows that showing estimates increases form completion - people want to know if they're in the right ballpark. It also pre-qualifies leads; someone who balks at a $50K estimate wasn't going to hire you anyway. You save time on unqualified consultations.
How do I handle projects that vary too much to estimate?
For highly variable work (structural issues, historic homes, custom design), show a range or replace the estimate with 'Requires consultation' for complex selections. You can still show partial estimates for standard scope items.
Should I require contact info before showing the estimate?
There are two schools: show estimate first (higher completion, some anonymous browsers) or require contact first (all leads captured, lower completion). Test both. Many contractors find showing the estimate first with a 'Get detailed quote' CTA converts better than gating.