[bldr]docs

Your first workspace

A directory, a manifest, and one member that does something.

A workspace is a directory with a bldr-workspace.yml in it. Everything bldr builds for you lives in one.

Create it

mkdir hello-bldr && cd hello-bldr
bldr ws init

That writes a bldr-workspace.yml. Open it and you will find a members: map, which is the only part that matters yet.

Add a member

A member is one buildable thing: a directory with its own .bldr.ts that says what it produces. Make one:

mkdir -p members/site
bldr-workspace.yml
members:
  site: members/site
  # A base image, pinned by digest. bldr fetches it once and stores it by content.
  node:
    content:
      kind: container-registry
      reference: docker.io/library/node@sha256:...
    tracking:
      kind: container-registry
      reference: docker.io/library/node:22-slim

options:
  build_controller: default

Two members, two kinds. site is a local directory, so its content is whatever is on disk when you build. node is pinned to an exact image digest, with a separate note saying where a newer one would come from. Asking what upstream offers never changes what builds; only bldr ws pull node does.

Say what the member produces

members/site/.bldr.ts
import { ContainerImage } from "bldr";
import nodeImage from "node";

// One pod: run a command in the node image, keep what it wrote to /out.
const site = ContainerImage.fromMember(nodeImage, "amd64")
    .pod()
    .run("mkdir -p /out && echo '<h1>hello from bldr</h1>' > /out/index.html")
    .capture("/out");

scope.addOutputDirectory("site", site);

Three things are worth noticing. import nodeImage from "node" refers to the member you declared, and that import is the dependency edge. scope and member are already in scope; a .bldr.ts does not import them. And addOutputDirectory names a target, which is what you will ask bldr to build.

Register the workspace

The node builds workspaces it knows about.

bldr ws register
bldr ws status

Next: build it.

On this page