```html

Building a Dynamic Artist Celebration System for Event Pages: From Google Apps Script to S3 Distribution

Overview

We implemented a real-time artist celebration feature across all Rady Shell event pages at queenofsandiego.com. The feature automatically injects curated artist spotlights into each event's landing page, refreshing three times daily until the concert date. This post details the architectural decisions, infrastructure changes, and deployment pipeline that made this possible.

The Vision Behind Artist Celebration

The concept draws inspiration from Nike's marketing philosophy: celebrate the athlete, not the commodity. By shifting focus to the artists themselves—their backgrounds, achievements, and cultural significance—we elevate the concert experience and create emotional connections that transcend the ticket purchase. This required building a system that could dynamically populate artist information without manual intervention for dozens of events spread across multiple subdomains.

Architecture Overview

The solution comprises three primary components:

  • Google Apps Script (GAS) backend: Fetches artist data from a Google Sheet, enriches it via Claude API calls, and serves JSON endpoints
  • Python static site generator: Injects artist spotlight HTML into event templates at build time
  • S3 + CloudFront distribution: Serves updated HTML files globally with cache invalidation

Technical Implementation Details

Google Apps Script Service Layer

We created a new service file at /apps-script-replacement/ArtistCelebrationsService.gs that encapsulates all artist data operations. This service:

  • Reads artist metadata from a Google Sheet (configured via sheet ID in environment)
  • Calls Claude API to generate contextual celebration copy (artist history, achievements, cultural impact)
  • Caches responses to minimize API costs and reduce latency
  • Exposes a REST endpoint for the static site generator to consume

The service was integrated into Code.gs with a new route handler. The GAS deployment was updated with environment variables pointing to the source Google Sheet and API endpoints:

// Sample function signature
function getArtistSpotlight(eventId) {
  const artistData = fetchArtistFromSheet(eventId);
  const enrichedData = enrichWithClaudeAPI(artistData);
  return enrichedData;
}

We created a new GAS deployment specifically for the artist celebration endpoint, listing all current deployments to identify the live executable URL ID. The update was applied to the existing production deployment that already handles event-related queries.

Python Site Renderer Enhancement

The static site generator at /tools/render_event_sites.py was modified to fetch artist spotlights during the build process. We created a companion script, /tools/inject_artist_spotlight.py, that:

  • Iterates through all event HTML files in the output directory
  • Calls the GAS endpoint to retrieve artist celebration copy for each event
  • Injects the spotlight section into a predefined location in the HTML template (positioned after the event header, before ticket information)
  • Handles failures gracefully—if the GAS endpoint is unavailable, the build completes without the spotlight (preventing broken deployments)

The injection happens post-build to decouple the static generation from dynamic data fetching, allowing iterative updates without full site rebuilds.

S3 Distribution Strategy

The Rady Shell maintains event subdomains as separate S3 buckets. For example:

  • s3://summer-concert-event-2024.queenofsandiego.com
  • s3://fall-festival-2024.queenofsandiego.com
  • s3://artist-series-2024.queenofsandiego.com

Updated HTML files are uploaded to each bucket after artist spotlight injection. This approach allows:

  • Per-event version control (each bucket maintains its own history)
  • Independent cache invalidation if an event needs urgent updates
  • Isolated failure domains—a problem with one event doesn't affect others

Infrastructure & Deployment Pipeline

CloudFront Cache Invalidation

Each event subdomain is fronted by a CloudFront distribution. After uploading updated HTML files to S3, we iterate through all live distributions and trigger cache invalidations:

// Pseudo-code for CloudFront invalidation
aws cloudfront create-invalidation \
  --distribution-id E1A2B3C4D5E6F7G8H \
  --paths "/*"

This ensures users receive the latest artist spotlight copy within seconds of upload, not after the default TTL expires. The challenge was identifying all active CloudFront distributions—we used Route53 records and AWS API queries to discover distributions not yet in our known inventory.

GAS Deployment Management

Google Apps Script projects maintain multiple deployments. We listed current deployments to identify the live execution URL ID (format: `AKfycbwXxXxXx...`), then updated the production deployment with the new ArtistCelebrationsService code. This required:

  • Authenticating with the GAS API using OAuth credentials
  • Pushing code changes to the project
  • Creating a new deployment version pointing to the updated code
  • Recording the new deployment ID for future reference in the project handoff file

Key Architectural Decisions

Why Google Apps Script for the Backend?

GAS integrates seamlessly with Google Sheets (the source of artist data) and requires minimal infrastructure management. It scales automatically and cost is negligible for this use case. The trade-off is latency—GAS cold starts can add 1-2 seconds—but since the Python renderer calls it once per build (not per user), this is acceptable.

Why Inject at Build Time?

Embedding artist spotlights in static HTML (rather than JavaScript) ensures:

  • Content is immediately visible (no render-blocking async calls)
  • Better SEO for artist information
  • Works even if JavaScript fails or is blocked
  • Reduces page weight and improves performance

The trade-off: updates require a rebuild and re-upload. We mitigate this by scheduling builds three times daily via CI/CD.

Why Per-Bucket Uploads?

Rather than maintaining a single master bucket and replicating to event buckets, we upload to each bucket independently. This provides fault isolation and simplifies rollback—reverting one event doesn't affect others. It also allows fine-grained CloudFront invalidation per event.

Verification & Quality Assurance

Post-deployment, we sampled event pages to verify artist spotlight injection. The section includes:

  • Artist name and photograph
  • Bio/background copy generated by Claude (contextual to the Rady Shell and San Diego)
  • Links to artist social profiles and related Rady Shell events
  • Styling consistent with the broader event page design

We verified spotlight appearance across desktop and mobile viewports, ensuring responsive layout and readable typography.

What's Next

Future enhancements could include: