Preview environments

Clank previews are temporary deployments attached to a production project. Each preview is a real isolated project with its own URL, SQLite database, migration history, releases, secrets, jobs, logs, metrics, backups, and project scoped tok

3 min read572 wordsClank 0.9.4

Clank previews are temporary deployments attached to a production project. Each preview is a real isolated project with its own URL, SQLite database, migration history, releases, secrets, jobs, logs, metrics, backups, and project-scoped tokens.

The important default is absence: creating a preview does not copy production data or secrets. An application must populate test data explicitly. This prevents a routine branch deploy from turning into an unreviewed production-data export.

Deploy a preview

Link the directory to its production project once, then name the preview:

sh
clank preview deploy feature-auth
clank preview deploy pull-482 --ttl=48
clank preview list

--ttl is an integer number of hours. The hosted defaults are seven days with a maximum of 30 days. Deploying the same normalized name again reuses its isolated environment, publishes a new atomic release, and refreshes its expiration. It never changes .clank/project.json, so the directory remains linked to production.

For agents and CI:

sh
clank preview deploy pull-482 --ttl=24 --json

The clank-preview-result/1 document includes the preview ID, normalized name, parent project, expiration, release digest, URL, and build/upload timing.

Remove a preview

Expiration removes the runtime and all platform-managed resources. Remove it sooner with:

sh
clank preview remove feature-auth \
  --confirm="delete-preview feature-auth" \
  --acknowledge-data-loss

The acknowledgement is deliberate because preview databases can contain useful test data. A production project cannot be deleted while it still owns previews; remove or let them expire first.

Control-plane UI and API

The project's Previews page shows the active environment, URL, runtime status, current release, and expiration. Authorized members can remove a preview there. Creation remains a CLI-first operation so the exact local build and artifact digest are preserved.

The authenticated API is:

MethodEndpointPurpose
GET/api/projects/:parentId/previewsList unexpired previews and the effective TTL/isolation policy
POST/api/projects/:parentId/previewsCreate or refresh { "name": string, "ttlHours"?: integer }
DELETE/api/projects/:parentId/previews/:previewIdPermanently remove a preview after exact confirmation

Creating, refreshing, and deleting previews requires deploy-capable workspace access and an account session or account CLI token. A project-scoped token cannot manage previews because it would not automatically gain authority over the newly isolated child project. Deploying a release to an existing preview uses the ordinary release API and authorization rules.

Isolation and limits

  • Preview and production database paths live under different project IDs.
  • Production secrets are not inherited. Set preview secrets explicitly if the app needs them.
  • Migrations run against only the preview database.
  • Realtime connections, MCP/OAuth endpoints, durable jobs, and logs belong to the preview URL.
  • Preview projects are hidden from the top-level production project list and appear under their parent.
  • Every preview counts toward both account and workspace project limits. This prevents previews from bypassing compute, port, storage, and retention limits.
  • Nested previews are rejected.
  • Names are unique within one parent project. The public hostname also carries a random project-ID suffix, so deleting and recreating a name does not accidentally address an older environment.

Self-hosting policy

Programmatic control planes can tune preview retention:

ts
const platform = await openPlatform({
  // ...
  previews: {
    defaultTtlMs: 3 * 24 * 60 * 60_000,
    maxTtlMs: 14 * 24 * 60 * 60_000,
    cleanupIntervalMs: 60_000,
  },
});

Cleanup runs at startup before application recovery and then in bounded background batches. Expired previews are not restarted. Deletion uses the same path containment, encrypted-backup removal, remote-artifact cleanup, token revocation, process shutdown, and audit path as an explicit project deletion. Set cleanupIntervalMs: false only when an external operator owns expiration.

CI naming

Use stable, low-cardinality names such as pull-482 or branch-auth-refresh. Always run the remove command when a pull request closes; TTL cleanup is the safety net for interrupted workflows. Do not put secrets, email addresses, commit messages, or untrusted free-form text in a preview name.