Essay
←Back to blogI Built Vercel on a Phone. A Rooted Android Phone.
Normal people pay $20/month for Vercel. I built the entire thing on a Snapdragon 660 with 4 GB of RAM running in a terminal emulator. This is normal behavior.
I Turned My Old Phone Into a Vercel Clone. Please Don't Ask Why.
Normal people: pays $20/month for hobby project hosting. Me: roots phone, installs Termux, rewrites deployment infrastructure from scratch at midnight.
Both are valid approaches to the problem. I'm not here to judge. I'm here to explain the sequence of decisions that led to me configuring Nginx on a Snapdragon 660 while the phone was also playing a lo-fi playlist.
The Inciting Incident
I had a rooted Android phone sitting in a drawer. I wanted to host some side projects. Vercel exists. Railway exists. Render exists.
I chose the drawer phone.
What Is MiniShinobi
It's a self-hosted, Vercel-like deployment platform that runs entirely inside Termux on a rooted Android device. You connect a GitHub repo, hit Deploy, and your project goes live on a real subdomain over HTTPS via Cloudflare Tunnel — all from a device that charges next to your bed at night.
The stack: Node.js backend, Vite/React dashboard, Nginx reverse proxy, PM2 for process management, sql.js for the database, and cloudflared for tunnels. All of it supervised by PM2 on a phone.
"We'll Just Use sql.js"
The first design constraint: you cannot compile better-sqlite3 on ARM Termux. Native Node addon compilation on ARM is a special kind of unpleasant that I don't recommend.
So the database runs on sql.js — SQLite compiled to WebAssembly. Zero native compilation, zero segfaults. Every write flushes the entire database buffer to disk. The database is small. The phone has 4 GB of RAM. This is fine.
It's cursed in a way that is technically completely fine.
"We'll Just Use child_process"
Similarly, node-pty needs native compilation. You know how that story ends.
So the entire deployment engine — git clone, npm install, npm run build, framework detection, process spawn — runs through Node's built-in child_process.spawn. Every byte of stdout and stderr is line-buffered and streamed live to the browser via Server-Sent Events. You watch your build happen in real-time from the dashboard, which is serving you that stream from a phone in your drawer.
Does it feel like it should work? No. Does it work? The phone is serving things to the open internet right now.
"We'll Just Use PM2"
pm2 start ecosystem.config.js and everything wakes up: the Express backend, Nginx, and cloudflared. Three supervised processes, one config file. If anything crashes, PM2 restarts it. On a phone.
This is the part where I discovered PM2 is genuinely great and I should have been using it everywhere.
The Build Queue (The Unsexy Correct Decision)
4 GB of RAM sounds fine until npm run build on a React app invites the OOM killer to the party.
There's a serialized build queue. One build at a time. If you deploy two projects simultaneously, one waits. It's not exciting. It's the right call for a device with less RAM than most laptops have VRAM.
I also added 1 GB of swap. Don't look at me like that.
Cloudflare Tunnels Are Legitimately Magic
cloudflared is the part that makes all of this actually work. You run one daemon, write a YAML config, and localhost:3000 is suddenly reachable at your-project.yourdomain.com over HTTPS with a valid certificate.
No port forwarding. No public IP. No router config. No DynDNS prayers. Every deployment gets its own named tunnel. Every project gets its own subdomain. The phone sitting in a drawer is serving real traffic on the real internet.
Does It Actually Work?
Build logs stream live. Deployments go live. GitHub OAuth works. Static sites and Node apps both deploy. The framework detector auto-detects Next.js, Vite, and plain static sites. SSL certificates are valid.
Running on a Snapdragon 660, 4 GB RAM, PixelExperience Android 13. The phone is also charging. The lo-fi playlist is still going.
Did I need to build this? No. Do I have a full deployment dashboard running on a rooted Android phone for exactly $0/month? Yes.
That's just engineering.
MiniShinobi is open source. If you have a rooted Android phone gathering dust and a questionable relationship with free time, the README has every command. I already did the part where you discover why you shouldn't do this. You get to skip straight to the part where it works.