How I Built and Deployed My React + Next.js Portfolio with Node.js and Docker
As a full-stack developer, having a personal website isn’t just a nice-to-have — it’s your digital handshake.
I wanted mine to reflect not only my projects, but the tech I use daily: React, Node.js, containers, CI/CD — the works.
Here’s how I built luisfaria.dev from the ground up.
The Stack
- Frontend: Next.js — React framework with SSR support
- Backend: Node.js API (Express-flavored)
- Deployment: Dockerized everything and hosted on DigitalOcean
- Reverse Proxy: Nginx container
- Domain & SSL: Let’s Encrypt + custom DNS
- Extras: GitHub Actions, Certbot, and a dash of stubbornness
1. Scaffolding the Project
Started with:
npx create-next-app@latest
This gave me a solid file structure with pages/, public/, and API routes baked in.
I created a custom _app.tsx, dynamic routing for my /projects page, and styled everything with Tailwind CSS.
2. Backend Setup
I created a lightweight Node.js API to handle future blog posts and contact form entries
(eventually hooked into a headless CMS or Supabase).
3. Dockerizing Everything 🐳
This was non-negotiable.
I created:
frontend/Dockerfilebackend/Dockerfiledocker-compose.yml
To fit it all in!
4. SSL, DNS, and The Headache
I mapped luisfaria.dev to my droplet using an A record.
Then used Certbot inside the Nginx container to generate my SSL certificates.
But here’s the real kicker:
My local /etc/hosts file still pointed to an old IP from months ago (157.245.x.x)
I flushed DNS, restarted routers: nothing. The fix?
Overwriting the record manually in /etc/hosts.
Always double-check your local DNS overrides.
5. Rebuilding From Scratch
For a clean restart:
docker-compose down --volumes --remove-orphans docker-compose build --no-cache docker-compose up -d
This guaranteed my containers weren’t holding onto any stale image cache.
6. Final Touches
- Clean SEO tags for pages
- Lighthouse optimization
- Minimalistic design focused on performance and clarity
Key Takeaways
- DNS issues can masquerade as app bugs — always check your IP resolution.
- Docker networking is powerful, but naming your services correctly in
proxy_passmatters. - Nginx + Let’s Encrypt + Next.js is a beautiful trio — once you tame them.
The Result
My site is now live at https://luisfaria.dev — secure, fast, and 100% mine.
If you’re building your own dev portfolio, feel free to fork mine or drop a question below.
I’m happy to help others skip the landmines I stepped on. 😅