Skip to content

ujjwalkirti/mini-vercel

Repository files navigation

Mini-Vercel

A self-hosted deployment platform that demonstrates a Vercel-like workflow. Deploy your static sites with Git integration, real-time build logs, and automatic subdomain routing.

Overview

Mini-Vercel consists of four main services working together:

Service Port Description
api-server 9000 Control plane API - handles projects, deployments, and build orchestration
frontend 5173 React dashboard for managing projects and viewing deployment logs
reverse-proxy 8001 Routes subdomain requests to deployed static assets
build-project Container Clones repos, runs builds, uploads artifacts to storage

Architecture

                                    +------------------+
                                    |    Frontend      |
                                    |   (React UI)     |
                                    +--------+---------+
                                             |
                                             v
+---------------+    Deploy Request    +------------------+
|    User       | ------------------> |   API Server     |
+---------------+                      |   (Express)      |
                                      +--------+---------+
                                               |
                          +--------------------+--------------------+
                          |                    |                    |
                          v                    v                    v
                   +--------------+     +--------------+      +--------------+
                   |  PostgreSQL  |     |    Kafka     |      |  AWS ECS     |
                   |  (Supabase)  |     |              |      |  (Fargate)   |
                   +--------------+     +------+-------+      +------+-------+
                                               |                     |
                                               |               +-----v------+
                                               |               |   Build    |
                                               |               | Container  |
                                               |               +-----+------+
                                               |                     |
                                               v                     v
                                        +--------------+     +--------------+
                                        | ClickHouse   |     |Cloudflare R2 |
                                        |   (Logs)     |     |  (Storage)   |
                                        +--------------+     +------+-------+
                                                                    |
+---------------+    subdomain.localhost:8001    +------------------v--------+
|  End User     | <---------------------------- |    Reverse Proxy          |
+---------------+                                +---------------------------+

Features

  • Git-based Deployments - Deploy directly from GitHub repositories
  • Real-time Build Logs - Stream build output via Kafka to ClickHouse
  • Automatic Subdomains - Each project gets a unique subdomain
  • Deployment Status Tracking - Track builds through QUEUED -> IN_PROGRESS -> READY/FAIL
  • User Authentication - Supabase-powered auth with protected routes
  • Rate Limiting - Production-grade API protection
  • Input Validation - Express-validator for request validation

Tech Stack

Backend

  • Runtime: Node.js 20+ with TypeScript
  • Framework: Express.js 5
  • Database: PostgreSQL (Supabase) with Prisma ORM
  • Message Queue: Apache Kafka
  • Analytics: ClickHouse
  • Container Orchestration: AWS ECS Fargate
  • Storage: Cloudflare R2 (S3-compatible)
  • Authentication: Supabase Auth

Frontend

  • Framework: React 19 with TypeScript
  • Build Tool: Vite
  • Styling: Tailwind CSS
  • UI Components: Radix UI
  • Routing: React Router DOM

Repository Structure

mini-vercel/
├── api-server/                 # Control plane API
│   ├── src/
│   │   ├── server.ts          # Express app & Kafka consumer
│   │   ├── controllers/       # Request handlers
│   │   ├── routes/            # Route definitions
│   │   ├── middleware/        # Auth, CORS, rate limiting, validation
│   │   ├── validators/        # Input validation schemas
│   │   ├── config/            # Service configurations
│   │   ├── utils/             # Logger, response helpers
│   │   └── lib/               # Prisma client
│   ├── prisma/
│   │   └── schema.prisma      # Database schema
│   ├── Dockerfile             # Container image
│   └── docker-compose.yml     # Local Kafka & ClickHouse
│
├── frontend/                   # React dashboard
│   ├── src/
│   │   ├── pages/             # Page components
│   │   ├── components/        # Reusable UI components
│   │   ├── contexts/          # Auth context
│   │   └── lib/               # API client, Supabase
│   └── vite.config.ts
│
├── reverse-proxy/              # Static asset routing
│   ├── src/
│   │   ├── reverse-proxy.ts   # Proxy logic
│   │   └── lib/               # Prisma client
│   ├── prisma/
│   │   └── schema.prisma
│   └── Dockerfile             # Container image
│
├── build-project/              # Build runner container
│   ├── script.js              # Build pipeline
│   ├── kafkaProducer.js       # Log streaming
│   ├── r2Blob.js              # R2 upload
│   └── Dockerfile
│
└── Readme.md

Getting Started

Prerequisites

  • Node.js 20+
  • Docker & Docker Compose
  • AWS Account (for ECS)
  • Supabase Project
  • Cloudflare R2 Bucket
  • Kafka Cluster (Aiven or self-hosted)
  • ClickHouse Instance

Installation

# Clone the repository
git clone https://github.com/yourusername/mini-vercel.git
cd mini-vercel

# Install dependencies for all services
cd api-server && npm install
cd ../frontend && npm install
cd ../reverse-proxy && npm install
cd ../build-project && npm install

Environment Setup

API Server (api-server/.env)

# AWS ECS
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=

# ECS Task Configuration
ECS_CLUSTER_NAME=
ECS_TASK_DEFINITION=
ECS_SUBNETS=                    # Comma-separated
ECS_SECURITY_GROUPS=            # Comma-separated
ECS_ASSIGN_PUBLIC_IP=ENABLED
ECS_IMAGE_NAME=
ECS_LAUNCH_TYPE=FARGATE
ECS_COUNT=1

# Database (Supabase PostgreSQL)
DATABASE_URL=postgresql://...

