Platform

Deploying

Deploy functions to Clusterbase — preview and production deployments, promote, and undeploy.

View as Markdown

ccp deploy bundles your code, uploads it, and activates a deployment on Clusterbase's serverless runtime.

Deploy to Production

ccp deploy --prod
# ◼ Building Function...
# ◼ Creating Deployment...
# ◼ Uploading code...
# ◼ Deploying...
# ◼ my-app deployed!
# › https://my-app.clusterbase.dev

The --prod flag (alias: --production) makes this the active production deployment, served at https://{function-name}.clusterbase.dev.

Preview Deployments

Without --prod, you get a preview deployment with its own URL:

ccp deploy
# ◼ my-app deployed!
# › https://abc123.clusterbase.dev

Preview deployments are useful for testing changes before promoting to production.

Promote a Preview

Promote any preview deployment to production:

ccp promote <deployment-id>

This swaps the production deployment to the given deployment ID without redeploying.

promote reads the linked App's identity directly — it doesn't require build files or an initialized project. If the current directory isn't linked, it fails immediately with an instruction to run ccp link. When the project has a custom OIDC callback committed in cluster.toml, promotion still registers it for redirect purposes.

Undeploy

Remove a specific deployment:

ccp undeploy <deployment-id>

List Deployments

ccp list        # or: ccp ls

Inside a linked project, shows all deployments for that function with their IDs, status, and timestamps.

Run outside a project (or in one that hasn't been deployed yet) and ccp ls instead lists every function in the organization — resolve the org with --org-id, the project config, or the interactive picker. See Functions → Managing Functions.

Deploy Options

FlagDescription
--prod / --productionDeploy as the production deployment
--public-dir <path>Include a public directory for static assets
--client <path>Include a client-side script
--org-id <id>Organization ID — skips the org selection prompt
--app-id <id>App ID — skips the App selection / creation prompt
-y / --yesSkip prompts; if unlinked, create a Project + App named after the project — errors if that name is already taken, rather than attaching to it (single-org auto-picks; pass --org-id or set CCP_ORG_ID for multi-org)
--register-redirect-uriRegister this deploy's host as an OIDC redirect URI on the linked client. Production deploys already do this automatically; pass the flag to opt a preview deploy in (see OIDC → Auto-register on Deploy)
<path>Path to a file or directory (defaults to current directory)

How It Works

  1. Bundle — your TypeScript/JavaScript is compiled into a single ESM bundle
  2. Upload — the bundle (and any assets) are uploaded to Clusterbase's storage
  3. Activate — Clusterbase publishes the new deployment to the runtime
  4. Route — routes are created for {function-name}.clusterbase.dev and {deployment-id}.clusterbase.dev
  5. Serve — the serverless runtime creates a V8 isolate and starts handling requests

Client Bundle and CSS

When client is set (e.g. src/main.tsx) under [serverless] in cluster.toml, that entry is bundled for the browser and served at /{stem}.js (main.js). CSS imported from the client (import "./App.css" — multiple files, @import, and *.module.css all work) is bundled into a single /{stem}.css (main.css).

The server entry (your handler) may import CSS too — that's how server-side rendering shares a component with the client. Stylesheets reached from the handler are discarded (the client is the sole producer of /{stem}.css), so import the same styles from the client entry, which SSR does naturally by sharing the component. Two things to watch for:

  • With no client entry there's nothing to serve the stylesheet, so a CSS import from the handler is still a deploy error.
  • *.module.css imported from the handler only warns, rather than erroring: class names still resolve correctly, but the client and server bundles are built as separate graphs, so generated class names can disagree if two *.module.css files share a basename. Prefer plain CSS, or unique basenames, for components shared between server and client.

First Deploy

On your first deploy, if .ccp/config.json has no App id, CCP resolves one for you:

  • Interactive: you're prompted to select an organization, then link an existing App or create a new one.
  • Headless (no TTY or --yes): CCP resolves an organization, then creates a same-named Project and App. If an App with that name already exists in the organization, CCP rejects the deploy instead of attaching to it — names aren't identity, so a same-name collision (for example a renamed or re-cloned directory) requires explicit --app-id to select the intended App. The name comes from your project (its package.json name, else the directory). A single-org account needs no flags; with multiple orgs pass --org-id or set CCP_ORG_ID (otherwise it errors listing them).

Either way the App, Project, and organization ids are saved to .ccp/config.json for future deploys.

Build Without Deploying

To test the build step without deploying:

ccp build

This runs the bundler and reports any errors, but doesn't upload or activate anything.

Headless / CI Deploys

For CI pipelines and AI agents, set CCP_HEADLESS=1 and deploy never blocks on a prompt. On a single-org account, the first deploy needs no flags at all — it creates a Project and App, and errors if that name is already taken:

export CCP_HEADLESS=1
ccp deploy --prod

With multiple organizations, name the target so CCP doesn't have to guess:

ccp deploy --prod --org-id "$ORG_ID"

Or export CCP_ORG_ID="$ORG_ID" once and every org-scoped command resolves the org without the flag.

To pin a specific App by id (for example after a directory rename, when the name no longer matches), pass both ids:

ccp deploy --prod --org-id "$ORG_ID" --app-id "$APP_ID"

After the first deploy the ids are written to .ccp/config.json, so subsequent deploys on that machine reuse them with no flags. That file is gitignored, so a fresh clone or a new CI runner won't have it — there, a bare deploy tries to create a Project and App with the project's name and fails if that name is already taken, since a name match is no longer treated as identity. Pass --app-id (and --org-id, or set CCP_ORG_ID) to select the original App explicitly. ccp link seeds the config without uploading code, when you want to link separately from the first deploy.

See Headless Mode for the full reference.

On this page