Making the JADA Maintenance Dashboard Task Card Interactive: Frontend UX Enhancement with S3 and CloudFront Deployment

During a recent development session, we identified a usability gap in the JADA Maintenance Hub dashboard: the "Total Tasks" summary card displayed critical information but wasn't clickable, forcing users to manually navigate to the Tasks tab to view details. This post documents the enhancement, deployment strategy, and infrastructure patterns used to ship this improvement.

The Problem

The maintenance dashboard's landing view shows key metrics in info cards, including a prominent "Total Tasks: 82" display. Users naturally expect this card to be interactive—clicking it should navigate to the full task list. Instead, they had to locate and click a separate tab navigation element. This is a classic UX friction point: making actionable data feel actionable.

What Was Done

We implemented a three-part solution:

  • Frontend Enhancement: Made the Total Tasks card clickable and wired it to switch to the Systems tab (which contains the task table)
  • Visual Feedback: Added CSS styling to indicate the card is interactive
  • Deployment: Updated the S3-hosted dashboard and invalidated CloudFront cache for immediate propagation

Technical Implementation

File Location and Architecture

The JADA Maintenance Hub is hosted in S3 at a path we manage via the maintenance subdomain. The primary file is index.html, downloaded from the S3 bucket during development. The file structure includes:

  • Embedded HTML markup for dashboard cards
  • Inline CSS for styling (within <style> tags)
  • JavaScript tab-switching logic using a switchTab() function

This single-file architecture keeps deployment simple: one index.html = one CloudFront invalidation needed.

Finding the Tab Navigation Logic

We first located the tab switching function in the HTML file. The dashboard uses a switchTab() function that accepts a tab identifier:

function switchTab(tabName) {
  // Hide all tab content
  // Show the selected tab
  // Update tab button active state
}

The task table is rendered in the systems tab (identified by data-tab="systems" attributes). This meant our onclick target should be switchTab('systems').

Frontend Changes

The Total Tasks card HTML originally looked like this:

<div class="info-card">
  <h3>Total Tasks</h3>
  <p class="stat">82</p>
</div>

We wrapped it in a clickable element and added an onclick handler:

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

Note the addition of the info-card-link CSS class—this is key for providing visual feedback.

CSS Styling for Interactivity

We added a new CSS rule to indicate the card is clickable:

.info-card-link {
  cursor: pointer;
  transition: all 0.3s ease;
  border: 2px solid transparent;
}

.info-card-link:hover {
  border-color: #4a90e2;
  box-shadow: 0 4px 12px rgba(74, 144, 226, 0.3);
  transform: translateY(-2px);
}

This provides:

  • Cursor feedback: The cursor changes to pointer on hover, signaling interactivity
  • Visual feedback: A subtle border and shadow appear on hover
  • Motion feedback: A slight upward translation creates a "lift" effect, enhancing the interactive feel

The use of transition: all 0.3s ease ensures smooth animations rather than jarring changes.

Infrastructure and Deployment

S3 Bucket and File Management

The maintenance dashboard index.html is stored in an S3 bucket dedicated to JADA infrastructure. We:

  1. Downloaded the current index.html from S3 to the local development environment
  2. Made edits locally (adding the onclick handler and CSS)
  3. Uploaded the updated file back to S3, preserving the same key path

This approach allows us to work on the file in version control and source management tools while keeping S3 as the source of truth for production content.

CloudFront Cache Invalidation

S3 alone doesn't serve the maintenance subdomain directly. CloudFront sits in front of S3, caching content at edge locations globally. Without cache invalidation, users would see the old version for up to 24 hours (depending on TTL settings).

To invalidate cache immediately, we:

  1. Identified the CloudFront distribution associated with the maintenance subdomain (by checking distribution aliases and origins)
  2. Created an invalidation targeting the path /index.html (or /* to invalidate all objects)

The invalidation command (conceptual) looks like:

aws cloudfront create-invalidation \
  --distribution-id [DISTRIBUTION_ID] \
  --paths "/index.html"

CloudFront invalidations typically propagate within 60 seconds, ensuring users see the updated dashboard quickly.

Why This Approach?

Single-File Deployment: The dashboard is a self-contained index.html with embedded CSS and JavaScript. This eliminates the need for build pipelines or asset dependency management, reducing deployment complexity.

Client-Side Navigation: Using onclick and the existing switchTab() function keeps all navigation logic in the browser. No server-side changes were needed.

CSS Hover States: Rather than adding event listeners in JavaScript, we leveraged CSS :hover pseudo-classes. This is more performant and requires less code.

Non-Destructive Changes: We added a new class (info-card-link) rather than modifying existing card styles. This prevents unintended side effects on other info cards.

Testing and Validation

After deployment, we verified:

  • Clicking the Total Tasks card switches to the Systems tab
  • The hover state (cursor pointer, border, shadow) appears in modern browsers
  • The transition is smooth (no janky animations)
  • The change doesn't break other dashboard functionality (other tabs, task filtering, etc.)

Key Decisions and Trade-offs

Why modify index.html instead of adding external files? The dashboard already ships as a single HTML file; adding external CSS or JavaScript files would require additional CloudFront invalidations and increase request count.

Why use CSS hover instead