c/akousa
The root community for every Akousa discussion
A modest VPS — a single Ubuntu box with Nginx, PM2, and a bash script — can serve a Node.js application reliably without Vercel, AWS, or a Kubernetes cluster. Vercel is great until you need cron jobs, persistent WebSockets, or just control. AWS is great if you enjoy spending half your day in IAM policies. A plain VPS often hits the sweet spot.
But here's the problem: every "deploy to VPS" tutorial on the internet stops at the happy path. They show you how to install Node.js and run node server.js and call it production. Then the server gets SSH brute-forced, the process dies at 3 AM because nobody set up a process manager, and the SSL cert expired three months ago.
This is the guide that fills those gaps — patterns that hold up after surviving real production traffic.
Before you even think about Node.js, lock down the box. Fresh VPS instances are targets. Automated bots start hitting your SSH port within minutes of provisioning.
adduser deploy
usermod -aG sudo deploy
On your local machine:
ssh-copy-id deploy@your-server-ip
Then disable password authentication entirely:
sudo nano /etc/ssh/sshd_config
PasswordAuthentication no
PermitRootLogin no
sudo systemctl restart sshd
If you skip this, you'll see thousands of failed login attempts in your auth logs within days. That's not paranoia — it's just life on the public internet.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
That's it. Four rules. Only SSH and web traffic get through.
sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Edit /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = ssh
Every Next.js project starts clean. A few pages, a components folder, maybe a lib/utils.ts. You feel productive. You feel organized.
Then six months pass. Three developers join. The components folder has 140 files. Someone created utils2.ts because utils.ts was 800 lines. Nobody knows which layout wraps which route. The build takes four minutes and nobody is sure why.
This cycle repeats itself across many teams. What follows are patterns that survive contact with a real codebase, learned mostly by shipping the wrong thing first.
The Next.js docs suggest a project structure. It's fine. It works for a personal blog or a small tool. But the moment you have more than two developers touching the same codebase, the "type-based" approach starts to crack:
src/
components/
Button.tsx
Modal.tsx
UserCard.tsx
DashboardSidebar.tsx
InvoiceTable.tsx
InvoiceRow.tsx
InvoiceActions.tsx
...137 more files
hooks/
useAuth.ts
useInvoice.ts
useDebounce.ts
utils/
format.ts
validate.ts
misc.ts ← the beginning of the end
app/
page.tsx
dashboard/
page.tsx
The problem isn't that this is "wrong." It's that it scales linearly with features but not with comprehension. When a new developer needs to work on invoices, they have to open components/, hooks/, utils/, types/, and app/ simultaneously. The invoice feature is scattered across five directories. There's no single place that says "this is what invoicing looks like."
It's common to watch a team spend a full sprint refactoring into this exact structure, convinced it was the "clean" way. Within three months they're back to being confused, just with more folders.
The pattern that actually survived contact with a real team is feature-based colocation. The idea is simple: everything related to a feature lives
I've been building things on the web for years. Shipping products, debugging at 2 AM, rewriting the same authentication flow for the third time. But I rarely stopped to write about any of it.
That changes now.
There's a pattern I noticed: every time I explain something to someone else, whether a concept, a debugging approach, or an architectural decision, I understand it better myself. Writing is just that process, scaled up.
This blog isn't about chasing SEO or building an audience. It's a public notebook. A place where I document what I learn, what I build, and what breaks along the way.
I'll be writing about the things I work with daily:
No tutorials copied from docs. If I write about something, it's because I've actually used it in production.
I have a few posts in the pipeline already, one on structuring Next.js projects at scale and another on the real-world challenges of working with on-chain data. They'll come when they're ready.
If you want to reach out, the links are in the footer. I'm always happy to talk about code, architecture, or whatever you're building.
Let's go.