Production Static Website Hosting on AWS Amplify

How ranjithr.com — my real, live personal portfolio, not a demo — is hosted on AWS Amplify with CloudFront, ACM, and Route 53, deployed straight from GitHub with automated CI/CD and HTTPS by default.

GitHubAWS AmplifyCloudFrontACMRoute 53S3Google Analytics
6 min readIntermediate
Section 01

Executive Summary

This is a live case study, not a tutorial — it documents exactly how ranjithr.com, my real personal portfolio, is hosted on AWS today. To be specific about what this is: it is a production static website, not an AWS application or server deployment — there is no compute instance, container, or backend runtime anywhere in this stack. Every push to the main branch on GitHub goes through a fully automated pipeline and is live within minutes, with no server to patch, no manual deploy step, and no dedicated DevOps time spent keeping it online.

The stack is deliberately different from the other two AWS projects on this site. AWS Static Website Hosting and AWS Dynamic Website Hosting both wire S3/EC2, CloudFront, ACM, and Route 53 together by hand to show how the primitives fit. This deployment instead leans on AWS Amplify as a managed layer over the same primitives — it provisions and operates the CloudFront distribution and the TLS certificate itself (and stores the static build output in S3 behind the scenes), triggered directly from GitHub. The trade-off is less manual control in exchange for a genuinely hands-off, git-driven release process, which is the right trade for a portfolio site that changes often and has no ops budget.

  • Source of truth: a single GitHub repository, deployed from the main branch.
  • Build & hosting: AWS Amplify — managed CI/CD, static build output, and CDN distribution.
  • DNS: Route 53 hosted zone for ranjithr.com, aliased to the Amplify/CloudFront domain.
  • TLS: AWS Certificate Manager, issued and renewed automatically for the custom domain.
  • Analytics: Google Analytics, loaded client-side to track visitors and engagement — kept separate from the AWS hosting stack itself.
Section 02

Architecture Diagram

A commit becomes a live page through one straight-line path: GitHub triggers Amplify, Amplify serves the build through CloudFront, CloudFront is secured by an ACM certificate, and Route 53 resolves ranjithr.com to that distribution. Google Analytics is kept deliberately separate from this hosting chain — it runs client-side in the visitor's browser after the page has already loaded, and has no part in serving the site itself.

GitHub → AWS Amplify (Hosting + CI/CD) → CloudFront (CDN) → ACM (HTTPS/TLS) → Route 53 (DNS) → ranjithr.com, with Google Analytics tracking visits separately

Section 03

AWS Services & Cost Estimation

Every service below is one this deployment actually uses today — nothing here is invented or hypothetical. Rather than guess a dollar figure that would go stale, each row lists the cost model AWS actually bills it under. Most of it is usage-based, which is why a low-traffic personal portfolio like this one tends to run for very little — but that is not the same as free, and the real number always depends on your own traffic and usage.

Cost model, not a quote

The table below shows how each service is billed, not a fixed price. Most of these are usage-based AWS services, so the actual charge depends on traffic, storage, requests, and build frequency — and can change as AWS updates its pricing. For a number based on your own usage, use the AWS Pricing Calculator and check the current AWS Free Tier terms.
Purpose
Static website hosting + CI/CD
Cost model
Usage-based
Purpose
CDN and content delivery
Cost model
Usage-based
Purpose
DNS management
Cost model
Hosted zone + DNS queries
Purpose
SSL/TLS certificate
Cost model
Free for public certificates
Purpose
Static/build asset storage
Cost model
Usage-based
Purpose
Source code + deployment trigger
Cost model
Free tier / plan dependent
Purpose
Website analytics
Cost model
Free
Low-Traffic Personal Portfolio
Monthly Cost Can Remain Very Low
Actual cost depends on traffic, requests, storage and other usage — nothing here is billed at a flat rate, and no monthly cost is guaranteed.
Section 04

Deployment Workflow

There is exactly one way a change reaches production: push to main. Amplify owns everything after that.

  • Push (or merge) to the main branch on GitHub.
  • GitHub's webhook notifies Amplify that a new commit landed.
  • Amplify spins up a managed build image and installs dependencies.
  • Amplify runs the build command, producing the production output.
  • Amplify deploys the new build behind its CloudFront distribution and invalidates stale cache.
  • The new version is live at ranjithr.com, typically within a few minutes of the push.

