My brother runs 24-Hour Movers — a two-man moving operation out of the Chicago suburbs. He had a flyer, a phone number, and 26 five-star Google reviews. No website. Leads were word-of-mouth only.
He asked me to build something. I told him I'd have it live in a weekend. This is how I built it, what I ran into, and what I'd do differently.
The Brief
A moving company website has one job: convert a visitor into a booked lead. Everything else is secondary. So the requirements were tight:
- A quote request form that actually notifies the owner
- Pricing that's honest and upfront (no "call for pricing" nonsense)
- Google reviews visible without making people leave the page
- A booking calendar so the owner can show availability and avoid double-bookings
- A photo gallery the owner can update himself without touching code
- A real domain, not a
netlify.appURL
The Stack
The whole thing runs on Netlify — static hosting plus serverless functions for anything that needs a backend. Here's what each piece does:
- Netlify Functions — Node.js for the quote form handler, gallery CRUD, booking calendar API, and PIN-gated owner tools
- Netlify Blobs — key-value blob store for gallery photos and the booking index. No database needed.
- Resend — transactional email for lead notifications. The owner gets a formatted HTML email every time someone submits a quote, with a one-click "Accept & Add to Schedule" button.
- Cloudflare — DNS, and eventually the domain itself (
24hourmoversllc.com)
What I Built
The Lead Notification Saga
This took longer than the entire rest of the site combined. The path went something like:
- Netlify Forms — silent spam filtering ate real submissions. Akismet flagged them.
- AT&T email-to-SMS gateway — never delivered. Carrier filtering.
- Twilio SMS — blocked by A2P 10DLC compliance. You need a registered campaign to send business SMS in the US, and that takes weeks.
- Resend email — finally worked, but DKIM verification failed on Squarespace DNS. Migrated to Cloudflare to fix it.
The final setup: quote form submits to a Netlify Function, which sends a formatted HTML email via Resend from leads@24hourmoversllc.com, BCC'd to me, with reply-to set to the owner's Gmail. Clean, reliable, and free under Resend's limits.
The Gallery — Netlify Blobs
The owner needed to upload photos himself. I didn't want to introduce a CMS, an S3 bucket, or any third-party service he'd need an account for. The answer was Netlify Blobs — a blob store built into the Netlify platform.
The flow:
- Owner visits
/gallery-admin.html?key=SECRET - Picks photos from camera roll — they resize in the browser via canvas (max 1600px, 0.82 quality JPEG) before upload
- A Netlify Function stores the image blob and prepends an entry to a JSON index
- The public gallery page fetches that index and renders a grid with a lightbox
One gotcha: Netlify Blobs needs the site ID and API token injected explicitly on manual CLI deploys. The automatic context injection only works inside Netlify's own build runners.
The Booking Calendar
The owner gets 90% of his business from referrals and repeat customers. He needed a way to block dates so customers couldn't book something on top of a confirmed move.
The model I built:
- Request → Approve: customers request, owner accepts. No auto-booking.
- One crew at a time: only one job per day, with the option to select start/end times or block the full day.
- Owner-only schedule page: protected by a PIN login. The schedule URL in lead notification emails embeds the job data in a single URL-encoded param to avoid email link mangling (quoted-printable encoding breaks multi-param URLs).
The Domain Situation
Getting 24hourmoversllc.com on Netlify was unexpectedly painful. Cloudflare Registrar blocked the registration with no explanation. Namecheap worked fine.
Then Netlify said "another project is already using this domain" — a ghost site ID that didn't exist in my account. Netlify support resolved it after I added a verified-for-netlify TXT record to prove domain ownership.
While waiting on support (a few hours), I set up a Cloudflare Page Rule to redirect the domain to the live netlify.app URL as a bridge. Worked perfectly.
The Result
The site is live at 24hourmoversllc.com. It's fast, mobile-first, and my brother can manage his own photos and schedule without touching code or calling me.
Total cost to run: $0/month. Netlify free tier, Resend free tier, Cloudflare free tier. Domain registration is ~$14/year.
If you're an agency or freelancer building sites for small businesses, this stack is worth knowing. It punches well above its weight.