# A house-cleaning quote, worked out on the server. Bootstrap 5 for the look, # no JavaScript. The form uses GET, so every quote is a link you can share. # All the prices live here: change a number and every quote follows. set business to "Fresh Start Cleaning" set business_email to "bookings@example.com" # where booking requests go set business_from to "website@example.com" # an address on your own domain set minimum to 120 # the smallest bill for one visit set type_names to "Standard clean", "Deep clean", "Move-out clean" set type_notes to "Dusting, floors, kitchen and bathrooms", "Everything in standard, plus baseboards, doors and grime", "An empty home, top to bottom, ready for the next people" set type_base to 90, 160, 220 # dollars per visit set type_bedroom to 20, 30, 35 # per bedroom set type_bathroom to 25, 35, 40 # per bathroom set type_hours to 2, 3.5, 4.5 # base time for one cleaner set bedroom_options to "1", "2", "3", "4", "5", "6" set bathroom_options to "1", "1.5", "2", "2.5", "3", "4" set often_names to "One time", "Monthly", "Every two weeks", "Weekly" set often_discounts to 0, 10, 15, 20 # percent off each visit set extra_keys to "oven", "fridge", "cabinets", "windows", "laundry", "pets" set extra_names to "Inside the oven", "Inside the fridge", "Inside cabinets", "Interior windows", "Laundry, washed and folded", "Pet hair" set extra_prices to 30, 30, 35, 40, 25, 15 # The position of what the visitor picked in a list of choices, or the # default when it is not one of them. A visitor can type anything into the # address, so the page only ever uses values from its own lists. to position_of wanted options fallback set found to fallback set position to 0 for each option in options set position to position + 1 if wanted is option set found to position end end give found end # Dollars and cents, rounded to the nearest cent: 158.9 shows as $158.90, 61.969 as $61.97. to money amount set cents to number of first of split "[amount * 100 + 0.5]" by "." set dollars to number of first of split "[cents / 100]" by "." set rest to cents - dollars * 100 if rest is less than 10 give "$[dollars].0[rest]" end give "$[dollars].[rest]" end # What was asked for. Before the first quote, a common home is filled in. set asked to query "quote" is "yes" set type_keys to "1", "2", "3" set often_keys to "1", "2", "3", "4" set type to position_of query "type" type_keys 1 set bedrooms_at to position_of query "bedrooms" bedroom_options 2 set bathrooms_at to position_of query "bathrooms" bathroom_options 1 set often to position_of query "often" often_keys 1 set name to trim of query "name" set bedrooms to number of item bedrooms_at of bedroom_options set bathrooms to number of item bathrooms_at of bathroom_options # The bill, one line at a time. set line_names to empty list set line_prices to empty list add item type of type_names to line_names add item type of type_base to line_prices add "[bedrooms] bedroom(s) at [money item type of type_bedroom]" to line_names add bedrooms * item type of type_bedroom to line_prices add "[bathrooms] bathroom(s) at [money item type of type_bathroom]" to line_names add bathrooms * item type of type_bathroom to line_prices set hours to item type of type_hours + bedrooms * 0.5 + bathrooms * 0.5 set chosen_extras to empty list set position to 0 for each extra_key in extra_keys set position to position + 1 if query extra_key is "on" add extra_key to chosen_extras add item position of extra_names to line_names add item position of extra_prices to line_prices set hours to hours + 0.25 end end set subtotal to 0 for each price in line_prices set subtotal to subtotal + price end set topped_up to 0 if subtotal is less than minimum set topped_up to minimum - subtotal set subtotal to minimum end # Regular visits get a discount. A move-out clean only happens once. set move_out_note to no if type is 3 and often is not 1 set move_out_note to yes set often to 1 end set percent to item often of often_discounts set discount to subtotal * percent / 100 set total to subtotal - discount # The address of this exact quote, so the booking form posts back to it. set quote_link to "?quote=yes&type=[type]&bedrooms=[item bedrooms_at of bedroom_options]&bathrooms=[item bathrooms_at of bathroom_options]&often=[often]" for each extra_key in chosen_extras set quote_link to "[quote_link]&[extra_key]=on" end # "Request this clean": check the details, email the quote to the business, then say thanks. set request_name to trim of form "request_name" set request_email to trim of form "request_email" set request_phone to trim of form "request_phone" set request_notes to trim of form "request_notes" set request_problems to empty list if form "request" is "yes" if request_name is empty add "your name" to request_problems end if request_email is not an email add "an email address we can reply to" to request_problems end if request_problems is empty set details to "" set position to 0 for each line_name in line_names set position to position + 1 set details to "[details] [line_name]: [money item position of line_prices]\n" end if topped_up is more than 0 set details to "[details] Minimum visit charge: +[money topped_up]\n" end if percent is more than 0 set details to "[details] [item often of often_names] discount ([percent]%): -[money discount]\n" end send email to business_email subject: "Cleaning request: [item type of type_names], [money total], from [request_name]" reply to: request_email from: business_from body: "[request_name] would like to book a clean.\n\nEmail: [request_email]\nPhone: [request_phone]\nHow often: [item often of often_names]\n\nThe quote:\n[details] Total: [money total] per visit, about [hours] hours\n\nNotes:\n[request_notes]\n" end go to "[quote_link]&requested=yes" end end <cl>show "Get a quote - [business]"</cl>

