A small learning project where I tried to understand how Vercel works under the hood — taking a Git repo, building it, and serving the static output on a URL — and then built a simplified version of it myself.
I took inspiration from Harkirat Singh's YouTube video on building a Vercel clone.
The project is split into three services that talk to each other through a Redis queue:
-
upload-service — Accepts a
POST /deploywith arepoURL, clones the repo, generates a unique deployid, uploads all the files to object storage (S3 / Cloudflare R2), and pushes theidonto a Redisbuild-queue. Runs on port3000. -
deploy-service — A background worker that pops ids off the
build-queue, downloads the project files, runs the build (npm install && npm run build), and uploads the finaldistoutput back to storage. -
request-handler — Serves the built sites. It reads the project
idfrom the request subdomain (e.g.<id>.localhost:3001) and fetches the matching file from storage. Runs on port3001.
client ──POST /deploy──▶ upload-service ──┐
│ push id
Redis build-queue
│ pop id
▼
deploy-service ──build──▶ storage
browser ──<id>.localhost──▶ request-handler ──fetch──▶ storage
- TypeScript + Node.js
- Express
- Redis (build queue)
- AWS S3 / Cloudflare R2 for storage
- simple-git for cloning repos
Each service is its own package. You'll need Redis running and storage credentials set in a .env file inside each service.
# in each of upload-service / deploy-service / request-handler
npm install
npm run devThis is a learning project built to understand the concepts — it is not meant for production use.