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 mainChallenge 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 20Phase 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 startup2. 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.