By this stage of the Cloud Resume Challenge, you’ve got a working backend (API Gateway + Lambda + DynamoDB) and a static website hosted on S3 + CloudFront. The next step is where the pieces start to come together: connecting the frontend to the backend, automating deployments, and making sure your project doesn’t break every time you push new code.
In this blog, I’ll walk through exactly how I tackled Chunk 3:
- Connecting the API to the website with JavaScript
- Writing smoke tests to validate the system end-to-end
- Automating deployments with GitHub Actions
- Securing everything with OIDC roles
1. Connecting the API to the Website
The goal here is to display the live visitor count from DynamoDB on the website.
Writing the JavaScript Call
At its core, this is just a fetch()
request to your API Gateway endpoint:
async function updateVisitorCount() {
const response = await fetch("https://your-api-gateway-id.execute-api.region.amazonaws.com/prod/visitors");
const data = await response.json();
document.getElementById("visitor-count").innerText = data.count;
}
updateVisitorCount();
That’s it—just a couple of lines!
Solving CORS Issues
The biggest headache is CORS (Cross-Origin Resource Sharing). By default, browsers will block calls between your static website domain and your API Gateway domain.
To fix this:
- In API Gateway, enable CORS for your routes.
- Allow the domain of your CloudFront distribution (not just
*
) for better security. - Test again in the browser console to confirm the API call succeeds.
Once working, your static site is now dynamic, pulling in live data from AWS.
2. Writing Smoke Tests with Playwright
Manual testing is fine when you’re experimenting, but production-ready cloud apps need automation. That’s where Playwright comes in.
Playwright allows you to run end-to-end smoke tests:
import { test, expect } from '@playwright/test';
test('Visitor counter API updates correctly', async ({ request }) => {
const response = await request.get('https://your-api-gateway-id.execute-api.region.amazonaws.com/prod/visitors');
const body = await response.json();
expect(body.count).toBeGreaterThan(0);
});
This test confirms:
- The API is reachable.
- It returns valid data.
- The visitor count increments as expected.
Other smoke tests I added:
- API rejects malformed requests.
- Visitor count initializes correctly (no undefined/null values).
- Database updates persist between calls.
These tests validate not just the Lambda code, but the entire deployed stack: API Gateway, Lambda, IAM roles, and DynamoDB.
3. Automating with GitHub Actions
Now that the site talks to the backend and tests exist, the next step is to automate deployments.
Here’s what my GitHub Actions pipeline does on every push to main
:
- Deploy Static Website – Syncs the Hugo build to the S3 bucket.
- Invalidate CloudFront Cache – Ensures new changes show instantly worldwide.
- Deploy Lambda + Infrastructure – Uses IaC (e.g., Terraform or SAM) for backend updates.
- Run Smoke Tests – Executes Playwright tests against the live API endpoint.
Example deploy.yml
:
name: Deploy Cloud Resume Challenge
on:
push:
branches: [ "main" ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy Infrastructure
run: ./deploy_infra.sh
- name: Run Playwright Tests
run: npx playwright test
This workflow means no manual deployments. Every code push goes live automatically—with tests ensuring nothing breaks.
4. Securing with OIDC Roles
One of the most important lessons from this challenge: never use long-lived AWS credentials in CI/CD pipelines.
Instead, I set up OIDC (OpenID Connect) roles between GitHub Actions and AWS:
- GitHub is configured as an OIDC identity provider in AWS IAM.
- A dedicated IAM role allows GitHub workflows to assume permissions temporarily.
- No AWS keys stored in the repo—security risks eliminated.
This is how professional teams handle authentication for CI/CD. It’s secure, scalable, and reduces human error.
Final Thoughts
Chunk 3 transformed my project from “a static site with a backend” into a production-ready cloud application:
- The frontend and backend communicate securely.
- Automated smoke tests validate every deployment.
- CI/CD pipelines push changes with confidence.
- OIDC roles keep the workflow secure. These are what connecting services, automating deployments, and securing infrastructure that make it a complete application.
Helpful Resources
Here’s what helped me in Chunk 3:
- Cloud Resume Challenge
- Playwright Docs
- CloudFront Invalidation
- GitHub Actions for AWS
- AWS OIDC with GitHub Actions
Let’s Connect
If you’re following this challenge, or just passing by, I’d love to connect! I’m always happy to help if you need guidance, want to swap ideas, or just chat about tech.
I’m also open to new opportunities, so if you have any inquiries or collaborations in mind, let me know!
- 🐙 GitHub
- ✍️ Dev.to Blog
- ✉️ Email Me
Top comments (0)