Building a Daily Artist Celebration Feature for Event Pages: Architecture and Implementation

Overview

We implemented a dynamic artist celebration system for the Queen of San Diego Rady Shell Events website that injects fresh artist spotlights into event pages three times daily until concert day. This feature was inspired by Nike's brand philosophy of celebrating athletes rather than commodities—in this case, celebrating world-class musicians to create emotional connection with attendees.

The implementation spans three primary layers: Google Apps Script for dynamic content generation, a Python-based static site renderer for template management, and AWS infrastructure (S3 + CloudFront) for content delivery and cache invalidation.

Architecture Overview

The system works as follows:

  • Content Generation: A new Google Apps Script service (ArtistCelebrationsService.gs) queries artist data and generates spotlight HTML using the Anthropic API
  • Template Injection: Python tooling (inject_artist_spotlight.py) injects placeholder sections into static event HTML files
  • Runtime Rendering: The GAS HTTP endpoint serves dynamic content via Code.gs router, which calls the celebration service
  • Static Site Updates: Updated HTML files are deployed to event-specific S3 buckets and cached via CloudFront distributions
  • Cache Management: CloudFront invalidations ensure fresh content appears immediately across all event subdomains

Technical Implementation

Google Apps Script Services

We created ArtistCelebrationsService.gs to handle artist spotlight generation. This service:

  • Queries the backing Google Sheet for artist metadata (name, biography, notable works)
  • Calls the Anthropic API with a carefully crafted prompt to generate compelling, concise celebration copy
  • Returns formatted HTML ready for injection into event pages
  • Includes error handling for API failures and rate limiting

The service is invoked via a new HTTP endpoint registered in the main Code.gs router. The router pattern was extended to support:

GET /artist-celebration?eventId={id} → returns HTML section

This endpoint is called via client-side JavaScript on each event page, ensuring the spotlight is fetched fresh on every page load.

Python Template Injection

The inject_artist_spotlight.py script handles bulk modification of existing event HTML files. Key responsibilities:

  • Parses the events manifest from events.json to iterate over all upcoming events
  • Locates the appropriate insertion point in each event's HTML template (typically after the main event description, before ticket links)
  • Injects a standardized <div id="artist-spotlight"> placeholder
  • Includes inline JavaScript to fetch and render the dynamic spotlight via the GAS endpoint

The injection is idempotent—running the script multiple times won't create duplicate sections. This was critical for the iterative development process.

Static Site Renderer Enhancement

We modified render_event_sites.py to incorporate the artist spotlight injection as part of the standard build pipeline. This ensures:

  • All newly generated event pages include the spotlight placeholder automatically
  • The renderer serves as the single source of truth for page structure
  • Manual edits to individual HTML files are overwritten on the next render, preventing drift

Infrastructure and Deployment

Google Apps Script Deployment

We created a new GAS deployment specifically for the artist celebration endpoint:

gapps deploy --create "Artist Celebration Service"

This generates a unique execution URL of the form: https://script.google.com/macros/s/{DEPLOYMENT_ID}/usercurrent

The deployment ID is stored in project configuration and referenced by the client-side JavaScript on event pages. This separation from the main GAS deployment provides:

  • Independent scaling and version management
  • Ability to rotate or update the endpoint without affecting other GAS functionality
  • Clear separation of concerns for monitoring and debugging

S3 and CloudFront Strategy

Event content is distributed across multiple S3 buckets, one per event subdomain:

  • s3://qos-event-subdomain-{eventId}/ pattern
  • Each bucket serves as the origin for a corresponding CloudFront distribution
  • CloudFront distributions are named qos-event-{eventId}-cf

We discovered several CloudFront distributions that weren't yet tracked in configuration, requiring a comprehensive audit via:

aws cloudfront list-distributions --query 'DistributionList.Items[?contains(Comment, `qos-event`)]'

This enumeration was essential for ensuring cache invalidations reached all live event pages.

Cache Invalidation Pattern

After uploading updated HTML files to S3, we trigger CloudFront invalidations for each distribution:

aws cloudfront create-invalidation --distribution-id {DIST_ID} --paths "/*"

The wildcard path ensures all cached assets—including newly injected sections—are refreshed within seconds. This was critical for the three-daily update schedule.

Key Architectural Decisions

Why Dynamic Content via GAS Instead of Static Generation

We chose a hybrid approach: static HTML shells with dynamic content injection via JavaScript callbacks to GAS. This decision was driven by:

  • Update Frequency: Three daily updates would require re-rendering and re-deploying all event pages to S3 if done statically. The hybrid approach keeps static assets mostly stable.
  • Cost: GAS HTTP invocations are cheaper than re-deploying gigabytes of HTML to S3 three times daily.
  • Simplicity: The GAS endpoint can be updated independently without coordinating with the static site build pipeline.

Why Anthropic API for Content Generation

Rather than storing pre-written spotlights for each artist, we generate them dynamically using Claude. This enables:

  • Variation across the three daily spotlights—different angles on the same artist
  • Consistency in tone and length across all artists
  • Easy experimentation with different prompts and styles without schema changes

Idempotent Injection Script

The inject_artist_spotlight.py script uses a marker-based approach to detect whether a spotlight section already exists in a file before injecting. This prevents accumulation of duplicate sections and allows the script to be safely re-run across large event catalogs.

Deployment Workflow

  1. Update ArtistCelebrationsService.gs and push to GAS project
  2. Create new GAS deployment and note the execution URL
  3. Update GAS router (Code.gs) with new endpoint URL
  4. Run inject_artist_spotlight.py to update all event HTML files locally