Machine
SDK

Apps

Deploy static sites, bundles, Dockerfiles, and OCI images to stable Kortix URLs.

GithubEdit

Kortix Apps are provider-neutral serverless deployments. An App owns one stable URL. Each deployment is immutable. Failed deployments do not replace active traffic.

Apps is an experimental feature flag and off by default. The Apps navigation remains visible for a selected project and opens an enablement screen. Until a project manager enables Apps under Customize → Feature flags, every Apps route answers 403 with { error, code: "feature_disabled", feature: "apps" }, and kortix apps <subcommand> prints that message and exits 1.

All current source kinds run through the same Kortix sandbox hosting backend. Kortix selects Daytona, Platinum, or E2B. Static Apps, bundles, Dockerfiles, and OCI images therefore share one deployment and cold-wake contract. Cloudflare, Deno Deploy, Vercel, and other managed hosting backends are not part of the current API or SDK contract.

Choose the fastest source path

  • Deploy plain HTML, CSS, JavaScript, or a prebuilt SPA as static.
  • Build Vite locally and deploy dist/ as static for the lowest latency.
  • Deploy Vite, React, or another package source as bundle when Kortix must run the install and build commands.
  • Export Next.js with output: 'export' and deploy out/ as static when the App needs no server runtime.
  • Deploy server-rendered Next.js and arbitrary services with a Dockerfile and an explicit command and port.
  • Deploy an existing public image as oci_image with an explicit command and port.

kortix apps deploy blocks by default until the stable URL is ready. Use --no-wait only when another process owns status tracking. An authorized request to a suspended App resumes its sandbox, waits for readiness, and proxies that same request. Browser navigation shows a branded page while the App is queued, validating, building, provisioning, checking, or starting. Machine clients receive 202 app_starting with Retry-After: 3 during a transient cold start. The stable URL does not expose app_stopped or an unavailable cold-start state.

New Apps are private. Choose one access mode:

  • private: only the creator.
  • project: every member who can read the project.
  • restricted: selected project members and groups.
  • public: no authentication.
  • password: anyone with the App password.

Kortix access uses a five-minute exchange URL and an eight-hour, host-only, secure cookie. Changing an access policy increments its revision and revokes existing App cookies. Passwords are Argon2id hashes. The API and SDK never return a password or hash. Do not put a password in kortix.yaml.

Every immutable deployment records created_by, actor_type, and its originating source_session_id when an agent deployed it.

typescript
const apps = kortix.project(projectId).apps;
const app = await apps.create({ slug: 'docs', name: 'Docs' });
const artifact = await apps.artifacts.uploadArchive(tarGzBytes);
const deployment = await apps.deployments.create(app.app_id, {
  artifact_id: artifact.artifact_id,
  source: { kind: 'static', spa: true },
});
console.log(app.url, deployment.status);

await apps.access.update(app.app_id, {
  mode: 'restricted',
  member_ids: [memberId],
  group_ids: [groupId],
});
const preview = await apps.access.session(app.app_id);
window.open(preview.url);

For OCI images, register the immutable image reference and declare the process command and public target port:

typescript
const registered = await apps.artifacts.register({
  kind: 'oci_image',
  image: 'ghcr.io/acme/service:2026-08-07',
});
await apps.deployments.create(app.app_id, {
  artifact_id: registered.artifact.artifact_id,
  source: {
    kind: 'oci_image',
    image: 'ghcr.io/acme/service:2026-08-07',
    command: ['node', 'server.js'],
    port: 3000,
    readiness_path: '/health',
  },
});

Use apps.access.get, apps.access.update, apps.access.session, apps.deployments.get, apps.deployments.logs, apps.rollback, apps.start, apps.stop, and apps.remove for the full lifecycle. apps.stop suspends compute immediately. The next request resumes the App. apps.start warms it before traffic arrives.

kortix apps access <app> reads a policy. Add --mode, --password, --members, or --groups to update it. kortix apps access-link <app> --json creates a five-minute authenticated browser URL without changing the policy. Treat that URL as a secret. kortix apps deploy accepts the equivalent --access, --password, --members, and --groups flags.

Each cold start compares the active deployment's runtime_version with the current Kortix App runtime. An old deployment continues serving while Kortix asynchronously builds one immutable replacement with the latest kortix-appd and Caddy binaries. One PostgreSQL advisory lock prevents duplicate refreshes.

The Kortix Browser opens *.apps.kortix.com and *.apps.localhost directly. Direct navigation preserves the host-only access cookie and avoids the generic sandbox proxy.

Hosting provider selection remains a server policy unless an operator supplies the optional deployment preference. Managed acceptance covers Platinum and Daytona. E2B implements the same provider contract.

On this page