Skip to content
Annas Ali

Platform

How this site runs

This portfolio is a small production system: static pages on a CDN, a serverless API for live stats, and a pipeline that ships every commit to main. The numbers below are fetched live from that API.

Live

connecting…

Visits
—
API round-trip
—
AWS cost, month to date
—
Last deploy
—

Recent deploys

CommitWhenDurationStatus
This build: 56c18e4, built

Architecture

annasali.cloud architectureSERVERLESS APIVisitorRoute 53 + ACMannasali.cloudCloudFrontTLS · cache · URL rewriteS3 (private)static Astro build · OACGitHub ActionsOIDC · build · sync · invalidateAPI GatewayHTTP API · /api/*LambdaPython 3.12EventBridgedaily cost refreshDynamoDBvisits · deploys · costHTTPSalias/*/api/*syncdeploy record
CloudFront serves both the static site and /api/*, so the browser only ever talks to one origin. There's no CORS and nothing public on S3.

Delivery pipeline

Every push to main runs one GitHub Actions workflow:

  1. Checkout & install. npm ci on Node 22 with cached dependencies
  2. Build. astro build validates content schemas and renders every page and diagram to static HTML
  3. Assume role (OIDC). GitHub → AWS STS web identity; short-lived credentials, no stored keys
  4. Sync to S3. Hashed assets get immutable caching; HTML is revalidated on every request
  5. Invalidate CloudFront. One wildcard invalidation, which is cheap because hashed assets are immutable and never go stale
  6. Record deploy. Writes SHA, duration and run URL to DynamoDB, which feeds the panel above

Guardrails

  • Private origin. The S3 bucket blocks all public access. Only this CloudFront distribution can read it, through Origin Access Control.
  • No long-lived keys. CI assumes an IAM role through GitHub OIDC, limited to this repository’s main branch.
  • Security headers. A CloudFront response-headers policy sets HSTS, CSP, X-Content-Type-Options, frame-ancestors and Referrer-Policy.
  • Least-privilege Lambda. The function can read and update its own DynamoDB table and read Cost Explorer, nothing else. The API has throttling limits.
  • Everything in Terraform. DNS, certificates, CDN, API, IAM and alarms, with state in Terraform Cloud.

Why this shape

Static HTML is the cheapest, fastest and most secure thing to serve, so everything that can be decided at build time is: résumé content, case studies and diagrams. The only runtime piece is the small API behind this page. The earlier version of this site stored the résumé in DynamoDB and rendered it in the browser, which meant two copies of the truth that drifted apart. Now there's one JSON file, validated at build time.