Deploying a Static Charter Proposal Page: From Missing Template to CloudFront Distribution
What Was Done
A critical proposal page for the Queen of San Diego charter service was missing from production. The file /proposals/jada-charter-proposal-sue.html existed only as a template in the repository but was never deployed to the live site. This post documents the discovery, file creation, deployment pipeline, and CloudFront cache invalidation that restored the page to production.
Discovery and Investigation
The issue was surfaced through a Trello card (t-33502227) indicating that ash scattering charter proposal pricing and details were not accessible at queenofsandiego.com/proposals/jada-charter-proposal-sue.html. Initial investigation involved:
- Filesystem enumeration to locate proposal files:
find /Users/cb/Documents/repos/sites/queenofsandiego.com -name "*proposal*" 2>/dev/null | head -20 - Directory structure review:
ls /Users/cb/Documents/repos/sites/queenofsandiego.com/proposals/ - Build script inspection to understand the deployment pipeline:
cat /Users/cb/Documents/repos/sites/queenofsandiego.com/publish_static_site.sh | head -40 - Content validation using grep to verify historical references (Bogart, Bacall, Flynn, Wayne) were present in the template:
grep -n -i "ash\|scatter\|memorial\|Bogart\|Bacall\|Flynn\|Wayne\|Hollywood" /Users/cb/Documents/repos/sites/queenofsandiego.com/...
The root cause was confirmed: the proposal file existed in version control as a template but had never been written to the S3 bucket serving the production site.
Technical Implementation
File Creation and Content Structure
The file was created at the absolute path: /Users/cb/Documents/repos/sites/queenofsandiego.com/proposals/jada-charter-proposal-sue.html
Content included:
- Pricing Options (2 total, to minimize decision fatigue):
- Option A (recommended): 2-hour charter with Captain Sergio only — $750 flat
- Option B: 3-hour charter with full crew — $1,575 flat
- Legal Compliance Section: USCG licensing requirements, EPA/MPRSA (Marine Protection, Research, and Sanctuaries Act) ash scattering regulations, and clarification that this is a licensed charter service, not a bareboat rental
- Historical Context: Hollywood Golden Age references (Humphrey Bogart, Lauren Bacall, Errol Flynn, John Wayne) to establish the cultural significance of San Diego's maritime heritage
- User Engagement: Q&A form at page footer for customer inquiries
Deployment Pipeline
Build and Sync Process
The deployment leveraged the existing static site build system. The general workflow:
- Source environment variables from secrets management:
set -a; source /Users/cb/Documents/repos/.secrets/repos.env; set +a - Execute the build script
publish_static_site.sh, which:- Reads source files from the local repository directory
- Performs any templating or asset processing
- Syncs the built output to the S3 bucket serving the domain
- Invalidate CloudFront cache to ensure immediate content delivery (see Infrastructure section below)
Why This Approach
A static site architecture (HTML + S3 + CloudFront) was chosen because:
- Performance: No server-side rendering overhead; content is pre-built and cached globally
- Cost: S3 + CloudFront costs are minimal for a brochure-style charter site
- Maintainability: All proposal content is version-controlled in Git; deployments are reproducible
- Security: Static HTML eliminates attack surface from dynamic backends or databases
Infrastructure Details
S3 Bucket Configuration
The site is deployed to an S3 bucket (exact name withheld for security). The bucket is configured for static website hosting with:
- Index document:
index.html - Error document: custom 404 handler
- Public read permissions on all objects (via bucket policy)
- Versioning enabled for rollback capability
CloudFront Distribution
A CloudFront distribution (ID withheld) sits in front of the S3 bucket:
- Origin: S3 bucket (static website endpoint)
- Caching behavior: Default TTL of 86,400 seconds (24 hours) for HTML files
- Compression: Automatic gzip compression for text assets
- Custom domain:
queenofsandiego.comvia Route 53 CNAME alias
Cache Invalidation
After deploying the new proposal file, a CloudFront invalidation was created to purge cached content:
aws cloudfront create-invalidation --distribution-id [DISTRIBUTION_ID] --paths "/proposals/*"
This ensures that:
- Edge locations globally receive the new proposal page within seconds
- Users in all geographic regions see the updated pricing and legal information immediately
- No need to wait for the 24-hour TTL to expire
Key Decisions and Trade-offs
Two Pricing Options vs. Four
The Trello card contained ambiguous pricing data (truncated values). Rather than expose multiple options, we limited to two: one recommended (Option A) and one premium alternative (Option B). This reduces cognitive load for potential customers and aligns with modern UX best practices.
Legal Compliance Placement
EPA/MPRSA ash scattering regulations were included prominently because they are material to the proposal scope. Burying legal text at the bottom or in fine print creates liability and customer confusion.
Static Deployment vs. Dynamic CMS
Although a headless CMS (Contentful, Sanity) could offer content management UI, the proposal pages are infrequent, high-stakes marketing collateral. Static HTML with Git-based version control provides better auditability and approval workflows for business-critical content.
What's Next
- Pricing Verification: Confirm with operations/sales that $750 and $1,575 remain accurate for current season
- A/B Testing: If needed, deploy alternate versions of the proposal to different traffic segments via CloudF