---
title: "@hyperframes/gcp-cloud-run"
description: "Google Cloud Run and Workflows adapter for distributed HyperFrames rendering."
---

The GCP Cloud Run package runs HyperFrames' distributed render primitives on Google Cloud. It ships a Cloud Run HTTP service, a Node client SDK, and a Terraform module for provisioning the bucket, service, workflow, and service accounts.

```bash
npm install @hyperframes/gcp-cloud-run
```

## When to Use

**Use `@hyperframes/gcp-cloud-run` when you need to:**
- Render large compositions on Google Cloud infrastructure
- Orchestrate `plan`, `renderChunk`, and `assemble` through Cloud Workflows
- Store project archives, chunk outputs, and final videos in GCS
- Deploy the renderer as a Cloud Run service with a pinned Chrome runtime
- Drive renders from CI, a backend service, or custom internal tooling

**Use a different package if you want to:**
- Render locally or inside a single Node process - use the [CLI](/packages/cli) or [producer](/packages/producer)
- Run the same distributed model on AWS - use [aws-lambda](/packages/aws-lambda)
- Build or edit composition HTML - use [studio](/packages/studio), [sdk](/packages/sdk), or [core](/packages/core)

<Tip>
  Cloud Run uses a container image, so it avoids Lambda ZIP-size pressure and can install the same pinned `chrome-headless-shell` runtime used by the standard renderer.
</Tip>

## Package Exports

| Import | Description |
|--------|-------------|
| `@hyperframes/gcp-cloud-run` | Server handler, event types, GCS transport, and client SDK exports |
| `@hyperframes/gcp-cloud-run/server` | Cloud Run HTTP service entry point |
| `@hyperframes/gcp-cloud-run/sdk` | Lightweight Node SDK for deploying sites, starting renders, polling progress, and estimating cost |

The published package also includes `terraform/` and a `Dockerfile` for deployment.

## Architecture

Cloud Workflows invokes one Cloud Run service with different `Action` values:

<Steps>
  <Step title="Plan">
    Downloads the project archive from GCS, runs the producer planner, and uploads the plan directory.
  </Step>
  <Step title="Render chunks">
    Cloud Workflows runs parallel `renderChunk` calls against the Cloud Run service. Each request renders one chunk and uploads it to GCS.
  </Step>
  <Step title="Assemble">
    Downloads all chunks and audio assets, assembles the deliverable, and uploads the final file.
  </Step>
</Steps>

The service is intentionally close to the AWS Lambda adapter: thin cloud transport around the same `@hyperframes/producer/distributed` primitives.

## Deploying

Build and push the container, then apply the Terraform module:

```bash
gcloud builds submit . \
  --tag REGION-docker.pkg.dev/PROJECT/REPO/hyperframes-render:TAG

terraform -chdir=node_modules/@hyperframes/gcp-cloud-run/terraform init
terraform -chdir=node_modules/@hyperframes/gcp-cloud-run/terraform apply \
  -var project_id=PROJECT \
  -var region=us-central1 \
  -var image=REGION-docker.pkg.dev/PROJECT/REPO/hyperframes-render:TAG
```

Terraform outputs the bucket name, service URL, workflow name, and region needed by the SDK.

## Using the SDK

```typescript
import { getRenderProgress, renderToCloudRun } from "@hyperframes/gcp-cloud-run/sdk";

const handle = await renderToCloudRun({
  projectDir: "./my-composition",
  planProtocol: "v2",
  config: { fps: 30, width: 1920, height: 1080, format: "mp4" },
  bucketName: "hyperframes-render-my-project",
  projectId: "my-project",
  location: "us-central1",
  workflowId: "hyperframes-render",
  serviceUrl: "https://hyperframes-render-abc.us-central1.run.app",
});

let progress = await getRenderProgress({ executionName: handle.executionName });
while (progress.status === "running") {
  await new Promise((resolve) => setTimeout(resolve, 5000));
  progress = await getRenderProgress({ executionName: handle.executionName });
}

console.log(progress.status, progress.outputFile, progress.costs.displayCost);
```

Plan v2 is recommended for new integrations because workers fetch
manifest-selected content-addressed artifacts. For backwards compatibility,
omitting `planProtocol` still selects v1; existing callers do not change
behavior until they opt in.

Pass `projectDir` for one-shot uploads, or call `deploySite()` separately and reuse the returned site handle across many renders.

## Related Guides

<CardGroup cols={2}>
  <Card title="GCP Cloud Run Deployment" icon="cloud" href="/deploy/gcp-cloud-run">
    End-to-end deployment details and smoke-test notes.
  </Card>
  <Card title="@hyperframes/producer" icon="video" href="/packages/producer">
    The distributed primitives that the Cloud Run service executes.
  </Card>
</CardGroup>
