🛠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
- Initialize a Next.js project:
npx create-next-app@latest my-static-site --typescript cd my-static-site
- Configure
next.config.js
for static export:/** @type {import('next').NextConfig} */ module.exports = { output: 'export', trailingSlash: true, };
- Add a Markdown-based blog system:
- Create a
posts
folder and add Markdown files (post.md
) - Use
gray-matter
andremark
to parse Markdown
- Create a
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
- Create an S3 bucket (e.g.,
mypage-static-site
). - Enable static website hosting and set index.html as the default document.
- Upload the
out
folder to S3.
Step 4: Set Up CloudFront for CDN
- Create a CloudFront distribution.
- Set the S3 bucket as the origin.
- Enable custom domain support.
- 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
- 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:
- Go to CloudFront > Functions and create a new function.
- 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; }
- 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
Service | Estimated 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!