Get a cleaning quote in a minute

Tell us about your home. The price updates when you press the button, and the link is yours to keep.

1. What kind of clean?

set position to 0 for each type_name in type_names set position to position + 1 set checked to "" if position is type set checked to "checked" end show "
" show "
" end

2. Your home

A half bathroom has a toilet and sink, no shower.

3. How often?

set position to 0 for each often_name in often_names set position to position + 1 set checked to "" if position is often set checked to "checked" end set saving to "" if item position of often_discounts is more than 0 set saving to " [item position of often_discounts]% off" end show "" show "" end
Move-out cleans are always one time.

4. Extras

set position to 0 for each extra_key in extra_keys set position to position + 1 set checked to "" if chosen_extras contains extra_key set checked to "checked" end show "
" show "" show "" show "
" end

5. Your name (optional)

if asked and name is not empty show "

[name], here is your quote

" otherwise if asked show "

Your quote

" otherwise show "

An example quote

" show "

For a two-bedroom home. Change the form and press the button for yours.

" end show "
[money total]
" if percent is more than 0 show "

per visit, [lowercase of item often of often_names]

" otherwise show "

for one visit

" end show "" set position to 0 for each line_name in line_names set position to position + 1 show "" end if topped_up is more than 0 show "" end if percent is more than 0 show "" show "" end show "" show "
[line_name][money item position of line_prices]
Minimum visit charge+[money topped_up]
Subtotal[money subtotal]
[item often of often_names] discount ([percent]%)−[money discount]
Total[money total]
" show "

⏱ About [hours] hours for one cleaner.

" if move_out_note show "
Move-out cleans happen once, so this quote is for a single visit.
" end show "

Prices include supplies. This is an estimate: the final price is confirmed when we see the home.

"
# Booking is offered once there is a real quote to book. if query "requested" is "yes" show "
Request sent. We will email you within one working day to pick a time.
" otherwise if asked show "
" show "

Request this clean

We email you back to pick a time. Nothing is charged now.

" if count of request_problems is 2 show "
Please add [item 1 of request_problems] and [item 2 of request_problems].
" otherwise if request_problems is not empty show "
Please add [first of request_problems].
" end show "" if request_name is empty set request_name to name end show "" show "" show "" show "" show "" show "
" end
📦

Want this page for your own site?

The whole example is one file of Common and Bootstrap 5, with a readme. Unzip it and run cl serve 8000 house-quote. The prices are at the top of the file.

Download .zip