SandboxSDK & APIPreviews & snapshots

Previews and snapshots

Open the app running in your sandbox, or save its workspace before making another change.

Open a running app

Start a server on 0.0.0.0, create a preview link for its port, and wait for the public route to respond.

import { createInterface } from 'node:readline/promises';
import { Sandbox } from '@tangle-network/sandbox';

const apiKey = process.env.TANGLE_API_KEY;
if (!apiKey) throw new Error('Set TANGLE_API_KEY');

const tangle = new Sandbox({
  apiKey,
  baseUrl: 'https://sandbox.tangle.tools',
});
const box = await tangle.create({
  maxLifetimeSeconds: 900,
});
await box.waitFor('running');

await box.write('/workspace/index.html', '<h1>Hello from your sandbox</h1>');
await box.process.spawnExact('python3', [
  '-m', 'http.server', '3000', '--bind', '0.0.0.0', '--directory', '/workspace',
], { timeoutMs: 900_000 });
const link = await box.previewLinks.create(3000);
const ready = await box.previewLinks.waitUntilReady(link.previewId);
console.log(ready.url);

const terminal = createInterface({ input: process.stdin, output: process.stdout });
await terminal.question('Press Enter when finished viewing the preview.');
terminal.close();

await box.delete();

The preview URL is public. Serve only files and application routes you intend to share. The example waits for you to open the URL, then deletes the sandbox when you press Enter.

previewLinks.remove(previewId) removes a link. Deleting its sandbox also ends the app.

Save and restore files

Capture a workspace snapshot, change a file, and restore that file from the snapshot.

TypeScript
import { Sandbox } from "@tangle-network/sandbox";

const apiKey = process.env.TANGLE_API_KEY;
if (!apiKey) throw new Error("Set TANGLE_API_KEY");

const client = new Sandbox({
  apiKey,
  baseUrl: "https://sandbox.tangle.tools",
});

const box = await client.create({
  maxLifetimeSeconds: 900,
});
await box.waitFor("running");

await box.write("/workspace/notes.txt", "Original notes");
const snapshot = await box.snapshot({ tags: ["baseline"] });

await box.write("/workspace/notes.txt", "Changed notes");
await box.restorePaths(snapshot.snapshotId, ["notes.txt"]);
console.log(await box.read("/workspace/notes.txt"));
await box.deleteSnapshot(snapshot.snapshotId);

await box.delete();

snapshot() captures the workspace. restorePaths() restores selected paths; revertToSnapshot() restores the whole workspace. Use listSnapshots() to find existing snapshots.

Start from a snapshot

Set TANGLE_SANDBOX_ID and TANGLE_SNAPSHOT_ID to the source sandbox and its snapshot.

TypeScript
import { Sandbox } from "@tangle-network/sandbox";

const apiKey = process.env.TANGLE_API_KEY;
if (!apiKey) throw new Error("Set TANGLE_API_KEY");

const client = new Sandbox({
  apiKey,
  baseUrl: "https://sandbox.tangle.tools",
});

const fromSandboxId = process.env.TANGLE_SANDBOX_ID;
const fromSnapshot = process.env.TANGLE_SNAPSHOT_ID;
if (!fromSandboxId || !fromSnapshot) {
  throw new Error("Set TANGLE_SANDBOX_ID and TANGLE_SNAPSHOT_ID");
}

const box = await client.create({ fromSandboxId, fromSnapshot, maxLifetimeSeconds: 900 });
await box.waitFor("running");
console.log((await box.exec("ls /workspace")).stdout);
await box.delete();

The restored sandbox has its own lifecycle. Deleting it does not delete the source sandbox.