diff --git a/packages/projects-docs/next-env.d.ts b/packages/projects-docs/next-env.d.ts new file mode 100644 index 00000000..4f11a03d --- /dev/null +++ b/packages/projects-docs/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/packages/projects-docs/package.json b/packages/projects-docs/package.json index 2afb15d8..d965cf92 100644 --- a/packages/projects-docs/package.json +++ b/packages/projects-docs/package.json @@ -24,8 +24,10 @@ }, "devDependencies": { "autoprefixer": "^10.4.16", + "markdown-table": "^3.0.4", "postcss": "^8.4.31", - "tailwindcss": "^3.3.5" + "tailwindcss": "^3.3.5", + "typescript": "5.7.2" }, "prettier": { "embeddedLanguageFormatting": "off", diff --git a/packages/projects-docs/pages/_meta.json b/packages/projects-docs/pages/_meta.json index 741b5a23..67aa6c90 100644 --- a/packages/projects-docs/pages/_meta.json +++ b/packages/projects-docs/pages/_meta.json @@ -1,14 +1,20 @@ { "learn": { - "title": "Documentation", + "title": "Editor", + "type": "page" + }, + "sdk": { + "title": "SDK", "type": "page" }, "tutorial": { "title": "Tutorial", - "type": "page" + "type": "page", + "display": "hidden" }, "faq": { "title": "FAQ", - "type": "page" + "type": "page", + "display": "hidden" } } diff --git a/packages/projects-docs/pages/learn/_meta.json b/packages/projects-docs/pages/learn/_meta.json index ee675e1f..943d9047 100644 --- a/packages/projects-docs/pages/learn/_meta.json +++ b/packages/projects-docs/pages/learn/_meta.json @@ -2,6 +2,10 @@ "index": "Introduction", "guides": "Getting Started", "editors": "Editors", + "sdk": { + "title": "SDK", + "href": "/sdk/" + }, "-- cloud-development": { "type": "separator", "title": "Cloud Development" @@ -29,5 +33,13 @@ "title": "More" }, "ci": "CodeSandbox CI", - "explore": "Discover Page" + "explore": "Discover Page", + "tutorials": { + "title": "Tutorials", + "href": "/tutorial/getting-started-with-dev-containers" + }, + "faq": { + "title": "FAQ", + "href": "/faq" + } } \ No newline at end of file diff --git a/packages/projects-docs/pages/learn/access/organizations.mdx b/packages/projects-docs/pages/learn/access/organizations.mdx index 99d8d7ec..03a5c629 100644 --- a/packages/projects-docs/pages/learn/access/organizations.mdx +++ b/packages/projects-docs/pages/learn/access/organizations.mdx @@ -17,48 +17,42 @@ Additionally, organizations make it possible to connect all the employees at a c ## Creating an organization -You can create an organization from any active workspace that is not already part of an organzation. -In the _Workspace settings_, open the [Organization tab](https://codesandbox.io/t/org) and enter a name for the organization. - +You can create an organization from any active workspace that is not already part of an organzation. +In the _Workspace settings_, open the [Organization tab](https://codesandbox.io/t/org) and enter a name for the organization. ![create org](../images/org-create.png) To prevent confusion, we recommend that you name your organization so it directly relates to your business’ name. - -![name org](../images/org-name.png) +![name organization](../images/org-name.png) Once you have created an organization, it will automatically be linked to the workspace you created it from. However, you can choose to add additional existing workspaces to that organization. -You can also manage the organization admins. +You can also manage the organization admins. - -![edit org](../images/org-edit.png) +![edit org](../images/org-edit.png) The [Organization settings](https://codesandbox.io/t/org) will always be discoverable through the _Workspace settings_. ## Setting an email domain -In the _Organizations settings_, open the `Domain` tab and add your email domain. -The domain must be verified before being approved. This is an automated process that requires no action from you. - +In the _Organizations settings_, open the `Domain` tab and add your email domain. +The domain must be verified before being approved. This is an automated process that requires no action from you. ![add domain](../images/org-domain-add.png) Once the domain is approved, users who have CodeSandbox accounts connected to emails with a matching domain will be given the option to join the workspace. -Users may encounter the suggestion to join an eligible workspace when they are attempting to access projects in the workspace or when they log into CodeSandbox for the first time after the email domain has been approved. +Users may encounter the suggestion to join an eligible workspace when they are attempting to access projects in the workspace or when they log into CodeSandbox for the first time after the email domain has been approved. Below is an example of the message a user with a matching email domain will see when opening a private Sandbox from a workspace they are not yet part of. - ![join ws](../images/org-domain-join-ws.png) - ## Accounts and domains + CodeSandbox accounts are tied to individual users. They grant access to shared workspaces and organizations, enabling collaboration with other CodeSandbox users. With a single CodeSandbox account, users can create or join multiple workspaces and organizations to collaborate with various groups of CodeSandbox users; these workspaces and organizations are separate entities, each with a unique set of members and projects. Since each workspace and organization are their own separate entities, members cannot see the other workspaces or organizations a user belongs to. - ![graph](../images/org-account-graph.png) diff --git a/packages/projects-docs/pages/learn/devboxes/upload.mdx b/packages/projects-docs/pages/learn/devboxes/upload.mdx index a7e6ccd5..878420e2 100644 --- a/packages/projects-docs/pages/learn/devboxes/upload.mdx +++ b/packages/projects-docs/pages/learn/devboxes/upload.mdx @@ -32,8 +32,7 @@ You can check your current Sandbox storage usage from your [Dashboard](https://c For Devboxes and repositories, the limits are: -- 20 GB total storage per Devbox or repository branch for workspaces on a Free plan. -- 50 GB total storage per Devbox or repository branch for workspaces on a Pro plan. +- 20 GB total storage per Devbox or repository branch for all workspaces. You can check your Devbox storage usage by clicking the CodeSandbox icon at the top left of the editor and then "Virtual machine". This will open a new DevTool displaying the current VM usage, including storage. diff --git a/packages/projects-docs/pages/learn/environment/vm.mdx b/packages/projects-docs/pages/learn/environment/vm.mdx index 706cec18..888a7400 100644 --- a/packages/projects-docs/pages/learn/environment/vm.mdx +++ b/packages/projects-docs/pages/learn/environment/vm.mdx @@ -22,7 +22,7 @@ VM resources consist of vCPU, RAM and storage. The vCPU and RAM specs are groupe | Subscription | Storage | | ------------ | ------- | | Free | 20 GB | -| Pro | 50 GB | +| Pro | 20 GB | If you require storage that goes beyond our Pro plan defaults, please select 'Pro Subscriptions' on our support form and [get in touch](https://codesandbox.io/support). Our team can adjust your limits to suit your project. diff --git a/packages/projects-docs/pages/sdk/_meta.json b/packages/projects-docs/pages/sdk/_meta.json new file mode 100644 index 00000000..fa45d39e --- /dev/null +++ b/packages/projects-docs/pages/sdk/_meta.json @@ -0,0 +1,33 @@ +{ + "index": "Introduction", + "use-cases": "Use Cases", + "pricing": "Pricing", + "contact": { + "title": "Contact Us", + "href": "https://codesandbox.io/support#form", + "newWindow": true + }, + + "-- api-reference": { + "type": "separator", + "title": "API Reference" + }, + "sandboxes": "Sandboxes", + "filesystem": "File System", + "shells": "Shells", + "ports": "Ports & Previews", + "tasks": "Tasks & Setup", + "specs": "VM Specs", + + "-- resources": { + "type": "separator", + "title": "Resources" + }, + "snapshot-library": "Snapshot Library", + "snapshot-builder": "Snapshot Builder", + "environment": "Environment", + "docker": "Docker & Docker Compose", + "persistence": "Persistence", + "fork": "Fork", + "faq": "FAQ" +} diff --git a/packages/projects-docs/pages/sdk/docker.mdx b/packages/projects-docs/pages/sdk/docker.mdx new file mode 100644 index 00000000..bcb32b5d --- /dev/null +++ b/packages/projects-docs/pages/sdk/docker.mdx @@ -0,0 +1,148 @@ +--- +title: Docker & Dev Containers +description: Learn how to configure your sandbox environment using Dev Containers. +--- + +import { Callout } from 'nextra-theme-docs' + +# Dev Containers + +CodeSandbox natively supports the [Dev Containers specification](https://containers.dev/), allowing you to customize your sandbox, install system-level dependencies, and run additional services. + +## Configuration + +To configure your sandbox environment, create a `.devcontainer/devcontainer.json` file inside the root of the sandbox: + +```json +{ + "name": "Node.js", + "image": "mcr.microsoft.com/devcontainers/javascript-node:18", + "features": { + "ghcr.io/devcontainers/features/python:1": {} + } +} +``` + +In this example, we're installing Node v18 as base, with Python on top using Dev Container Features. + +Alternatively, you can use a `Dockerfile` to build the Docker image when the sandbox boots: + +```json +{ + "name": "Node.js", + "build": { + "dockerfile": "./Dockerfile" + } +} +``` + +### Using Dev Containers in the SDK + +When creating a sandbox, all shells will automatically run inside the Docker container specified in the Dev Container configuration. + +```ts +const sandbox = await sdk.sandbox.create({ + template: "node" // Template with Dev Container configuration +}); + +await sandbox.shells.run("node --version"); +``` + +Since we use memory snapshots, the Docker container will already be running when you run your shell. + +## Docker Compose + +You can run additional services using Docker Compose by adding a `docker-compose.yml` configuration to your Dev Container: + +```json +{ + "name": "Full Stack App", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspace" +} +``` + +With a corresponding `docker-compose.yml`: + +```yaml +services: + app: + image: mcr.microsoft.com/devcontainers/javascript-node:18 + command: sleep infinity + + db: + image: postgres:14 + ports: + - 5432:5432 + environment: + POSTGRES_PASSWORD: password +``` + +### Using Docker Compose in the SDK + +The SDK will automatically start all services defined in your Docker Compose configuration: + +```ts +const sandbox = await sdk.sandbox.create({ + template: "fullstack" // Template with Dev Container configuration +}); + +// Wait for all services to be ready +await sandbox.setup.waitForFinish(); + +// You can now connect to the services +const portInfo = await sandbox.ports.waitForPort(5432); +console.log(`Database available at: ${portInfo.hostname}:${portInfo.port}`); +``` + +## Examples + +### Full-Stack Development Environment + +Here's an example of setting up a full-stack development environment with Node.js and PostgreSQL: + +```ts +const sandbox = await sdk.sandbox.create({ + template: "fullstack" +}); + +// Wait for environment setup +const progress = await sandbox.setup.waitForFinish(); +if (progress.state !== "FINISHED") { + throw new Error("Environment setup failed"); +} + +// Start the development server +const devTask = await sandbox.tasks.runTask("dev"); + +// Wait for both the app and database to be ready +const [appPort, dbPort] = await Promise.all([ + sandbox.ports.waitForPort(3000), + sandbox.ports.waitForPort(5432) +]); + +console.log(` +App running at: ${appPort.getPreviewUrl()} +Database available at: ${dbPort.hostname}:${dbPort.port} +`); +``` + +### Custom Environment with System Dependencies + +Example of a sandbox that needs specific system packages: + +```ts +const sandbox = await sdk.sandbox.create({ + template: "custom-env" +}); + +// The Dev Container will install required packages during setup +await sandbox.setup.waitForFinish(); + +// Run a command that uses the installed packages +const result = await sandbox.shells.run("ffmpeg -version"); +console.log(result.output); +``` + +For more information about Dev Container configuration options and features, visit the [Dev Container specification](https://containers.dev/). Also, take a look at our [snapshot builder](/sdk/snapshot-builder.mdx) to learn how to create efficient snapshots with preloaded Docker images. diff --git a/packages/projects-docs/pages/sdk/environment.mdx b/packages/projects-docs/pages/sdk/environment.mdx new file mode 100644 index 00000000..55718ced --- /dev/null +++ b/packages/projects-docs/pages/sdk/environment.mdx @@ -0,0 +1,22 @@ +--- +title: Environment +description: Learn how the CodeSandbox SDK's environment works. +--- + +import { Callout } from 'nextra-theme-docs' + +# Environment + +Sandboxes on CodeSandbox are backed by a [Firecracker](https://firecracker-microvm.github.io/) microVM, within the VM we run a rootless Docker container based on a [Dev Container](https://containers.dev/) configuration (specified in the `.devcontainer/devcontainer.json` file). + +## Booting a Sandbox + +Whenever we boot a sandbox from scratch, we'll: + +1. Start the Firecracker VM +2. Create a default user (called `pitcher-host`) +3. (optional) Build the Docker image specified in the `.devcontainer/devcontainer.json` file +4. Start the Docker container +5. Mount the `/project/sandbox` directory as a volume inside the Docker container + +We run an agent inside the VM that the SDK connects to. Via an RPC protocol you can then interact with the sandbox. diff --git a/packages/projects-docs/pages/sdk/faq.mdx b/packages/projects-docs/pages/sdk/faq.mdx new file mode 100644 index 00000000..dd2b8491 --- /dev/null +++ b/packages/projects-docs/pages/sdk/faq.mdx @@ -0,0 +1,42 @@ +--- +title: FAQs +description: Find answers to common questions about the CodeSandbox SDK. +--- + +import { Callout } from 'nextra-theme-docs' + +# FAQ + +## Do I need a CodeSandbox workspace to be able to use the SDK? + +Yes. You need a CodeSandbox API key to use CodeSandbox SDK, which you can get by [creating a CodeSandbox account](https://codesandbox.io/signin). + +## How can I revoke my API key? + +To revoke an API key, go to the "Permissions" tab of your [Workspace Settings](https://codesandbox.io/t/permissions) and click the respective token under "API Access". Then, click "Remove Token" from the bottom of that modal. + +## I have hit a rate limit - what should I do? + +Please subscribe to a CodeSandbox plan that includes the most suitable rate limit for you. In case you're on our Builder plan already, please [contact us](https://webforms.pipedrive.com/f/72gS7iXoP8qjL8Ku9HZQcN5UKpUpZkgKRCjhbqREjCOYyBgzrCKCr7Mys5AyczOHBN) to discuss an Enterprise plan. + +## Can I change the specs of the VMs? + +Currently, we only allow changing the default specs for all VMs created with the SDK. You can change + +We are also SOC 2 Type II compliant. + +## Is it possible to self-host CodeSandbox SDK? + +No, for now we don't provide a self-host option. + +## Are there any SDK rate limits? + +Yes. The SDK has rate limits on concurrent VMs, number of requests per hour, and number of sandboxes created per hour. These limits vary depending on the CodeSandbox plan, as explained on our [Pricing page](https://codesandbox.io/pricing). + +## Can I use the same CodeSandbox plan for SDK and non-SDK usage? + +Yes. Your CodeSandbox plan will allow you to use both, so you can leverage the SDK for programmatic sandbox creation, while still allowing your team to use CodeSandbox for their development. + +## Does the CodeSandbox SDK use CodeSandbox Sandboxes or Devboxes? + +While the SDK code only mentions "sandbox", the actual environments that it uses are officially called "Devboxes" (which use VMs). So, if you need more details about these VMs, please always refer to "[Devbox](/learn/devboxes/overview)" section of the CodeSandbox documentation and pricing. diff --git a/packages/projects-docs/pages/sdk/filesystem.mdx b/packages/projects-docs/pages/sdk/filesystem.mdx new file mode 100644 index 00000000..c33950de --- /dev/null +++ b/packages/projects-docs/pages/sdk/filesystem.mdx @@ -0,0 +1,95 @@ +--- +title: File System +description: Learn how the CodeSandbox SDK's file system works. +--- + +# File System + +Every sandbox has a persistent file system under `/project/sandbox`. By default, the working directory is `/project/sandbox`. All files saved in `/project/sandbox` have `git` source control and will be persisted between reboots. Whenever we hibernate or shutdown a sandbox, we'll create a commit to track the filesystem of the sandbox. + +Refer to the [Environment](/sdk/environment) section for more information about how we store files and other resources. + +## API + +The API of the filesystem is similar to the Node.js fs module. You can find the API under `sandbox.fs`. All filesystem +operations are relative to the workspace directory of the sandbox (which is `/project/sandbox` by default). + +### Writing & Reading Files + +You can read & write files using an api that's similer to the Node.js fs module: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Writing text files +await sandbox.fs.writeTextFile("./hello.txt", "Hello, world!"); + +// Reading text files +const content = await sandbox.fs.readTextFile("./hello.txt"); +console.log(content); + +// Writing binary files +await sandbox.fs.writeFile("./hello.bin", new Uint8Array([1, 2, 3])); + +// Reading binary files +const content = await sandbox.fs.readFile("./hello.bin"); +console.log(content); +``` + +### Uploading & Downloading Files + +Uploading and downloading files can be done using the same methods as writing and reading files. + +```ts +import fs from "node:fs"; + +const sandbox = await sdk.sandbox.create(); + +const myBinaryFile = fs.readFileSync("./my-binary-file"); +await sandbox.fs.writeFile("./my-binary-file", myBinaryFile); + +const content = await sandbox.fs.readFile("./my-binary-file"); +fs.writeFileSync("./my-binary-file", content); +``` + +You can also download a file or directory by generating a download URL to a zip file. This download URL is valid for 5 minutes: + +```ts +const { downloadUrl } = await sandbox.fs.download("./"); +console.log(downloadUrl); +``` + +### Listing Files & Directories + +You can list files & directories in a directory using the `readdir` method. + +```ts +const filesOrDirs = await sandbox.fs.readdir("./"); + +console.log(filesOrDirs); +``` + +### Copying, Renaming & Deleting Files + +You can copy, rename & delete files using the `copy`, `rename` & `remove` methods. + +```ts +await sandbox.fs.copy("./hello.txt", "./hello-copy.txt"); +await sandbox.fs.rename("./hello-copy.txt", "./hello-renamed.txt"); +await sandbox.fs.remove("./hello-renamed.txt"); +``` + +### Watching Files + +You can watch files for file changes, additions and deletions using the `watch` method. + +```ts +const watcher = await sandbox.fs.watch("./", { recursive: true, excludes: [".git"] }); + +watcher.onEvent((event) => { + console.log(event); +}); + +// When you're done, you can stop the watcher +watcher.dispose(); +``` diff --git a/packages/projects-docs/pages/sdk/fork.mdx b/packages/projects-docs/pages/sdk/fork.mdx new file mode 100644 index 00000000..29aa978b --- /dev/null +++ b/packages/projects-docs/pages/sdk/fork.mdx @@ -0,0 +1,54 @@ +--- +title: Fork +description: Learn how forking snapshots work in the CodeSandbox SDK. +--- + +# Fork + +When you hibernate a sandbox, we keep a memory snapshot of the underlying Firecracker VM. When you start that sandbox, or if any network request is made to the sandbox, we'll restore the memory snapshot and continue from where you left off. +Because we can snapshot a sandbox, we can also fork it! For example, you can fork a sandbox to create a new sandbox running the same server. + +```ts +import { CodeSandbox } from '@codesandbox/sdk' +const sdk = new CodeSandbox(); + +const sandbox = await sdk.sandbox.create(); + +// Run anything on the sandbox +await sandbox.shells.run('echo test > test.txt'); + +const sandbox2 = await sandbox.fork(); + +// Now we have two sandboxes that have the same fs & memory state! +``` + +You can use this to add support for checkpoint/restore functionality, or A/B test different agent iterations. At CodeSandbox we use this to enable users to quickly fork shared Sandboxes to their own account. + +## Manually Creating a Memory Snapshot + +You can manually create a memory snapshot by calling `sandbox.hibernate()`: + +```ts +import { CodeSandbox } from '@codesandbox/sdk' +const sdk = new CodeSandbox(); + +const sandbox = await sdk.sandbox.create(); + +// Do work + +await sandbox.hibernate(); +``` + +Creating a memory snapshot can take between 3-10 seconds. Resuming from a memory snapshot takes between 0.5-2 seconds. + +## Live snapshots + +If a Sandbox is already running we can still fork its exact current state. This has a small overhead of about 0.5 seconds. + +## Learn More + +We have written a couple blog posts about how memory snapshots work under the hood: + +- [How we clone a running VM in 2 seconds](https://codesandbox.io/blog/how-we-clone-a-running-vm-in-2-seconds) +- [Cloning microVMs by sharing memory through userfaultfd](https://codesandbox.io/blog/cloning-microvms-using-userfaultfd) +- [How we scale our microVM infrastructure using low-latency memory decompression](https://codesandbox.io/blog/how-we-scale-our-microvm-infrastructure-using-low-latency-memory-decompression) diff --git a/packages/projects-docs/pages/sdk/index.mdx b/packages/projects-docs/pages/sdk/index.mdx new file mode 100644 index 00000000..62975a36 --- /dev/null +++ b/packages/projects-docs/pages/sdk/index.mdx @@ -0,0 +1,73 @@ +--- +title: CodeSandbox SDK +description: Learn how CodeSandbox works and the different types of projects you can create and develop. +--- + +import Hero from "../../../../shared-components/Hero.js"; + + + +CodeSandbox SDK (beta) enables you to quickly create and run isolated sandboxes securely. +The SDK can be used to run concurrent VMs to support multiple use cases such as AI agents, code interpretation and [more](/sdk/use-cases.mdx) + +## How it works + +The SDK can spin up a sandbox by cloning a template in under 3 seconds. Inside this VM, you can run any code, install any dependencies and even run servers. + +The sandboxes run on the same infrastructure as CodeSandbox, which means you can clone, snapshot and restore sandboxes at any point in time (checkpointing). + +Under the hood, the SDK uses the microVM infrastructure of CodeSandbox to spin up sandboxes. It supports: + +1. Memory snapshot/restore (checkpointing) at any point in time +2. Resume/clone VMs from a snapshot in 3 seconds +3. VM FS persistence (with `git` version control) +4. Environment customization using Docker & Docker Compose (Dev Containers) + +## Quickstart + +Install the SDK: + +```bash +npm install @codesandbox/sdk +``` + +Create an API key at [https://codesandbox.io/t/api](https://codesandbox.io/t/api), and enable all scopes. + +Now you can create a sandbox and run a server: + +```js +import { CodeSandbox } from "@codesandbox/sdk"; + +const sdk = new CodeSandbox(process.env.CSB_API_KEY!); +const sandbox = await sdk.sandbox.create(); + +await sandbox.shells.python.run("print(1+1)"); +await sandbox.shells.run('echo "Hello World"'); + +// We can also start shells in the background by not awaiting them +const shellInfo = sandbox.shells.run("npx -y serve ."); + +// Wait for port to open +const portInfo = await sandbox.ports.waitForPort(3000); +console.log(portInfo.getPreviewUrl()); + +// And, we can clone(!) the sandbox! This takes 1-3s. +const sandbox2 = await sandbox.fork(); + +// Sandbox 2 will have the same processes running as sandbox 1 +const portInfo2 = await sandbox2.ports.waitForPort(3000); +console.log(portInfo2.getPreviewUrl()); + +// Finally, we can hibernate the sandbox. This will snapshot the sandbox and stop it. +// Next time you start the sandbox, it will continue where it left off, as we created a memory snapshot. +// The sandboxes will also automatically resume if a network request comes in for the +// servers they have started. +await sandbox.hibernate(); +await sandbox2.hibernate(); + +// Open the sandbox again +const resumedSandbox = await sdk.sandbox.open(sandbox.id); +``` diff --git a/packages/projects-docs/pages/sdk/persistence.mdx b/packages/projects-docs/pages/sdk/persistence.mdx new file mode 100644 index 00000000..e980f483 --- /dev/null +++ b/packages/projects-docs/pages/sdk/persistence.mdx @@ -0,0 +1,34 @@ +--- +title: Persistence +description: Learn how the persistence of sandboxes works. +--- + +import { Callout } from 'nextra-theme-docs' + +# Persistence + +Sandboxes have three states of persistence: + +- **Memory**: the sandbox has a memory snapshot and will be restored from memory when started. This takes 1-2 seconds. +- **Disk**: the sandbox has a disk snapshot, but needs to boot from scratch. This takes 5-20 seconds. +- **Archived**: the sandbox has no disk, and will be recreated from our archive storage. This takes 20-60 seconds. + +Generally, a sandbox will have a memory snapshot for 7 days, a disk snapshot for 2 weeks, and an archive for undetermined time (so far in the last 4 years, we've never deleted an archive). + +## Memory + +Whenever a sandbox is hibernated, we keep a memory snapshot of the underlying Firecracker VM. Then, when you start that sandbox, or if any network request is made to the sandbox, we'll restore the memory snapshot and continue from where you left off (this takes 0.5-2 seconds). + +Memory snapshots are kept for a week (can be longer depending on plan, and disk pressure), after which they'll be deleted. If the sandbox was used in the meantime (either the sandbox was resumed, or the sandbox was forked), the memory snapshot will be kept around and the timer will reset. + +## Disk + +Sandboxes have two layers of disk persistence: + +- `/persisted`: contains our archive of the sandbox. If you start a sandbox after a year of inactivity, the `/persisted` directory will still be there. Because of this, it's smaller than the `/project/sandbox` directory. + + +We keep a `.git` directory in `/persisted` to track the filesystem of the sandbox, which we regularly commit to. + + +- `/project/sandbox`: this is the working directory of the sandbox. All files saved in this directory will be persisted between reboots. If the sandbox is not started for more than two weeks (or longer, depending on plan and disk pressure), we'll commit all files of `/project/sandbox` to `/persisted` and delete the disk. If the persisting of those files fails, we won't delete the disk to ensure the user's data is not lost. diff --git a/packages/projects-docs/pages/sdk/ports.mdx b/packages/projects-docs/pages/sdk/ports.mdx new file mode 100644 index 00000000..bddc3afd --- /dev/null +++ b/packages/projects-docs/pages/sdk/ports.mdx @@ -0,0 +1,130 @@ +--- +title: Ports +description: Learn how you can interact with ports in your sandbox. +--- + +import { Callout } from 'nextra-theme-docs' + +# Ports + +The Ports API allows you to monitor and interact with HTTP ports in your sandbox. This is particularly useful when working with development servers or any other services that listen on specific ports. + +Whenever a port is opened within a sandbox, we'll automatically expose it under `https://-.csb.app`. + + +If the sandbox is private, we'll ask the user to sign in to open the preview. We're currently working on an API to allow creating signed URLs for private sandboxes, or selecting which ports are exposed and which are closed. + + +Also, we'll automatically resume a sandbox whenever a port is accessed while the sandbox is hibernated. + +## API + +The Ports API is available under `sandbox.ports`. It provides methods for monitoring port activity and getting preview URLs for web services. + +### Monitoring Ports + +You can listen for ports being opened and closed in your sandbox: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Listen for ports being opened +const listener1 = sandbox.ports.onDidPortOpen((portInfo) => { + console.log(`Port ${portInfo.port} opened`); + console.log(`Preview URL: ${portInfo.getPreviewUrl()}`); +}); + +// Listen for ports being closed +const listener2 = sandbox.ports.onDidPortClose((port) => { + console.log(`Port ${port} closed`); +}); + +// Remove listeners when done +listener1.dispose(); +listener2.dispose(); +``` + +### Getting Port Information + +You can get information about currently opened ports: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Get all opened ports +const openPorts = sandbox.ports.getOpenedPorts(); +for (const port of openPorts) { + console.log(`Port ${port.port} is open at ${port.hostname}`); +} + +// Get preview URL for a specific port +const previewUrl = sandbox.ports.getPreviewUrl(3000); +if (previewUrl) { + console.log(`Preview available at: ${previewUrl}`); +} +``` + +### Waiting for Ports + +When starting services, you often need to wait for a port to become available: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Start a development server +sandbox.shells.run("npm run dev"); + +// Wait for the dev server port to open +const portInfo = await sandbox.ports.waitForPort(3000); +console.log(`Dev server is ready at: ${portInfo.getPreviewUrl()}`); +``` + +## Examples + +### Starting a Web Server + +Here's a complete example of starting a web server and getting its preview URL: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Start the server +sandbox.shells.run("npx serve -y ."); + +// Wait for the server to be ready +const portInfo = await sandbox.ports.waitForPort(3000); + +// Get the preview URL with custom protocol +const httpUrl = portInfo.getPreviewUrl("http://"); +const httpsUrl = portInfo.getPreviewUrl(); // defaults to https:// + +console.log(`Server is running at: +- HTTP: ${httpUrl} +- HTTPS: ${httpsUrl}`); +``` + +### Monitoring Multiple Ports + +When working with multiple services, you might want to monitor several ports: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Start monitoring before launching services +sandbox.ports.onDidPortOpen((portInfo) => { + switch (portInfo.port) { + case 3000: + console.log("Frontend server ready"); + break; + case 3001: + console.log("API server ready"); + break; + case 5432: + console.log("Database ready"); + break; + } +}); + +// Start your services +sandbox.shells.run("npm run start:all"); +``` diff --git a/packages/projects-docs/pages/sdk/pricing.mdx b/packages/projects-docs/pages/sdk/pricing.mdx new file mode 100644 index 00000000..1e388f1f --- /dev/null +++ b/packages/projects-docs/pages/sdk/pricing.mdx @@ -0,0 +1,61 @@ +--- +title: Pricing +description: Learn how CodeSandbox SDK is priced, find your ideal plan, and estimate your bill. +--- + +import { Callout } from 'nextra-theme-docs' + +# Pricing + +CodeSandbox SDK is priced according to the [CodeSandbox plans](https://codesandbox.io/pricing). The SDK follows two main pricing components: + +- **VM credits**: Credits serve as the unit of measurement for VM runtime. One credit equates to a specific amount of resources used per hour, depending on the specs of the VM you are using. VM credits follow a pay-as-you-go approach and are priced at $0.018 per credit. Learn more about credits [here](/learn/credit-usage/credits). + +- **VM concurrency**: This defines the maximum number of VMs you can run simultaneously with the SDK. As explored below, each CodeSandbox plan has a different VM concurrency limit. + +We use minutes as the smallest unit of measurement for VM credits. E.g.: if a VM runs for 3 minutes and 25 seconds, we bill the equivalent of 4 minutes of VM runtime. + +## VM credit prices by VM size + +Below is a summary of how many VM credits are used per hour of runtime in each of our available VM sizes. Note that, by default, we recommend using the Pico VM size, as it should provide enough resources for most workflows that require basic code interpretation. + +| VM size | Credits / hour | Cost / hour | CPU | RAM | +| ------- | -------------- | ----------- | -------- | ------ | +| Pico | 7 credits | $0.126 | 2 cores | 1 GB | +| Nano | 10 credits | $0.18 | 2 cores | 4 GB | +| Micro | 20 credits | $0.36 | 4 cores | 8 GB | +| Small | 40 credits | $0.72 | 8 cores | 16 GB | +| Medium | 80 credits | $1.44 | 16 cores | 32 GB | +| Large | 160 credits | $2.88 | 32 cores | 64 GB | +| XLarge | 320 credits | $5.76 | 64 cores | 128 GB | + +## Concurrent VMs + +To pick the most suitable plan for your use case, consider how many concurrent VMs you require and pick the corresponding plan: + +- Free plan: 5 concurrent VMs +- Pro plan: 20 concurrent VMs +- Builder plan: 100 concurrent VMs +- Enterprise plan: custom concurrent VMs + +In case you expect a a high volume of VM runtime, our Enterprise plan also provides special discounts (up to 50% off) on VM credits. + +## Estimating your bill + +To estimate your bill, you must consider: + +- The base price of your CodeSandbox plan. +- The number of included VM credits on that plan. +- How many VM credits you expect to require. + +As an example, let's say you are planning to run 80 concurrent VMs on average, each running 3 hours per day, every day, on the Pico VM size. Here's the breakdown: + +- You will need a Builder plan (which allows up to 100 concurrent VMs). +- You will use a total of 50,400 VM credits per month (80 VMs x 3 hours/day x 30 days x 7 credits/hour). +- Your Builder plan includes 1100 free VM credits each month, so you will purchase 49,300 VM credits (50,400 - 1100). + +Based on this, your expected bill for that month is: + +- Base price of Builder plan: $170 +- Total price of VM credits: $887.40 (49,300 VM credits x $0.018/credit) +- Total bill: $1057.40 diff --git a/packages/projects-docs/pages/sdk/sandboxes.mdx b/packages/projects-docs/pages/sdk/sandboxes.mdx new file mode 100644 index 00000000..a766dc31 --- /dev/null +++ b/packages/projects-docs/pages/sdk/sandboxes.mdx @@ -0,0 +1,112 @@ +--- +title: Sandboxes +description: Learn how to create sandboxes with the CodeSandbox SDK. +--- + +import { Callout } from 'nextra-theme-docs' + +# Sandboxes + +Sandboxes are the main building block of the CodeSandbox SDK. They represent a single project that you can run, fork, and modify. They are backed by a Firecracker VM. Sandboxes are completely isolated, and persisted, so you can securely run untrusted code in them. + +## Creating a Sandbox + +You can create a sandbox by calling `sandbox.create()`: + +```ts +import { CodeSandbox } from '@codesandbox/sdk' +const sdk = new CodeSandbox(); + +const sandbox = await sdk.sandbox.create(); +``` + +If no argument is provided to `sandbox.create()`, we'll create a sandbox based on our [Universal](https://codesandbox.io/p/devbox/universal-pcz35m) template on CodeSandbox. You can also pass in a template id, either from [our collection of templates](/sdk/snapshot-library) or by creating your own snapshot using our [Snapshot Builder](/sdk/snapshot-builder). + +## Opening an Existing Sandbox + +You can also open an existing sandbox by calling `sandbox.open()`: + +```ts +const sandbox = await sdk.sandbox.open('sandbox-id'); +``` + +This will start the sandbox and connect to it. + +## Opening a Sandbox from the Browser + +It's possible to connect to a sandbox directly from the browser without sharing your API key with the frontend. You can do this by generating a single-use token from the server: + +```ts +import express from 'express'; +import { CodeSandbox } from '@codesandbox/sdk' + +const app = express(); +const sdk = new CodeSandbox(); + +app.get('/api/start-sandbox/:id', async (req, res) => { + const startData = await sdk.sandbox.start(req.params.id); + + res.json(startData); +}); +``` + +From the browser, you can use this start data to connect to the sandbox: + +```ts +import { connectToSandbox } from '@codesandbox/sdk/browser' + +// Fetch the start data from the server +const startData = await fetch('/api/start-sandbox/some-sandbox-id').then(res => res.json()); + +const sandbox = await connectToSandbox(startData); + +// Now you can do whatever you normally do using the SDK +await sandbox.fs.writeFile('./index.html', '

