End-to-end flow
Main components
Express 5 HTTP server
The entry point (src/index.ts) creates an Express application and mounts route modules under the /api prefix. Each route family has its own file under src/routes/ and a corresponding controller under src/controller/. Protected routes run the isAuth middleware, which validates the JWT before the controller is reached. The server listens on port 8080.
Socket.io real-time log streaming
A Socket.io server is attached to the same HTTP server. After a client authenticates (theSocketAuth middleware validates the JWT on the WebSocket handshake), the socket joins a room named after the user’s numeric database ID. The build engine emits all log lines and status changes to that room so only the owning user receives them.
Build engine (buildEngine.ts)
runBuild is the core of the CI pipeline. It receives a project record (including the user’s GitHub token and any associated secrets), a build record, and the Socket.io server instance. It orchestrates every step from cloning to cleanup: writing secrets to a .env file, authenticating the clone URL, detecting the framework, generating a fallback Dockerfile, running docker build, and then running the built image with a volume mount so build output persists on the host. Logs are buffered in memory and flushed to PostgreSQL in a single batch insert.
Deployment engine (deploymentEngine.ts)
deployProject copies the build output from the temporary working directory to a permanent deployments/<project-name>/ directory on the host filesystem. It then emits a deploymentUpdate event over Socket.io, updates projectTable.productionUrl in the database, and inserts a deployment record. For rollbacks the insertion step is skipped because the deployment record already exists.
PostgreSQL database (Drizzle ORM)
All persistent state lives in a single PostgreSQL database accessed through Drizzle ORM. The schema defines six tables:Subdomain middleware
Before any API route is reached, every incoming request passes throughsubdomainMiddleware. The middleware reads the Host header, extracts the first label as the subdomain, and checks whether a deployments/<subdomain>/ directory exists on disk. If it does, express.static serves the files directly; requests that do not match a static file fall back to index.html to support single-page applications. If no deployment directory matches, the request proceeds to the API routes normally.
Data flow
Explore further
Build pipeline
Every stage of the clone-build-test cycle in detail.
Deployment
How build output becomes a live subdomain.
Secrets
AES-256-GCM encryption and build-time injection.
Authentication
GitHub OAuth flow and JWT session tokens.