Halvo
Connect a GitHub repository and Halvo detects or generates a Dockerfile, builds the image, and streams the build log over a WebSocket while the container comes up.
- Project
- Deployment platform
- Language
- TypeScript
- Started
- 2025-03
The story
Halvo is the largest thing here by some distance, and the one that taught me the most about the gap between a deploy that works and a deploy that keeps working. It takes a Git reference or a prebuilt image and puts a running, addressable container behind it.
The frontend is React 18; the backend is Express on TypeScript. Neither is interesting on its own. What matters is the layer underneath: a Docker Engine API client that has to stay correct when a build fails halfway, when a user closes the tab mid-stream, or when a previous deploy left resources behind. Orphan reclamation and a CLI fallback for the socket exist because both of those happened.
Credit deduction is modelled as a state machine rather than a counter, so a container that dies during provisioning does not silently bill. That decision came out of a bug, not a design doc.
Under the hood
The decisions that make it work.
- Deployment engine
- Talks to the Docker Engine API through dockerode over the unix socket, with a CLI fallback path and a sweeper that reclaims orphaned containers, images and volumes.
- Live operations
- Build and runtime logs stream over ws; the Docker events stream drives per-container CPU and memory readouts without polling.
- Dockerfile fallback
- When a repository ships no container spec, a Gemini call generates one from the detected runtime and lockfiles rather than failing the deploy.
- CLI companion
- @nub-coders/halvo wraps build, push, deploy, logs and rollback in a Commander.js + Inquirer interface for people who never open the dashboard.
- Auth and metering
- Four sign-in paths — Telegram initData, Google OAuth, GitHub App/OAuth, email OTP — over a state-machine credit ledger backed by Stripe and Razorpay.