Making the JADA Maintenance Dashboard Card Clickable: UI/UX Enhancement with S3 and CloudFront Cache Invalidation

What Was Done

The JADA Maintenance Hub dashboard had a "Total Tasks" information card displaying task counts, but it was purely informational. Users expected to click it to navigate to the detailed task list. This session involved making that card interactive by wiring it to the existing tab navigation system, then deploying the change through the S3/CloudFront architecture with proper cache invalidation.

Technical Details: DOM Manipulation and Event Binding

The maintenance hub lives in a static HTML file stored in an S3 bucket. The original "Total Tasks" card was a simple <div> with class info-card:

<div class="info-card">
  <div class="card-label">Total Tasks</div>
  <div class="card-value">82</div>
</div>

To make it clickable without breaking existing structure, we wrapped it in a styled container and added an onclick handler that calls the existing tab-switching function:

<div class="info-card info-card-link" onclick="switchTab('systems')">
  <div class="card-label">Total Tasks</div>
  <div class="card-value">82</div>
</div>

The switchTab() function was already implemented in the page's JavaScript and handles tab switching via data attributes on tab elements. By passing 'systems' as the parameter, clicking the card now switches to the Systems tab where the full task table resides.

CSS Enhancement for UX Feedback

To make the card's interactivity obvious, we added a new CSS class info-card-link:

.info-card-link {
  cursor: pointer;
  transition: all 0.2s ease;
}

.info-card-link:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
  background-color: rgba(255, 255, 255, 0.95);
}

This provides visual feedback: the card lifts slightly on hover, the shadow deepens, and the background brightens. These subtle cues signal to users that the element is clickable without requiring additional button styling.

Infrastructure: S3 and CloudFront Deployment

The JADA Maintenance Hub architecture uses a multi-layered caching strategy:

  • S3 Bucket: jada-maintenance-hub — stores the static index.html file and associated assets
  • CloudFront Distribution: Acts as the CDN layer, caching the S3 content with a short TTL for rapid updates
  • Route53: DNS routing for the maintenance subdomain points to the CloudFront distribution

The deployment workflow involved three distinct steps:

Step 1: File Download and Local Modification

We downloaded the current index.html from the S3 bucket to verify the structure and locate the Total Tasks card. The file is around 50KB and contains embedded CSS and JavaScript for the dashboard.

Step 2: S3 Upload

After making the HTML and CSS modifications, the file was uploaded back to S3 using:

aws s3 cp /path/to/maintenance_index.html s3://jada-maintenance-hub/index.html --content-type "text/html"

The --content-type flag ensures S3 serves the file with the correct MIME type, preventing browser caching issues.

Step 3: CloudFront Invalidation

S3 alone wouldn't be sufficient—the CloudFront distribution caches the file at edge locations worldwide. Without cache invalidation, users would see the old version for up to 24 hours (default TTL). We identified the CloudFront distribution ID and created an invalidation:

aws cloudfront create-invalidation --distribution-id [DIST_ID] --paths "/*"

Using /* invalidates all cached files in the distribution, ensuring the new index.html is fetched immediately from origin (S3) on the next request. This invalidation completes in 30–60 seconds across CloudFront's global edge locations.

Key Decisions and Rationale

Why Reuse switchTab() Instead of Creating New Navigation?

The tab system was already well-established in the codebase. The switchTab() function handles state management, tab highlighting, and content visibility. Reusing it meant zero risk of creating duplicate state or navigation bugs. Adding a new event handler for a card click would have increased complexity and maintenance burden.

Why CSS Hover States Matter in This Context

The maintenance hub serves Sergio and other crew members who may not be familiar with typical web UI patterns. On a mobile device or tablet in the cockpit, hover states don't exist—but the cursor: pointer still signals interactivity on desktop. The transform: translateY(-2px) is subtle enough to feel refined but visible enough to register as feedback.

Why Invalidate All Paths Instead of Just /index.html?

While theoretically we could have targeted just /index.html, using /* is safer because it accounts for potential CSS or JS asset changes. If any inline assets were modified alongside the HTML, they'd all be refreshed. The cost is negligible (CloudFront invalidations are free for the first 3,000/month per distribution).

Testing and Validation

Post-deployment validation involved:

  • Hard-refreshing the maintenance hub URL in a browser and confirming the card displays hover effects
  • Clicking the "Total Tasks" card and verifying the Systems tab activates and the task table appears
  • Checking browser DevTools to confirm the CloudFront X-Cache header shows "Hit from cloudfront" (proving the new version was cached), not stale content

What's Next

This change is a UX improvement with zero breaking changes. Future enhancements could include:

  • Making other information cards (Systems, Maintenance Records, etc.) similarly clickable to their respective tabs
  • Adding click analytics to track which cards users interact with most, informing dashboard layout decisions
  • Implementing URL routing so clicking the card updates the browser history, allowing back-button navigation

The infrastructure pattern used here—S3 origin, CloudFront CDN, cache invalidation on content changes—is the standard deployment model for JADA's static web properties and scales well as the dashboard grows with additional features.