# Kafka
KAFKA_BROKERS=
KAFKA_USERNAME=
KAFKA_PASSWORD=
KAFKA_SSL=true

# Cloudflare R2
R2_ACCOUNT_ID=
R2_ACCESS_KEY_ID=
R2_SECRET_ACCESS_KEY=
R2_BUCKET_NAME=
R2_PUBLIC_URL=

# ClickHouse
CLICKHOUSE_HOST=
CLICKHOUSE_PORT=8443
CLICKHOUSE_DATABASE=
CLICKHOUSE_USERNAME=
CLICKHOUSE_PASSWORD=

# Server
NODE_ENV=development
PORT=9000

# CORS
FRONTEND_URL=http://localhost:5173

# Supabase Auth
SUPABASE_URL=
SUPABASE_SERVICE_ROLE_KEY=

Frontend (frontend/.env)

VITE_API_URL=http://localhost:9000
VITE_SUPABASE_URL=
VITE_SUPABASE_ANON_KEY=

Reverse Proxy (reverse-proxy/.env)

R2_PUBLIC_URL=https://pub-xxx.r2.dev
DATABASE_URL=postgresql://...

Database Setup

# Generate Prisma client
cd api-server
npx prisma generate

# Push schema to database
npx prisma db push

# Repeat for reverse-proxy
cd ../reverse-proxy
npx prisma generate

Running Locally

# Terminal 1: Start infrastructure (Kafka, ClickHouse)
cd api-server
docker-compose up

# Terminal 2: Start API server
cd api-server
npm run dev

# Terminal 3: Start Reverse Proxy
cd reverse-proxy
npm run dev

# Terminal 4: Start Frontend
cd frontend
npm run dev

Docker Deployment

Building Docker Images

# Build API Server
cd api-server
docker build -t mini-vercel-api:latest .

# Build Reverse Proxy
cd ../reverse-proxy
docker build -t mini-vercel-proxy:latest .

# Build Project Builder
cd ../build-project
docker build -t mini-vercel-build:latest .

Running with Docker

# Run API Server
docker run -d \
  --name mini-vercel-api \
  -p 9000:9000 \
  --env-file .env \
  mini-vercel-api:latest

# Run Reverse Proxy
docker run -d \
  --name mini-vercel-proxy \
  -p 8001:8001 \
  --env-file .env \
  mini-vercel-proxy:latest

Pushing to Registry

# Tag and push to your registry
docker tag mini-vercel-api:latest your-registry/mini-vercel-api:latest
docker push your-registry/mini-vercel-api:latest

docker tag mini-vercel-proxy:latest your-registry/mini-vercel-proxy:latest
docker push your-registry/mini-vercel-proxy:latest

docker tag mini-vercel-build:latest your-registry/mini-vercel-build:latest
docker push your-registry/mini-vercel-build:latest

API Endpoints

Health

Method Endpoint Description
GET /health Health check

Projects

Method Endpoint Description
GET /projects List all projects
GET /projects/:id Get project details
POST /projects Create new project
DELETE /projects/:id Delete project

Deployments

Method Endpoint Description
GET /projects/:projectId/deployments List deployments
GET /deployments/:id Get deployment details
GET /deployments/:id/logs Get deployment logs
POST /deploy Trigger new deployment

Deployment Flow

  1. User triggers deployment via frontend or API
  2. API server creates deployment record with status QUEUED
  3. AWS ECS task spawns build container with project config
  4. Build container:
    • Clones Git repository
    • Runs npm install and npm run build
    • Streams logs to Kafka
    • Uploads dist/ to Cloudflare R2
  5. API server consumes Kafka logs:
    • Updates status to IN_PROGRESS on build start
    • Updates status to READY on success
    • Updates status to FAIL on error
    • Stores logs in ClickHouse
  6. Reverse proxy routes traffic to the deployed assets

Database Schema

model Project {
  id           String        @id @default(uuid())
  name         String
  gitURL       String
  subDomain    String        // Auto-generated slug
  customDomain String?
  userId       String
  Deployment   Deployment[]
  createdAt    DateTime      @default(now())
  updatedAt    DateTime      @updatedAt
}

model Deployment {
  id        String           @id @default(uuid())
  projectId String
  project   Project          @relation(...)
  status    DeploymentStatus @default(NOT_STARTED)
  createdAt DateTime         @default(now())
  updatedAt DateTime         @updatedAt
}

enum DeploymentStatus {
  NOT_STARTED
  QUEUED
  IN_PROGRESS
  READY
  FAIL
}

Rate Limiting

Limiter Limit Use Case
apiRateLimiter 100/min General API endpoints
authRateLimiter 10/min Authentication endpoints
deployRateLimiter 10/min Deployment triggers
logsRateLimiter 60/min Log fetching
strictRateLimiter 5/min Sensitive operations

Ports Reference

Service Port Protocol
API Server 9000 HTTP
Frontend (dev) 5173 HTTP
Reverse Proxy 8001 HTTP
Zookeeper 2181 TCP
Kafka 9092-9094 TCP
ClickHouse HTTP 8123 HTTP
ClickHouse Native 9001 TCP

Production Considerations

  • Enable HTTPS/TLS on all services
  • Use proper secrets management (AWS Secrets Manager, Vault)
  • Set up monitoring and alerting (Prometheus, Grafana)
  • Configure CDN for static assets
  • Implement deployment rollbacks
  • Add build timeout handling
  • Set up database connection pooling

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Commit your changes
  4. Push to the branch
  5. Open a Pull Request

License

MIT License - See LICENSE file for details.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors