Skip to main content
Skip to main content
Still in beta — questions, comments or suggestions? aramb@aramb.dev

Add a Simple Frontend to View Uploaded Files

Build a small HTML frontend that calls the metadata list API and configure CORS for your API Gateway.

25 min
Introductory
AWS Free TierFREE TIER

All services used in this lesson are covered by the AWS Free Tier.

AWS Services Used

S312-month free tierAPI Gateway12-month free tier

Learning Outcomes

By the end of this lesson, you will be able to:

  1. Build a small HTML frontend that calls the metadata list API.
  2. Explain why CORS is required when a site hosted on one origin calls an API hosted on another origin.
  3. Configure CORS for an API Gateway HTTP API.
  4. Deploy the frontend to an S3 static website bucket.
  5. Render a list of uploaded files returned by the API.

The Core Idea

You already built the backend pieces: S3 for uploads, Lambda for processing, DynamoDB for metadata, and API Gateway for read and list endpoints.

Now you will add a tiny browser frontend that calls GET /metadata/list and shows the results on a page.

Cross-Origin Request Flow

Why CORS Matters Here

CORS (Cross-Origin Resource Sharing) is required when a web app hosted on one domain (origin) calls an API hosted on another. In this lesson:

  • Your frontend origin is your S3 website endpoint.
  • Your API origin is your API Gateway execute-api URL.

Because these origins are different, you must configure your HTTP API to explicitly allow requests from your frontend origin.


Part 1: Enable CORS on the HTTP API

Open your API Gateway HTTP API and configure CORS. A safe starting setup is:

  • Allow origin: your S3 website URL (e.g., http://bucket-name.s3-website-region.amazonaws.com)
  • Allow methods: GET
  • Allow headers: Content-Type

Part 2: Create the Frontend File

Create a file named index.html with this content:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Uploaded Files Viewer</title>
  <style>
    body { font-family: sans-serif; max-width: 760px; margin: 40px auto; padding: 0 16px; line-height: 1.5; }
    form { display: grid; gap: 12px; margin: 20px 0; }
    input, button { padding: 10px 12px; font-size: 16px; }
    .card { border: 5px solid #ddd; border-radius: 10px; padding: 12px; margin-top: 12px; }
    .muted { color: #666; font-size: 14px; }
    .error { color: #b00020; margin-top: 12px; }
  </style>
</head>
<body>
  <h1>Uploaded Files Viewer</h1>
  <form id="searchForm">
    <input id="bucket" type="text" placeholder="Bucket name" required />
    <input id="prefix" type="text" placeholder="Prefix (optional), e.g. incoming/" />
    <button type="submit">Load files</button>
  </form>
  <div id="status" class="muted"></div>
  <div id="error" class="error"></div>
  <div id="results"></div>

  <script>
    const API_BASE_URL = "YOUR_API_BASE_URL";

    const form = document.getElementById("searchForm");
    form.addEventListener("submit", async (event) => {
      event.preventDefault();
      const bucket = document.getElementById("bucket").value.trim();
      const prefix = document.getElementById("prefix").value.trim();
      
      const params = new URLSearchParams({ bucket });
      if (prefix) params.set("prefix", prefix);

      try {
        const response = await fetch(`${API_BASE_URL}/metadata/list?${params.toString()}`);
        const data = await response.json();
        if (!response.ok) throw new Error(data.error || "Request failed");
        
        document.getElementById("results").innerHTML = data.items.map(item => `
          <div class="card">
            <strong>${item.object_key}</strong>
            <div class="muted">Size: ${item.size} bytes | Event: ${item.event_name}</div>
          </div>
        `).join("");
      } catch (error) {
        document.getElementById("error").textContent = error.message;
      }
    });
  </script>
</body>
</html>

Part 3: Add your Real API URL

Replace YOUR_API_BASE_URL in the script with your actual API Gateway base URL (e.g., https://abc123.execute-api.us-east-1.amazonaws.com).


Part 4: Upload the Frontend to S3

  1. Upload index.html to your S3 website bucket.
  2. Ensure Static website hosting is enabled on the bucket.
  3. Open the Website endpoint provided by S3.

Part 5: Test the Flow

  1. Open your frontend in the browser.
  2. Enter your upload bucket name.
  3. Enter the prefix incoming/.
  4. Submit and verify that your file metadata appears.

Lab Checklist

StepSuccess Condition
Enable CORS on HTTP APIBrowser is allowed to call the API
Create index.htmlFrontend file exists
Add real API base URLFrontend points to your API
Upload to S3 bucketFrontend is hosted
Submit bucket/prefixAPI request runs and returns metadata

Micro-activity 1: Reflection

Think about it

After the lab, reflect: What website URL did you open? What API base URL did you configure? What bucket did you search? Did the page render files or an error?


Micro-activity 2: Match Each Service's Role

Micro-Activity

Match each service to what it does in this lesson

Examples

Choose one, then match it on the right

Characteristics

Select an example first

0 of 4 matched so far.


Summary

In this lesson, you added the user-facing piece: a static frontend that calls your API and renders metadata. You learned that CORS is essential when your frontend and backend live on different origins.


Quiz

Knowledge Check
1 / 4

Why is CORS needed in this lesson?