Amplify reads its build steps from a build spec checked into the repo:

amplify.yml
version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm ci
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: .next
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
      - .next/cache/**/*

No manual deploy step, on purpose

There is no aws s3 sync or CLI deploy command anywhere in this workflow — the entire point of choosing Amplify here was to remove that step. A broken build simply fails the Amplify job and never reaches production; the previous deployment keeps serving traffic.
Section 05

Security

  • HTTPS everywhere — CloudFront redirects all HTTP traffic to HTTPS, and the ACM certificate is validated and renewed automatically with no manual step.
  • Secrets stay out of git — analytics IDs and any environment-specific values are set as Amplify environment variables, scoped to the branch, never committed to the repository.
  • Least-privilege deploys — Amplify's GitHub integration only needs read access to the repository and its own service role to publish; it never needs direct IAM credentials checked into CI config.
  • Immutable releases — every deploy is a new, versioned Amplify build; rolling back means re-promoting a previous build, not hand-editing anything live.

Branch previews are still public URLs

Amplify can auto-deploy a preview for every branch/PR. Preview URLs are reachable by anyone who has the link, so treat them the same as production for anything sensitive — don't rely on obscurity.
Section 06

Performance

CloudFront serves every static asset from an edge location near the visitor, so repeat views and navigations feel effectively instant. Next.js's own build output (pre-rendered pages, code-split JavaScript, optimized images) means the origin rarely has to do real work on a cache hit.

  • Fingerprinted, hashed build assets get long-lived, immutable cache headers.
  • HTML is revalidated frequently so a fresh deploy becomes visible without waiting on a manual cache invalidation.
  • Images are served through Next.js's image pipeline rather than as unoptimized originals.
Section 07

Monitoring & Analytics

Monitoring here is intentionally lightweight, matching the size of the project:

  • Amplify build notifications — every build's pass/fail status is visible in the Amplify console and can email or notify on failure.
  • Google Analytics — pageviews, traffic sources, and custom events (like the interactions tracked elsewhere on this site) for understanding real visitor behavior. It runs entirely client-side and is kept separate from the AWS hosting stack itself.
  • Uptime — CloudFront and Amplify's hosting are managed AWS services with their own published availability SLAs, so there is no separate uptime monitor to run for the hosting layer itself.
Section 08

Project Highlights

  • Zero-touch deploys — a git push is the entire release process, end to end.
  • Custom domain with fully managed, auto-renewing TLS — no certificate to track manually.
  • Global CDN distribution included by default, with no separate CloudFront setup step.
  • Effectively no infrastructure maintenance — nothing to patch, back up, or scale.
  • Usage-based AWS cost model, which stays very low for a low-traffic personal site like this one.
Section 09

Challenges

Rewrites & redirects on a managed platform

Next.js's own routing config and Amplify's rewrite/redirect rules can overlap. Getting trailing-slash behavior and the custom 404 to match what worked locally took a few iterations of Amplify's console-level rewrite rules.

Branch-scoped environment variables

Environment variables in Amplify are per-branch by default. It's easy to set a value on main and forget a preview branch needs it too, which surfaces as a feature working in production but silently missing on a PR preview.

Cache visibility after a deploy

Because CloudFront invalidation happens automatically as part of an Amplify deploy, it's not always obvious from the console alone whether a specific change has finished propagating — a hard refresh and checking the deployed commit hash is the reliable way to confirm.
Section 10

Lessons Learned

  • A managed platform like Amplify trades some low-level control (you don't touch the CloudFront distribution or bucket directly) for a much shorter path from commit to production — worth it for a fast-moving personal site, less so for a system that needs fine-grained infrastructure control.
  • Keeping the build spec (amplify.yml) in the repository, rather than only in the console, means the entire deploy process is reviewable in a pull request like any other code change.
  • Treating preview URLs as public by default, from day one, avoided ever having to retroactively lock one down.
Section 11

Documentation & References

Section 12

Final Result

The outcome is a real, production static website that deploys itself: a push to main becomes a live, HTTPS-secured, globally-cached update at ranjithr.com with no manual step in between, running on a usage-based AWS cost model that stays very low for a site at this traffic level — though, since every AWS service here bills by usage rather than a flat fee, the actual cost always depends on traffic and resource usage, not a fixed number. For a personal project, that ratio of automation to operating cost is the entire point of building it this way.