Static site
Plain HTML/CSS/JS, no build step. A vanilla JS toggle swaps text from data-en/data-es attributes already on each element, including the page <title> and meta description.
The site you're reading right now: a static, bilingual portfolio with no build step, deployed to AWS through a GitHub Actions pipeline that authenticates with a short-lived OIDC token instead of a long-lived access key.
THE SMALLEST PROJECT HERE, ON PURPOSE
Day to day I work in Google Cloud. This site is deliberately on AWS instead — a small, low-stakes place to keep that muscle current. It's plain HTML, CSS, and JavaScript: no bundler, no package install, no framework. The bilingual EN/ES toggle is about 40 lines of vanilla JavaScript that swaps text from data-en/data-es attributes already sitting on each element.
The part worth showing isn't the HTML — it's the pipeline. A push to main syncs the site to S3 and invalidates CloudFront automatically, and the GitHub Actions workflow never holds an AWS access key: it assumes an IAM role for the duration of the job via OpenID Connect, so there's no long-lived secret sitting in a repository setting.
DEPLOY PIPELINE
GitHub Actions assumes a scoped IAM role via OIDC, syncs the website/ folder to S3, and invalidates the CloudFront cache so the change is visible immediately rather than waiting out a TTL.
Three steps, one workflow file: checkout, aws s3 sync --delete ./website s3://<bucket>, aws cloudfront create-invalidation --paths '/*'.
WHAT EACH PIECE DOES
Plain HTML/CSS/JS, no build step. A vanilla JS toggle swaps text from data-en/data-es attributes already on each element, including the page <title> and meta description.
One workflow, triggered on push to main: checkout, assume role, sync, invalidate. No secrets stored in the repository.
The workflow requests a short-lived token and exchanges it for temporary AWS credentials scoped to one IAM role — nothing to rotate, nothing to leak.
S3 holds the synced files; CloudFront fronts it with HTTPS and caching, invalidated on every deploy so changes are visible immediately.
WHY IT'S BUILT THIS WAY