Sandbox

Run isolated sandboxes on Cloudflare Durable Objects, Cloudflare Dynamic Workers, Vercel, Deno, Docker, or locally.

Use Sandbox to run server-side handlers in an isolated runtime when the job needs filesystem, process, or network isolation without introducing a queue or durable workflow.

Define sandboxes in server/sandboxes/** with defineSandbox(handler, options?), then execute them with runSandbox().

Getting started

Install the package

Install @vitehub/sandbox and the SDK for the provider you plan to use.

Terminal
pnpm add https://pkg.pr.new/vite-hub/vitehub/@vitehub/sandbox@main @cloudflare/sandbox

Configure a provider

nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@vitehub/sandbox/nuxt'],
  sandbox: {
    provider: 'cloudflare',
  },
})

Define a sandbox

Add a sandbox module under server/sandboxes/. ViteHub derives the sandbox name from the path inside that directory. For example, server/sandboxes/release-notes.ts registers release-notes.

server/sandboxes/release-notes.ts
type ReleaseNotesPayload = {
  notes?: unknown
}

export default defineSandbox(async (input?: ReleaseNotesPayload) => {
  const { notes } = await readValidatedPayload(input, value => ({
    notes: typeof value?.notes === 'string' ? value.notes.trim() : '',
  }))
  const items = notes
    .split(/\n+/)
    .map(line => line.replace(/^[-*]\s*/, '').trim())
    .filter(Boolean)

  return {
    summary: items[0] || 'No notes provided.',
    items: items.slice(0, 3),
  }
}, {
  timeout: 30_000,
})

Run the sandbox

Call the named sandbox from any server-side code. runSandbox() returns a result object, so check for errors before you return the value.

server/api/sandboxes/release-notes.post.ts
import { createError, readBody } from 'h3'
import { runSandbox } from '@vitehub/sandbox'

export default defineEventHandler(async (event) => {
  const body = await readBody<{ notes?: unknown }>(event)
  const result = await runSandbox('release-notes', body)

  if (result.isErr()) {
    throw createError({
      statusCode: 500,
      statusMessage: result.error.message,
      data: {
        code: result.error.code,
        provider: result.error.provider,
      },
    })
  }

  return result.value
})
Cloudflare Sandbox
Configure Cloudflare Sandbox on top of Durable Objects.
Cloudflare Dynamic Workers
Configure Cloudflare Dynamic Workers with the Worker Loader API.
Vercel Sandbox
Configure Vercel Sandbox and run isolated sandboxes on Vercel.
Deno Sandbox
Configure Deno Sandbox and run isolated sandboxes on Deno Deploy.
Docker Sandbox
Configure Docker Sandbox and run isolated sandboxes locally.
Local Sandbox
Run sandboxes locally with OS-level isolation using platform primitives.

Public API

FunctionUse it for
defineSandbox(handler, options?)Register one sandbox by exporting it from the sandboxes directory.
runSandbox(name, payload, { context? })Execute that sandbox from a route, task, or webhook.

Type reference

Handler signature

The handler receives an optional payload and an optional context object, and returns the result directly.

type SandboxHandler<TPayload, TResult> = (
  payload?: TPayload,
  context?: Record<string, unknown>,
) => TResult | Promise<TResult>

SandboxDefinitionOptions

The options object passed to defineSandbox() accepts portable options that work across all providers:

OptionTypeDescription
timeoutnumberMaximum execution time in milliseconds.
envRecord<string, string>Environment variables passed to the sandbox.
runtime{ command, args? }Custom runtime command for the sandbox process.
Provider-specific settings such as cpu, ports, or sandboxId belong in the top-level sandbox config in nitro.config.ts, not in the definition.

Result<T>

runSandbox() returns a Result<T> instead of throwing. Check the result before accessing the value.

Method / FieldTypeDescription
isOk()booleantrue when execution succeeded.
isErr()booleantrue when execution failed.
valueTThe handler return value. Only safe after isOk().
errorSandboxErrorError details with message, code, provider, and details.

Configure provider and sandbox options

Sandbox has two configuration layers:

  • Top-level sandbox config selects the provider and sets app-wide defaults.
  • defineSandbox(handler, options?) and createSandbox(options?)(handler) both configure one sandbox file with portable options such as timeout and env. ::
  • defineSandbox(handler, options?) configures one sandbox file with portable options such as timeout and env.

runSandbox() is not configuration. It is the execution call, so that is where you pass the payload and optional per-request context.

nuxt.config.ts
export default defineNuxtConfig({
  sandbox: {
    provider: 'vercel',
  },
})
server/sandboxes/release-notes.ts
export default defineSandbox(async (payload) => {
  return { ok: true }
}, {
  timeout: 30_000,
})
Each provider adds its own runtime APIs and sub-features. Use the provider pages in the sidebar for SDK installation, platform setup, and provider-specific options.