avatar

Niki Tech

受託開発のほかにも、独自に開発しているアプリもあります🚀

🛠Deploying a Static Website with Next.js, Markdown Posts, GitHub Actions, and AWS (S3, CloudFront, Route 53) With 1$/month

2025-04-04

Deploying a Static Website with Next.js, Markdown Posts, GitHub Actions, and AWS (S3, CloudFront, Route 53) With 1$/month

This guide explains how to set up a static website using Next.js, write posts in Markdown, automate deployment with GitHub Actions, and host the site on AWS using S3, CloudFront, and Route 53—all within a budget of under $1 per month.

Prerequisites

  • AWS Account
  • GitHub Account
  • Domain name (registered in Route 53 or another provider)
  • Node.js installed

Step 1: Create a Next.js Static Website

  1. Initialize a Next.js project:
    npx create-next-app@latest my-static-site --typescript cd my-static-site
  2. Configure next.config.js for static export:
    /** @type {import('next').NextConfig} */ module.exports = { output: 'export', trailingSlash: true, };
  3. Add a Markdown-based blog system:
    • Create a posts folder and add Markdown files (post.md)
    • Use gray-matter and remark to parse Markdown

Step 2: Build and Export Static Files

Run the following command to generate static files:

npm run build && npm run export

The files will be available in the out directory.

Step 3: Configure AWS S3 for Hosting

  1. Create an S3 bucket (e.g., mypage-static-site).
  2. Enable static website hosting and set index.html as the default document.
  3. Upload the out folder to S3.

Step 4: Set Up CloudFront for CDN

  1. Create a CloudFront distribution.
  2. Set the S3 bucket as the origin.
  3. Enable custom domain support.
  4. Configure CloudFront to use HTTPS with AWS Certificate Manager.
    • Request a free SSL/TLS certificate in AWS Certificate Manager.
    • Attach the certificate to the CloudFront distribution.
    • Redirect HTTP to HTTPS in CloudFront settings.

Step 5: Configure Route 53

  1. Add an Alias pointing to CloudFront.

Step 6: Automate Deployment with GitHub Actions

Create .github/workflows/deploy.yml:

name: Build and Deploy on: push: branches: - main permissions: id-token: write contents: read jobs: build-and-deploy: name: Build and Deploy runs-on: ubuntu-latest env: S3_BUCKET_NAME: your_domain CLOUDFRONT_DISTRIBUTION_ID: your_cloudfront_id NEXTJS_DIST: out AWS_REGION: ap-northeast-1 strategy: matrix: node-version: [16.x] steps: - name: Checkout code uses: actions/checkout@v2 - name: Configure AWS credentials from AWS account uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: arn:aws:iam::your_iam_id:role/github-to-aws aws-region: ap-northeast-1 - name: Set up Node.js uses: actions/setup-node@v2 with: node-version: '16' - name: Install dependencies run: npm install - name: Build Static Site run: npm run build - name: Copy files to S3 run: aws s3 sync --delete out s3://your_s3_bucket - name: Copy files to production run: aws cloudfront create-invalidation --distribution-id your_cloudfront_id --paths '/*' - name: Deploy run: | # Add your deployment commands here # For example, you can use rsync, scp, or any other deployment method

Step 7: Redirect URLs Without index.html Using CloudFront Function

To ensure users accessing URLs without index.html are properly redirected, create a CloudFront Function:

  1. Go to CloudFront > Functions and create a new function.
  2. Add the following JavaScript code:
    function handler(event) { var request = event.request; var uri = request.uri; // If the URI doesn't contain a file extension, append index.html if (!uri.includes('.') && !uri.endsWith('/')) { request.uri += '/index.html'; } return request; }
  3. Attach the function to the CloudFront distribution as a viewer request function.

Step 8: Optimize Costs

  • Use S3 Standard-IA storage class.
  • Enable CloudFront caching.
  • Use Route 53 for DNS resolution.

Estimated Monthly Cost

ServiceEstimated Cost
S3 Storage~$0.20
CloudFront~$0.30
Route 53~$0.50
Total~$1.00

Now, your static website is live and automatically updated with each GitHub commit!