Hostic is a minimal, production-ready platform to deploy static and SPA frontend apps from GitHub. It clones your repo, installs and builds inside an isolated Docker container, uploads build artifacts to Cloudflare R2, serves them via a smart proxy on custom subdomains, and streams build logs live over WebSockets.
Deploy from the dashboard or the hostic CLI — same pipeline either way.
- Simple: Connect GitHub, pick a repo, deploy — install/build commands autodetected from
package.json. - CLI-first option:
hostic login→hostic deploy --slug my-appfrom any cloned repo. - Isolated builds: Each build runs in a fresh Node 20 Docker container.
- Fast rebuilds: Per-deployment git cache and R2-backed npm dependency cache.
- Fast static hosting: Artifacts streamed from R2 via signed URLs.
- Live feedback: Realtime logs and statuses via Redis + Socket.IO on the API.
- Push-to-deploy: GitHub webhooks auto-redeploy when the API is publicly reachable.
- Multi-deploy: Per-user deployments with unique slugs and redeploys.
| Package | Role |
|---|---|
api/ |
REST API (Express + MongoDB) and Socket.IO for live build logs. Build worker, GitHub OAuth/webhooks. |
proxy/ |
Public edge proxy. Serves each deployment at {slug}.localhost:8080 (local) or https://{slug}.apps.yourdomain.com (prod). |
frontend/ |
React dashboard — auth, GitHub repo picker, deploy, live logs, deployment list. |
cli/ |
Terminal tool (hostic) — login, deploy, redeploy, list. |
- User authenticates (dashboard or CLI) and deploys with repo URL, commands, optional
slugandbuildDir. - API creates a
Deployment+ queuedBuild, enqueues a build job, optionally registers a GitHub webhook. - Worker syncs git cache, runs install+build in Docker, uploads artifacts to R2, updates MongoDB.
- Proxy serves the latest successful build for
slugvia signed R2 URLs; shows a building page while in progress. - Socket.IO on the API streams logs and status to the dashboard; CLI polls and prints logs in the terminal.
buildQueue.ts— in-memory FIFO, single concurrency by defaultworker.ts— git cache, Docker install/build, artifact uploaddeploymentCache.ts— per-deployment git fetch cache,buildDirresolutiondepsCache.ts— R2-backed npm cache keyed by lockfile hashdockercmd.ts+runStreaming.ts— Docker with live stdout/stderr streamingdetectArtifactPath.ts+findProjectRoot.ts— output and monorepo detectionprojectDefaults.ts— autodetect install/build/type frompackage.jsongithubWebhooks.ts— register webhooks for push-to-deployupload.ts— recursive R2 uploadlogger.ts+socketServer.ts— logs/status via Redis → Socket.IOimagesHandle.ts— Puppeteer + ImageKit preview screenshots
cd cli && npm install && npm run build && npm link
hostic login
hostic deploy --slug my-app
hostic redeploy my-app
hostic listSee cli/README.md for all options. Publish to npm as hostic-cli.
APPS_DOMAINconfig — local:localhost→{slug}.localhost:8080- SPA fallback, building page, presigned R2 streaming
Base: /api
Auth: POST /auth/signup, POST /auth/login, DELETE /auth/delete, PATCH /auth/update
User: GET /user/me
Deploy:
POST /host— create deployment (optionalslug,buildDir,branch)POST /host/redeploy— new build for existing deploymentGET /host,GET /host/deployment,DELETE /host/deleteGET /host/builds,GET /host/buildPOST /host/getimg— preview screenshotGET /host/webhook,PATCH /host/auto-deploy,POST /host/webhook/regenerate
GitHub:
GET /github/connect,GET /github/callback,GET /github/statusGET /github/repos,GET /github/repos/:owner/:repoGET /github/repos/:owner/:repo/detect— autodetect install/build/type
Webhooks: POST /webhooks/github/:webhookSecret — GitHub push (HMAC verified)
Requirements: Node 20+, Docker, MongoDB, Redis, R2 credentials
API (api/.env):
PORT=5000
DATABASE_URL=mongodb://localhost:27017/hostic
JWT_SECRET=replace-me
REDIS_URL=redis://localhost:6379
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
R2_BUCKET=<bucket-name>
R2_ACCESS_KEY_ID=<key>
R2_SECRET_ACCESS_KEY=<secret>
API_PUBLIC_URL=http://localhost:5000
GITHUB_CALLBACK_URL=http://localhost:5000/api/github/callback
FRONTEND_URL=http://localhost:5173
DEPLOY_URL_TEMPLATE=http://{slug}.localhost:8080
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...
Proxy (proxy/.env):
PORT=8080
DATABASE_URL=mongodb://localhost:27017/hostic
APPS_DOMAIN=localhost
R2_ENDPOINT=...
R2_ACCESS_KEY_ID=...
R2_SECRET_ACCESS_KEY=...
R2_BUCKET=...
Frontend (frontend/.env):
VITE_API_URL=http://localhost:5000/api
VITE_DEPLOY_URL_TEMPLATE=http://{slug}.localhost:8080
cd api && npm i && npm run dev # :5000 — API + Socket.IO
cd proxy && npm i && npm run dev # :8080
cd frontend && npm i && npm run dev # :5173
# Optional CLI
cd cli && npm i && npm run build && npm linkDo not run a separate socket/ service — Socket.IO is merged into the API.
- Login/signup.
- Open Deploy → connect GitHub → pick a repo (commands autofill from
package.json). - Watch live logs on the build page.
- Visit
http://{slug}.localhost:8080when the build succeeds.
hostic login
cd my-vite-app
hostic deploy --slug my-appPush changes, run hostic deploy --slug my-app again — same slug, new build.
- Queue is in-memory (single API instance). Use BullMQ for HA.
- Single build concurrency by default.
- Docker required on the API host.
- GitHub webhooks require a public
API_PUBLIC_URL. - Public repos only — private repo clone not yet implemented.
- Max 3 deployments per user, max 50 builds per deployment.
| File | Purpose |
|---|---|
ARCHITECTURE.md |
Current system architecture |
Platform.md |
Build lifecycle deep dive |
cli/README.md |
CLI reference |
INTERVIEW_PITCH.md |
Interview elevator pitch and demo script |
INTERVIEW_TECH.md |
Technical deep dive for interviews |
DESIGN.md |
UI design tokens |