Skip to main content
Shipyard streams build logs, status changes, and deployment updates to connected clients in real time using Socket.io. The WebSocket server runs on the same HTTP server as the REST API, so no separate port or connection is required.

Connecting

Pass your JWT in the auth.token field of the Socket.io handshake options. The server validates the token before accepting the connection — unauthenticated connections are rejected immediately.
import { io } from "socket.io-client";

const socket = io("http://localhost:8080", {
  auth: {
    token: "your-jwt-token"
  }
});

socket.on("connect", () => {
  console.log("Connected to Shipyard");
});
Replace http://localhost:8080 with your server’s address in production. On a successful connection, the server automatically joins your socket to a private room identified by your userId. All events are scoped to that room.

Room model

Every event is delivered only to the room that matches your user ID. You receive events for all projects and builds associated with your account, and no events for other users’ builds. If you have multiple browser tabs or clients connected with the same token, all of them receive the same events.
Events are not scoped to an individual project — they fire for every build and deployment under your account. Filter by projectId in your event handlers if you need to isolate activity for a specific project.

Events

All events are emitted from the server to the client. There are no client-to-server events in the current API.

build_logs

Real-time output from the Docker image build step. Each line of Docker’s stdout is emitted as a separate event. Payload
{
  projectId: number;
  buildId: number;
  log: string;
  lineNumber: number;
  type: "info" | "error";
}

build_errors

Docker build stderr output. Lines that contain the keywords error, failed, fatal, or exception (case-insensitive) are classified as "error"; all other stderr lines are "info". Payload
{
  projectId: number;
  buildId: number;
  log: string;
  lineNumber: number;
  type: "info" | "error";
}

run_logs

Standard output from the container execution step — the output of your install command and build command running inside the container. Payload
{
  projectId: number;
  buildId: number;
  log: string;
  lineNumber: number;
  type: "info";
}

run_error

Standard error from the container execution step. Payload
{
  projectId: number;
  buildId: number;
  log: string;
  lineNumber: number;
  type: "info" | "error";
}

buildStatusUpdate

Emitted when a build transitions between statuses. Use this event to update progress indicators or surface pass/fail results in your UI. Payload
{
  projectId: number;
  buildId: number;
  status: "running" | "passed" | "failed";
}

deploymentUpdate

Emitted when a deployment record is created or updated. The url field contains the subdomain URL where the build output is being served. Payload
{
  projectId: number;
  buildId: number;
  status: "live";
  url: string;
}

Full example

The following example shows how to listen for all six events in a client application:
socket.on("build_logs", ({ projectId, buildId, log, lineNumber, type }) => {
  console.log(`[Build ${buildId}][${lineNumber}] ${log}`);
});

socket.on("build_errors", ({ buildId, log, lineNumber, type }) => {
  if (type === "error") {
    console.error(`[Build ${buildId}][${lineNumber}] ${log}`);
  } else {
    console.warn(`[Build ${buildId}][${lineNumber}] ${log}`);
  }
});

socket.on("run_logs", ({ buildId, log, lineNumber }) => {
  console.log(`[Run ${buildId}][${lineNumber}] ${log}`);
});

socket.on("run_error", ({ buildId, log, lineNumber, type }) => {
  if (type === "error") {
    console.error(`[Run ${buildId}][${lineNumber}] ${log}`);
  } else {
    console.warn(`[Run ${buildId}][${lineNumber}] ${log}`);
  }
});

socket.on("buildStatusUpdate", ({ buildId, status }) => {
  if (status === "passed") {
    console.log(`Build ${buildId} passed!`);
  } else if (status === "failed") {
    console.error(`Build ${buildId} failed`);
  }
});

socket.on("deploymentUpdate", ({ projectId, status, url }) => {
  console.log(`Project ${projectId} deployed at ${url}`);
});

Build docs developers (and LLMs) love