Hello World

'); +sandbox.shells.run('npx -y serve .') +console.log((await sandbox.ports.waitForPort(3000)).getPreviewUrl()) +``` + + +Some APIs are not available when connecting from the browser. For example, you can't hibernate, shutdown or fork a sandbox. + + +## Hibernation & Hibernation Timeout + +When you're done with a sandbox, you can hibernate it. This will save the memory state of the sandbox, so it will resume from the same state when you start it again. + +```ts +await sandbox.hibernate(); +``` + +When starting a sandbox, you can also set a hibernation timeout between 1 minute and 24 hours. By default this timeout is 5 minutes for free users, and 30 minutes for paid users. + +```ts +import { CodeSandbox } from '@codesandbox/sdk' +const sdk = new CodeSandbox(); + +const sandbox = await sdk.sandbox.create({ + hibernationTimeoutSeconds: 60 * 60 * 1 // 1 hour +}); +``` + +When you set a hibernation timeout, the sandbox will hibernate after the specified period of inactivity (no calls from the SDK). While the SDK remains connected, we recommend either explicitly hibernating the sandbox or disconnecting from it when you're done using it. Since resuming only takes a few seconds, you can be aggressive with hibernation to conserve resources. + +## Disconnecting from a Sandbox + +Alternatively, you can disconnect from the sandbox. In this case, it will automatically hibernate after the timeout: + +```ts +await sandbox.disconnect(); +``` + +You can do this if you want a user to still interact with the sandbox, but don't need to keep the SDK connected. + +## Shutdown + +Finally, you can also shutdown a sandbox. This will shut down the sandbox without creating a memory snapshot. Next time the sandbox is started, it will boot from a clean state (but your files in `/project/sandbox` will be preserved). + +```ts +await sandbox.shutdown(); +``` + +Generally you should shutdown a sandbox if you want to start from a clean state. diff --git a/packages/projects-docs/pages/sdk/shells.mdx b/packages/projects-docs/pages/sdk/shells.mdx new file mode 100644 index 00000000..e097d62f --- /dev/null +++ b/packages/projects-docs/pages/sdk/shells.mdx @@ -0,0 +1,115 @@ +--- +title: Shells +description: Learn how the CodeSandbox SDK's shells work. +--- + +# Shells + +The Shell API allows you to create, manage and interact with shell processes in your sandbox. You can create interactive shells, run commands, and execute code in different programming languages. + +## API + +The Shell API is available under `sandbox.shells`. It provides methods for creating shells, running commands, and managing shell instances. + +### Creating Interactive Shells + +You can create an interactive shell that allows you to send commands and receive output: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Create a new shell (bash is default) +const shell = await sandbox.shells.create('bash'); + +// Listen to shell output +shell.onShellOut((output) => { + console.log(output); +}); + +// Send commands to the shell +await shell.write("echo 'Hello, world!'"); + +// Kill the shell when done +await shell.kill(); +``` + +### Running Commands + +For simple command execution, you can use the `run` method which returns a promise with the command's output: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Run a single command +const command = sandbox.shells.run("npm install"); + +// Listen to real-time output +command.onOutput((output) => { + console.log(output); +}); + +// Optionally cancel the command if it's not finished +if (Math.random() > 0.5) { + command.kill(); +} + +// Wait for completion and get results +const result = await command; +console.log(result.output, result.exitCode); +``` + +### Language Interpreters + +The Shell API includes built-in support for running code in different programming languages: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Run JavaScript code +const jsResult = await sandbox.shells.js.run(` + console.log("Hello from Node.js!"); +`); + +// Run Python code +const pythonResult = await sandbox.shells.python.run(` + print("Hello from Python!") +`); +``` + +These interpreters are built on top of the `run` method, so you can use the same options and event listeners. Currently, we only support `python` and `js` interpreters, but we're working on adding more. In the meantime you can use the `run` method to run any command. + +### Managing Shell Instances + +You can list and reconnect to existing shells: + +```ts +const sandbox = await sdk.sandbox.create(); + +// Get all shells +const shells = await sandbox.shells.getShells(); + +// Reconnect to an existing shell +const shell = await sandbox.shells.open(shellId); + +// Check shell status and info +console.log(shell.status); // "RUNNING" | "FINISHED" | "ERROR" | "KILLED" | "RESTARTING" +console.log(shell.exitCode); +console.log(shell.getOutput()); +``` + +## Examples + +### Starting a server and waiting for the port to open + +```ts +const sandbox = await sdk.sandbox.create(); + +const shell = await sandbox.shells.create(); + +// Run in background by not awaiting the command +shell.run("npx serve -y ."); + +const portInfo = await shell.waitForPort(3000); + +console.log(portInfo.getPreviewUrl()); +``` diff --git a/packages/projects-docs/pages/sdk/snapshot-builder.mdx b/packages/projects-docs/pages/sdk/snapshot-builder.mdx new file mode 100644 index 00000000..cc842b95 --- /dev/null +++ b/packages/projects-docs/pages/sdk/snapshot-builder.mdx @@ -0,0 +1,128 @@ +--- +title: Snapshot Builder +description: Learn how to create your own templates with the CodeSandbox SDK. +--- + +import Video from '../../../../shared-components/Video' + +# Snapshot Builder + +If you’re using CodeSandbox SDK, there’s a big chance that you want to customize the base environment of your sandboxes. You might want to preload a custom Docker image, or prestart a server that should be available as soon as you create a sandbox. + +You can use our CLI to create a memory snapshot that has all this data preloaded. This CLI will build a sandbox based on a folder, load the docker image, start the servers and finally create a memory snapshot that can be used when creating new sandboxes. + +New sandboxes can be created from this memory snapshot, which means that new sandboxes will “hit the ground running” with the servers running during snapshot creation. Creating a sandbox from a memory snapshot takes 1-3 seconds. + +