SYSTEM ARCHITECTURE

How This Was Built

The portfolio itself is a working demonstration of platform engineering — IaC-provisioned CDN, CI/CD-automated deployments, and a Next.js SSR app wired together with Terraform and AWS Amplify.

DEPLOYMENT PIPELINE

GitHub

Source Control

Main branch — push triggers Amplify CI

→

Amplify CI

Build Pipeline

npm ci → npm run build (Next.js 16 + Turbopack)

→

Next.js 16

SSR Build

App Router, TypeScript, Tailwind CSS v4

→

CloudFront

Amplify Hosting CDN

Global CDN — serves the Next.js app

PHOTO CDN PIPELINE (TERRAFORM)

S3 Bucket

private

→

OAC

sigv4 signing

→

CloudFront

PriceClass_100

→

Browser

immutable cache

Bucket policy scoped to CloudFront ARN via AWS:SourceArn — S3 is never publicly accessible

INFRASTRUCTURE BREAKDOWN

AWS Amplify

Hosting + CI/CD

Amplify detects every push to main and triggers a full build. The build spec (amplify.yml) runs npm ci and npm run build, then Amplify deploys the Next.js output behind CloudFront automatically. No manual deploy steps.

  • Auto-deploy on push to main
  • Build spec: amplify.yml
  • Next.js SSR support via Amplify Hosting
  • Environment variables for CDN URL injection

Terraform

Infrastructure as Code

The photo CDN infrastructure is provisioned with Terraform: a private S3 bucket and a CloudFront distribution connected via Origin Access Control (OAC). The bucket is never publicly accessible — CloudFront is the only allowed reader, scoped by AWS:SourceArn in the bucket policy.

  • S3 bucket: private, public access fully blocked
  • CloudFront OAC: sigv4 signing, replaces legacy OAI
  • Bucket policy: scoped to CloudFront distribution ARN
  • 1-year immutable cache TTL, brotli + gzip compression
  • PriceClass_100: US, Canada, Europe

S3 + CloudFront CDN

Photo Delivery

Portfolio photos are stored in S3 and served via a dedicated CloudFront distribution, separate from the app hosting. This keeps large binary assets out of the deployment pipeline while giving photos their own long-lived cache headers (max-age=31536000, immutable).

  • Photos uploaded via scripts/upload-photos.sh
  • Cache-Control: public, max-age=31536000, immutable
  • CloudFront invalidation on re-upload
  • NEXT_PUBLIC_PHOTO_CDN_URL injected at build time

Next.js 16

Framework

App Router with per-route server and client components. Dynamic case study routes (/projects/[id] and /experience/[slug]) are server components that resolve params and pass them to client content components. Turbopack handles local development. Rajdhani + Geist fonts via next/font.

  • App Router: server components by default
  • Dynamic routes: instant = false for params resolution
  • Turbopack: local dev HMR
  • next/font: Rajdhani (headings), Geist Sans/Mono
  • TypeScript strict mode throughout

FULL STACK

AWS Amplify

Hosting

CloudFront

CDN

S3

Storage

Terraform

IaC

Next.js 16

Framework

TypeScript

Language

Tailwind CSS v4

Styling

Turbopack

Bundler

GitHub

Source Control

Rajdhani

Typography

Framer Motion

Animation

react-type-animation

UI