Dynamic Event Site Generation with Template Transformation: Automating Static Site Rendering for Rady Shell Events
What Was Done
Over this development session, we refactored the Rady Shell Events static site generation pipeline to use a template-driven approach. Instead of manually maintaining individual HTML files for each event, we built an automated transformation system that generates event-specific pages from a single template, pulls data from a JSON event manifest, and deploys the rendered output to S3 with CloudFront cache invalidation.
The core workflow now follows this pattern:
- Master template lives at:
/sites/queenofsandiego.com/rady-shell-events/sites/bobdylan/index.html - Event data is stored in
events.jsonwith structured metadata (pricing, dates, modal content) - Python transformation script at
/tools/render_event_sites.pyiterates over all events and generates customized HTML - Rendered pages are deployed to S3 bucket
queenofsandiego.comunder event-specific prefixes - CloudFront distributions are invalidated to clear stale cache
Technical Details: The Template Transformation Pipeline
The transformation script uses a straightforward but effective approach: it loads the template once, then uses Python string replacement to inject event-specific values. Key implementation details:
render_event_sites.py
├── Load template HTML from bobdylan/index.html
├── Parse events.json for all event configurations
├── For each event:
│ ├── Replace {{ARTIST_NAME}} with event name
│ ├── Replace {{EVENT_DATE}} with formatted date
│ ├── Replace {{PRICING_TIERS}} with JSON pricing array
│ ├── Replace {{MODAL_CONTENT}} with event-specific details
│ └── Write rendered output to temp directory
└── Deploy each rendered file to S3 and invalidate CloudFront
The script explicitly skips certain events during batch operations (notably bobdylan and archived events) to avoid redundant deployments or overwriting the master template.
The template includes modal widgets with data attributes that are populated at render time. For example, the pricing widget structure gets injected as a complete JSON array, allowing frontend JavaScript to iterate and display pricing tiers without additional API calls:
<div class="pricing-modal" data-pricing='[{"tier":"GA","price":"$95"},...]'>
<!-- Modal content populated by frontend JS -->
</div>
Infrastructure: S3, CloudFront, and Deployment Strategy
The deployment infrastructure leverages AWS primitives for global distribution:
- S3 Bucket:
queenofsandiego.com— primary static asset storage - Object Structure:
rady-shell-events/sites/{event-slug}/index.html - CloudFront Distribution: Fronts the S3 bucket with edge caching for low-latency global delivery
- Cache Invalidation: After each deployment, we invalidate the CloudFront distribution using wildcard patterns like
/rady-shell-events/sites/{event-slug}/*
Each deployment cycle runs independently per event. For batch operations, the script loops through events, uploads to S3, then immediately invalidates the corresponding CloudFront path. This ensures that deployed changes are visible within seconds rather than waiting for TTL-based cache expiry (which defaults to 24-86400 seconds).
Deployment commands executed during this session:
aws s3 cp /tmp/rendered/{event-slug}/index.html s3://queenofsandiego.com/rady-shell-events/sites/{event-slug}/index.html
aws cloudfront create-invalidation --distribution-id {DIST_ID} --paths "/rady-shell-events/sites/{event-slug}/*"
Data Structure: events.json as the Single Source of Truth
Event metadata is centralized in a single JSON file. This eliminates scattered configuration and makes bulk operations (like pricing updates or date corrections) a matter of editing one file and re-rendering:
{
"events": [
{
"slug": "koolandthegang",
"artist_name": "Kool & The Gang",
"event_date": "2024-07-15",
"pricing": [
{"tier": "GA", "price": "$85"},
{"tier": "VIP", "price": "$150"}
],
"modal_content": "..."
},
...
]
}
The script validates against this schema and can perform bulk audits (e.g., "list all birthday event pricing" or "check which events have incomplete modal data") by querying the JSON directly.
Key Decisions and Rationale
- Template Over Manual HTML: Before this refactor, each event had its own hand-maintained HTML file. This created drift risk—UI improvements had to be manually applied to 7+ files. The template approach ensures consistency and makes global changes (like adding a new modal section) a single-edit operation.
- Python String Replacement Over a Templating Engine: We chose simple string replacement over Jinja2 or similar because the transformation is lightweight and one-directional. There's no need for loops, conditionals, or complex logic in the template—just placeholder substitution. This keeps dependencies minimal and the script fast.
- Immediate CloudFront Invalidation: Rather than relying on cache TTL, we invalidate immediately after S3 upload. This guarantees that production traffic sees new content within seconds, which is critical for time-sensitive event updates (e.g., last-minute pricing changes or sold-out notices).
- Batch Skip Logic: The script explicitly skips
bobdylanduring batch runs to protect the master template. Individual manual deployments ofbobdylanare supported, but automatic batch cycles ignore it to prevent accidental overwrites.
Improvements Made During This Session
- Fixed HTML encoding issues in modal widget rendering—ensured JSON payloads within data attributes are properly escaped
- Verified modal element structure in rendered pages to confirm JavaScript can correctly parse pricing and content data
- Batch-deployed 6 event pages in a single operation with CloudFront cache warming
- Added validation checks for required fields (artist name, date, pricing tiers) before rendering
What's Next
Potential enhancements for future iterations:
- Conditional Template Sections: Add logic to render event-specific sections (e.g., "VIP meet-and-greet" for certain artists) without duplicating template code
- Automated Validation: Pre-render checks to ensure all required data is present in events.json before S3 upload
- CI/CD Integration: Trigger renders and deployments on Git commits to the events.json file, using a webhook or scheduled GitHub Actions
- Analytics Tracking: Embed event-specific UTM parameters or tracking codes during render time for downstream reporting
The refactor establishes a scalable foundation for managing dozens or hundreds of event pages with minimal manual overhead.
```