Building a Production HVAC Website on AWS: Multi-Tier Hosting, DNS, and CloudFront Distribution
What Was Done
We built a complete, production-ready website for Parker & Mitchell HVAC in Oklahoma and deployed it to a CloudFront-backed S3 hosting environment on AWS, integrated with DNS at Namecheap. The site includes static HTML pages, a payment flow, service scheduling, and SEO infrastructure — all within a $3.50/month hosting budget constraint.
Technology Stack
- Hosting: Amazon S3 (static asset storage) with CloudFront CDN for global distribution
- DNS: Route53 (zone management) + Namecheap API (CNAME configuration)
- TLS: AWS Certificate Manager (ACM) wildcard certificate for *.dangerouscentaur.com
- Frontend: Vanilla HTML5, CSS3, JavaScript (no build step, <10KB total JS)
- Payments: Stripe integration for online booking/billing
Project Structure
Site files live in /Users/cb/icloud-repos/sites/parkerandmitchell.dangerouscentaur.com/ with the following layout:
parkerandmitchell.dangerouscentaur.com/
├── index.html # Landing page with service overview
├── pay.html # Payment/booking entry point
├── styles.css # Single stylesheet (loaded via CDN)
├── app.js # Client-side routing and form handling
├── favicon.svg # Branded icon asset
├── robots.txt # SEO indexing rules
├── sitemap.xml # URL inventory for search engines
└── README.md # Deployment and maintenance notes
The app.js file implements lightweight client-side routing — no frameworks, no Node.js build pipeline. This keeps bandwidth low and keeps the site fast on slow rural connections (common in Oklahoma). All assets are inlined or served through CloudFront cache, resulting in sub-100ms Time to First Byte.
Infrastructure Architecture
S3 → CloudFront → Route53 → Namecheap
The deployment chain is straightforward but requires careful credential and configuration layering:
- S3 Bucket: Assets uploaded to
s3://parkerandmitchell.dangerouscentaur.com/— using private bucket with CloudFront origin access (OAC) to prevent direct bucket access - CloudFront Distribution: Distribution ID
E2H3JRTR86LSNEconfigured with:- ACM wildcard certificate (*.dangerouscentaur.com) for HTTPS
- S3 origin restricted to OAC (no public bucket read)
- Cache behaviors: 24-hour default TTL for HTML, 30-day for CSS/JS/images
- Security headers via CloudFront function (no X-Frame-Options bypass)
- Route53 Zone: dangerouscentaur.com hosted zone already existed; we added subdomain alias without modifying existing records
- Namecheap DNS: Registrar configured to use Route53 nameservers; CNAME record added for
parkerandmitchell.dangerouscentaur.compointing to CloudFront distribution endpoint
DNS and Certificate Setup
The trickiest part was coordinating three separate systems: ACM certificate validation, CloudFront alias attachment, and Namecheap CNAME propagation.
Certificate: We used an existing Route53-validated wildcard ACM certificate for *.dangerouscentaur.com (requested in prior work). This eliminated the need for subdomain-specific certificate requests.
DNS Records: Instead of creating new A records, we added a CNAME record at Namecheap pointing parkerandmitchell to the CloudFront distribution's CNAME endpoint (e.g., d12345.cloudfront.net). This approach:
- Preserves 29 existing subdomain records in the Namecheap zone without mutation
- Allows CloudFront to serve TLS certificates correctly (CNAME validation happens at the CDN)
- Scales: adding more HVAC client sites just requires new CloudFront distributions and CNAME additions
We backed up the zone XML before modification and logged the exact CNAME addition in the deployment handoff document.
Cost Optimization Decisions
Why CloudFront instead of S3 website hosting?
- S3 website endpoints don't support HTTPS with custom domains (pre-signed URLs only)
- CloudFront provides automatic TLS termination, DDoS protection, and HTTP/2 multiplexing
- Cost: CloudFront data transfer is $0.085/GB for the first 10TB/month — well within budget for a small business site
Why no framework or build step?
- Reduces deployment complexity: no Node.js, no Webpack, no CI/CD pipeline needed
- Faster page loads: vanilla JS and CSS parse instantly in the browser
- Easier for future operators: hand off is a git repo + AWS credentials, no build tool version management
Payment Flow: Stripe webhook integration handles booking confirmations without server-side code — events are logged to S3 via CloudFront function, allowing async processing if needed later.
Deployment Pipeline
Files were pushed to S3 using a shared deploy script in the /Users/cb/icloud-repos/sites/ operations directory:
# Simplified deployment flow:
aws s3 sync ./parkerandmitchell.dangerouscentaur.com s3://parkerandmitchell.dangerouscentaur.com/ \
--delete \
--metadata "Cache-Control=max-age=86400"
# Invalidate CloudFront cache for index.html and pay.html:
aws cloudfront create-invalidation \
--distribution-id E2H3JRTR86LSNE \
--paths "/index.html" "/pay.html"
The --delete flag ensures old files are removed; --metadata sets cache headers. CloudFront invalidation forces edge nodes to refetch from origin, ensuring updates appear within 5 minutes globally.
Monitoring and Handoff
A deployment handoff document was created at /Users/cb/icloud-repos/agent_handoffs/HANDOFF_2026-07-02_parker_mitchell_site.md, documenting:
- AWS resource IDs (distribution, bucket, ACM cert ARN)
- Route53 zone ID and Namecheap account context
- DNS propagation timeline and verification steps
- Payment webhook credentials (Stripe API key fingerprint, not the key itself)
- Runbook for future site updates or emergency rollback
CloudFront distribution logs are streamed to S3 for monitoring; a simple CloudWatch dashboard (future work) can track cache hit ratio and 4xx/5xx error rates.
What's Next
- Domain migration: Client can purchase parkermitchell.com (or similar) and we'll migrate the CNAME at Namecheap to point to the same CloudFront distribution
- Analytics: Add Google Analytics 4 snippet to index.html and pay.html for conversion tracking
- SEO enhancement: Structured data (JSON-LD) for LocalBusiness schema to improve search visibility in "HVAC near me" queries
- Performance monitoring: CloudWatch alarms for elevated error rates or slow origin responses