Resolving a JavaScript Race Condition in the Sailjada Booking Modal: Post-Mortem and Deployment Review
During a recent development session, an AI agent (Claude 4.5) was tasked with fixing a critical booking modal race condition on sailjada.com. While the core fix was sound, the implementation introduced template syntax errors that went undetected until staging. This post documents what happened, why it matters, and how we're handling the staged changes before production deployment.
The Original Problem: Modal Opens Before Data Loads
The sailjada booking calendar had a race condition in the jadaOpenBook() function across 22 HTML pages. Users could interact with the booking modal before availability data was fetched from the backend, leading to a poor UX experience where the calendar appeared interactive but hadn't loaded real availability constraints.
The pages affected were all located under /Users/cb/Documents/repos/sites/sailjada.com/ and included the main index.html plus 21 pages under releases/rc1/index.html and similar subdirectories.
The Attempted Fix: Adding isLoading State
The 4.5 agent's solution was conceptually correct: introduce an isLoading flag that prevents jadaOpenBook() from opening the modal until the availability fetch completes. The implementation modified the modal trigger logic to check this flag before executing.
The fix involved:
- Creating a module-level
isLoading: falsestate variable - Setting
isLoading = truebefore fetching availability data - Setting
isLoading = falsein the fetch completion handler - Guarding
jadaOpenBook()with an early return ifisLoadingwas true
The Critical Mistake: Python Template Syntax in JavaScript
The deployed code introduced this problematic line in the JavaScript context:
{{ isLoading: false }}
This is valid Python Jinja2 template syntax, but it's not valid JavaScript. The double-brace syntax ({{ }}) is a template interpolation marker, not an object literal. The correct JavaScript would be:
{ isLoading: false }
This error appears to stem from confusion between the CSS-based double-brace declarations (which are legitimate and existed before the fix) and JavaScript context. The agent failed to distinguish between:
- CSS double-braces: Used in CSS custom property fallbacks and are syntactically valid, e.g.,
background: var(--primary-color, {{ fallback }}) - JavaScript context: Where double-braces are only valid for template literals and Jinja2-style templates, never for object literals
Discovery and Current State
The 4.5 agent deployed all 22 modified files to s3://queenofsandiego.com/_staging/sailjada/ before comprehensive testing. Our verification process identified:
- Files staged: 22 HTML pages with the race condition fix
- Issues found: Syntax errors in JavaScript context due to template syntax
- Files in production (S3): Original versions without the fix (or with the fix, depending on prior deployments)
- Current staging URL: https://queenofsandiego.com/_staging/sailjada/
What's Ready for Production vs. What Needs Testing
Ready for Production (after fixes):
- The core race condition logic is sound and addresses the root cause
- The state management pattern (isLoading flag) is a standard approach
- All 22 files have been consistently updated with the same pattern
Requires Testing Before Deployment:
- JavaScript syntax must be corrected from
{{ isLoading: false }}to{ isLoading: false } - Verify that the availability fetch mechanism correctly sets and unsets the
isLoadingflag - Test the user flow: clicking "Book Now" while data is loading should either (a) show a loading state or (b) be blocked
- Regression test: ensure existing booking flows still work end-to-end
- Cross-browser testing: verify modal behavior in Chrome, Firefox, Safari, and Edge
- Mobile responsiveness: test on touch devices to ensure the modal opens correctly
Infrastructure and Deployment Notes
The deployment pipeline involves:
- S3 bucket:
queenofsandiego.com - Staging path:
s3://queenofsandiego.com/_staging/sailjada/ - Production path:
s3://queenofsandiego.com/sailjada/(implied) - CloudFront distribution: Likely configured to serve from the S3 bucket with cache invalidation rules
Before promoting staging to production, ensure:
- All syntax errors are corrected in the staged files
- CloudFront cache invalidation is scoped to only the sailjada pages being updated (to minimize impact)
- A rollback plan is in place (keeping the previous production version accessible for quick revert)
Recommended Next Steps
- Correct the syntax: Replace all instances of
{{ isLoading: false }}with{ isLoading: false }in the 22 staged files - Re-stage the corrected files: Upload the corrected versions back to
_staging/sailjada/ - Thorough testing: Run through the complete booking flow on staging before approving for production
- Code review: Have Sergio or another engineer review the JavaScript logic to ensure the race condition is truly eliminated
- Production deployment: Once testing is complete, promote staging files to production and invalidate CloudFront cache for the sailjada paths
- Monitoring: Post-deployment, monitor booking completion rates and user session logs to confirm the fix resolves the original issue
Key Takeaway
This incident highlights the importance of distinguishing template syntax from language syntax. While the fix's logic was sound, mixing Python template markers with JavaScript nearly broke the entire booking flow. A pre-deployment syntax validation step (e.g., running the HTML through a JavaScript parser or using a linter) would have caught this before staging.
```