How this site is built
This portfolio is itself a project: a small but production-shaped serverless system on AWS, defined entirely as code.
/*
/api/*
Design decisions
Static frontend, serverless backend
The Next.js site is statically exported and served from a private S3 bucket through CloudFront with Origin Access Control. There are no servers to patch, and hosting costs cents.
Same-origin API through CloudFront
CloudFront routes /api/* to an API Gateway HTTP API. The browser never makes a cross-origin call, so production needs no CORS. A secret origin header ensures the API only accepts traffic that came through CloudFront.
A bounded, grounded AI agent
The chat Lambda runs a tool-use loop on the Bedrock Converse API. Tools are typed with zod, and the JSON schemas the model sees are generated from the same definitions. The loop is capped at 5 iterations, and answers must be grounded in tool results.
Cost controls by design
Bedrock spend is bounded three ways: API Gateway throttling, a per-IP hourly limit and a global daily quota, each enforced with atomic DynamoDB counters that expire via TTL. An AWS Budget emails me before costs drift.
Event-driven notifications
Contact submissions are written to DynamoDB. A stream with event filtering invokes a notifier Lambda only for new contact items. It uses partial batch responses and an SQS dead-letter queue, so a failed email never blocks or duplicates the others.
Keyless CI/CD
GitHub Actions assumes a narrowly scoped IAM role via OIDC. The role can only drive CloudFormation through a separate execution role, sync site files and invalidate the CDN. No long-lived AWS keys exist anywhere.