← Back to Blog

Building and Deploying a Modern Portfolio: From Local Development to AWS EC2

In this project, I moved beyond simple static hosting to deploy a professional-grade Next.js application on Amazon Web Services (AWS). This post documents the technical journey of setting up a robust deployment pipeline using Git, Nginx, and PM2.

The Tech Stack

  • Frontend: Next.js 15, Tailwind CSS, TypeScript
  • Hosting: AWS EC2 (Amazon Linux)
  • Web Server: Nginx (Reverse Proxy)
  • Process Management: PM2
  • Version Control: Git & GitHub

Phase 1: Local Development & Version Control

The project began in VS Code. To ensure the code was portable and ready for production, I initialized a Git repository and established a connection to GitHub.

Key Commands (PowerShell):

git init
git add .
git commit -m "Initial commit: Next.js Portfolio"
git remote add origin https://github.com/FrederickAtasina/my-portfolio-website.git
git push -u origin main

Challenge Overcome: I initially encountered "Repository not found" errors due to a remote URL mismatch. I resolved this by using git remote set-url to point to the correct GitHub repository, ensuring my local environment and remote origin were perfectly synced.

Phase 2: Server Environment Setup

On the AWS EC2 instance, I needed an environment capable of building modern React applications.

Updating the Engine

Next.js 15 requires Node.js v20.9.0 or higher. My server was initially running v18. To fix this, I implemented NVM (Node Version Manager) to upgrade the environment without breaking system dependencies.

nvm install 20
nvm use 20

Phase 3: Deployment & Build Process

Once the environment was ready, I cloned the repository and executed the production build.

  • Cloning: git clone [repository-url]
  • Dependencies: npm install
  • Optimization: npm run build — This step generates optimized static pages and server-side logic, significantly improving the site's Core Web Vitals.

Phase 4: Production Management (PM2 & Nginx)

To make the site "production-ready," I needed it to stay online 24/7 and handle web traffic efficiently.

1. Process Management with PM2

Instead of running the app in a temporary terminal session, I used PM2 to manage the Node.js process in the background. This ensures the app restarts automatically if the server reboots.

pm2 start npm --name "portfolio" -- start
pm2 save
pm2 startup

2. Nginx Reverse Proxy

I configured Nginx to act as a "traffic controller." It handles incoming requests on Port 80 (HTTP) and Port 443 (HTTPS) and safely routes them to the Next.js app running locally on Port 3000.

location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
}

Lessons Learned

  • Version Alignment: Matching local and server Node.js versions is critical for build stability.
  • Resource Management: Handling Next.js builds on a t2.micro instance requires careful monitoring of memory usage.
  • Deployment Logic: Mastering the bridge between a git push on a laptop and a live update on a remote server is the foundation of modern DevOps.

Final Thoughts

Setting up this pipeline taught me that being a developer isn't just about writing code; it's about understanding the infrastructure that delivers that code to the world. My portfolio is now more than just a site—it's a testament to a complete deployment workflow.