diff --git a/README.md b/README.md
index 739d031..ac693ba 100644
--- a/README.md
+++ b/README.md
@@ -102,7 +102,7 @@ After cloning the repository, run the docs site in development mode with:
```sh
npm install
-npm start
+npm run dev
```
### Editor setup
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index 82037af..684c606 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -15,10 +15,7 @@ const SIDEBAR_DEFAULT = [
items: links.guideLinks,
},
{
- text: 'Tutorial',
- collapsible: true,
- collapsed: false,
- items: links.tutorialLinks,
+ items: [{ text: 'Tutorial', link: 'https://webcontainer-tutorial.pages.dev', target: "_blank" }],
},
{
items: [{ text: 'API Reference', link: '/api' }],
@@ -27,7 +24,7 @@ const SIDEBAR_DEFAULT = [
items: [{ text: 'Changelog', link: '/changelog' }],
},
{
- items: [{ text: 'Enterprise', link: '/enterprise' }],
+ items: [{ text: 'Commercial Usage', link: '/enterprise' }],
},
{
text: 'Community Projects',
@@ -56,7 +53,7 @@ export default defineConfig({
},
],
},
-
+
srcDir: '.',
outDir: 'build',
@@ -73,7 +70,7 @@ export default defineConfig({
'Build the future of web based coding experiences, from interactive tutorials to instant production-ready dev environments.',
head: getHeadTags(process.env),
// See docs: https://vitepress.vuejs.org/guides/theme-nav
-
+
// Sitemap
lastUpdated: true,
sitemap: {
@@ -89,9 +86,10 @@ export default defineConfig({
},
nav: [
{ text: 'Guides', link: '/guides/introduction' },
- { text: 'Tutorial', link: '/tutorial/1-build-your-first-webcontainer-app' },
+ { text: 'Tutorial', link: 'https://webcontainer-tutorial.pages.dev', target: '_blank' },
{ text: 'API Reference', link: '/api' },
- { text: 'Enterprise', link: '/enterprise' },
+ { text: 'AI', link: '/ai' },
+ { text: 'Pricing', link: 'https://stackblitz.com/pricing#webcontainer-api' },
],
sidebar: {
'/guides/': SIDEBAR_DEFAULT,
diff --git a/docs/.vitepress/theme/components/Ai.vue b/docs/.vitepress/theme/components/Ai.vue
new file mode 100644
index 0000000..f832274
--- /dev/null
+++ b/docs/.vitepress/theme/components/Ai.vue
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
The best runtime for your AI Agents.
+
Looking for proper test cases to evaluate an AI agent? We've assembled the best test cases based on npm stats and usage by millions of developers.
+
Learn more
+
+
+
+
+
+
+
Improve the quality of your AI-generated code
+
To ensure code generated by your LLM is valid, performant, and satisfies the prompt, you need to be able to actually execute it. The WebContainer API enables this securely, right inside the user's browser tab.
+
+
+
Provide a better developer experience for your users
+
With the WebContainer API you can provide your users a low-latency in-browser code execution environment seamlessly integrated into your AI application so they can get production-ready code faster.
+
+
+
Avoid infrastructure and security headaches
+
With no virtual machines or network connections to manage, you can ensure untrusted AI-generated code doesn’t pose security risks to you or your end users.
+
+
+
+
+
+
+
Leverage the tech we use
in our own products.
+
WebContainers already powers production developer experiences from interactive tutorials to full-blown IDEs. With the WebContainer API, you can build a secure and performant coding environment into your AI applications without worrying about provisioning infrastructure.
+
Get started!
+
+
+
+
+
+
+
diff --git a/docs/.vitepress/theme/components/AuthButtons/AuthButtons.vue b/docs/.vitepress/theme/components/AuthButtons/AuthButtons.vue
new file mode 100644
index 0000000..d1dd86e
--- /dev/null
+++ b/docs/.vitepress/theme/components/AuthButtons/AuthButtons.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
diff --git a/docs/.vitepress/theme/components/AuthButtons/NavBarAuthButtons.vue b/docs/.vitepress/theme/components/AuthButtons/NavBarAuthButtons.vue
new file mode 100644
index 0000000..0a95d1a
--- /dev/null
+++ b/docs/.vitepress/theme/components/AuthButtons/NavBarAuthButtons.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/docs/.vitepress/theme/components/AuthButtons/NavScreenAuthButtons.vue b/docs/.vitepress/theme/components/AuthButtons/NavScreenAuthButtons.vue
new file mode 100644
index 0000000..e372a8a
--- /dev/null
+++ b/docs/.vitepress/theme/components/AuthButtons/NavScreenAuthButtons.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/docs/.vitepress/theme/components/AuthButtons/linkStyles.scss b/docs/.vitepress/theme/components/AuthButtons/linkStyles.scss
new file mode 100644
index 0000000..7aaa0fd
--- /dev/null
+++ b/docs/.vitepress/theme/components/AuthButtons/linkStyles.scss
@@ -0,0 +1,48 @@
+
+.link {
+ --outline-color-hsl: 0, 0%, 100%;
+ --outline-opacity: 0.08;
+ --text-strong-color: #fff;
+ display: flex;
+ align-items: center;
+ height: 36px;
+ padding: 0 20px;
+ border-radius: 8px;
+ color: var(--text-strong-color);
+ font-size: 13px;
+ font-weight: 500;
+ text-decoration: none;
+ box-shadow: inset 0 0 0 1px hsla(var(--outline-color-hsl), var(--outline-opacity));
+ background-color: hsla(224, 32%, 28%, 0.24);
+ backdrop-filter: blur(8px);
+ transition: 0.1s ease;
+ transition-property: background-color, box-shadow, color;
+ }
+
+ .light {
+ &:hover {
+ --outline-opacity: 0.14;
+ color: var(--text-strong-color);
+ background-color: hsla(224, 32%, 28%, 0.54);
+ }
+ :root:not(.dark) & {
+ --outline-color-hsl: 224, 32%, 28%;
+ --outline-opacity: 0.1;
+ color: hsl(240, 6%, 23%);
+ background-color: hsla(224, 32%, 28%, 0.1);
+ &:hover {
+ --outline-opacity: 0.2;
+ background-color: transparent;
+ }
+ }
+ }
+
+ .accent {
+ --outline-opacity: 0.14;
+ color: var(--text-strong-color);
+ background-color: hsl(214, 87%, 51%);
+ &:hover {
+ --outline-opacity: 0.24;
+ background-color: hsl(208, 100%, 53%);
+ }
+ }
\ No newline at end of file
diff --git a/docs/.vitepress/theme/components/CustomLayout.vue b/docs/.vitepress/theme/components/CustomLayout.vue
index c433eba..73f4038 100644
--- a/docs/.vitepress/theme/components/CustomLayout.vue
+++ b/docs/.vitepress/theme/components/CustomLayout.vue
@@ -1,13 +1,17 @@
-
+
+
+
@@ -15,5 +19,8 @@ const { Layout } = DefaultTheme;
+
+
+
diff --git a/docs/.vitepress/theme/components/Hero/Hero.vue b/docs/.vitepress/theme/components/Hero/Hero.vue
index e593ec3..2866b8f 100644
--- a/docs/.vitepress/theme/components/Hero/Hero.vue
+++ b/docs/.vitepress/theme/components/Hero/Hero.vue
@@ -9,8 +9,8 @@ import WCEmbed from '@theme/components/Examples/WCEmbed/WCEmbed.vue';
Dev environments.
In your web app.
From interactive tutorials to full-blown IDEs, build instant, interactive coding experiences backed by WebContainers: the trusted, browser-based runtime from StackBlitz.
- Get started
- Learn more
+ Get started
+ Book a demo
diff --git a/docs/.vitepress/theme/components/Hero/HeroAi.vue b/docs/.vitepress/theme/components/Hero/HeroAi.vue
new file mode 100644
index 0000000..706bace
--- /dev/null
+++ b/docs/.vitepress/theme/components/Hero/HeroAi.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
diff --git a/docs/.vitepress/theme/components/WCUsedByOrgs/WCUsedBy.vue b/docs/.vitepress/theme/components/WCUsedByOrgs/WCUsedBy.vue
index 8503292..65d0c47 100644
--- a/docs/.vitepress/theme/components/WCUsedByOrgs/WCUsedBy.vue
+++ b/docs/.vitepress/theme/components/WCUsedByOrgs/WCUsedBy.vue
@@ -6,11 +6,13 @@
-
![]()
+
+
+
diff --git a/docs/.vitepress/theme/data/community-projects.ts b/docs/.vitepress/theme/data/community-projects.ts
index e65d5e8..c103fc0 100644
--- a/docs/.vitepress/theme/data/community-projects.ts
+++ b/docs/.vitepress/theme/data/community-projects.ts
@@ -1,6 +1,6 @@
export type CardLinkType = 'article'|'podcast'|'repositoryGithub'|'video';
-export type CommunityProjectCategory = 'ai'|'game'|'ide'|'lowCode'|'tutorial';
+export type CommunityProjectCategory = 'ai'|'game'|'ide'|'tool'|'lowCode'|'tutorial';
export type CommunityProjectCategories = { [project in CommunityProjectCategory]: {
rgb: string;
title: string;
@@ -20,7 +20,12 @@ export const communityProjectCategories: CommunityProjectCategories = {
ide: {
rgb: '31, 143, 255',
title: 'Browser IDE',
- titlePlural: 'Browser IDEs',
+ titlePlural: 'Browser IDE',
+ },
+ tool: {
+ rgb: '231, 203, 255',
+ title: 'Tool',
+ titlePlural: 'Tools',
},
lowCode: {
rgb: '255, 9, 255',
@@ -56,6 +61,13 @@ export const communityProjectCardData: CommunityProjectCardData[] = [
itemUrl: '/community-projects/stackblitz-codeflow',
thumbnailUrl: '/img/community/codeflow.png',
},
+ {
+ category: 'tutorial',
+ title: 'Angular Tutorial',
+ description: 'The official Angular Tutorial at angular.dev.',
+ itemUrl: '/community-projects/angular-tutorial',
+ thumbnailUrl: '/img/community/angular-tutorial.png',
+ },
{
category: 'ai',
title: 're:tune',
@@ -83,5 +95,47 @@ export const communityProjectCardData: CommunityProjectCardData[] = [
description: `The API Security Academy is a new interactive learning platform focused on mastering GraphQL security.`,
itemUrl: '/community-projects/api-security-academy',
thumbnailUrl: '/img/community/api_security_academy.png',
- }
+ },
+ {
+ category: 'ai',
+ title: 'Otto Engineer',
+ description: `The AI sidekick that tests its own code and iterates until it works.`,
+ itemUrl: '/community-projects/otto-engineer',
+ thumbnailUrl: '/img/community/otto_engineer.png',
+ },
+ {
+ category: 'ide',
+ title: 'Stylelint Playground',
+ description: `A live playground where you can experiment with styleling rulesets using various packages.`,
+ itemUrl: '/community-projects/stylelint-playground',
+ thumbnailUrl: '/img/community/stylelint-playground.png',
+ },
+ {
+ category: 'ide',
+ title: 'builder.io playground',
+ description: `Explore builder.io's visual editor fully in the browser.`,
+ itemUrl: '/community-projects/builder-io-playground',
+ thumbnailUrl: '/img/community/builder-io-playground.png',
+ },
+ {
+ category: 'ide',
+ title: 'VSLite',
+ description: `A lighweight IDE-like experience with a fresh Node.js environment for you to play with.`,
+ itemUrl: '/community-projects/vslite',
+ thumbnailUrl: '/img/community/vslite.png',
+ },
+ {
+ category: 'tool',
+ title: 'pkg-size',
+ description: `Find the true size of an npm package.`,
+ itemUrl: '/community-projects/pkg-size',
+ thumbnailUrl: '/img/community/pkg-size.png',
+ },
+ {
+ category: 'tool',
+ title: 'clack.cc',
+ description: `Build your own custom CLI with a set of feature-rich components.`,
+ itemUrl: '/community-projects/clack',
+ thumbnailUrl: '/img/community/clack.png',
+ },
];
diff --git a/docs/.vitepress/theme/data/links.ts b/docs/.vitepress/theme/data/links.ts
index a12abaa..00d3c89 100644
--- a/docs/.vitepress/theme/data/links.ts
+++ b/docs/.vitepress/theme/data/links.ts
@@ -5,7 +5,9 @@ export const guideLinks = [
{ text: 'Running Processes', link: '/guides/running-processes' },
{ text: 'Configuring Headers', link: '/guides/configuring-headers' },
{ text: 'Troubleshooting', link: '/guides/troubleshooting'},
+ { text: 'Runtime Test Cases for AI Agents', link: '/guides/ai-agents'},
{ text: 'Browser Support', link: '/guides/browser-support' },
+ { text: 'API Versioning and Support', link: '/guides/api-support' },
{ text: 'Browser Configuration', link: '/guides/browser-config' },
];
@@ -22,11 +24,18 @@ export const tutorialLinks = [
export const communityProjectsLinks = [
{ text: 'All Projects', link: '/community-projects/all-projects' },
{ text: 're:tune', link: '/community-projects/retune' },
+ { text: 'Angular Tutorial', link: '/community-projects/angular-tutorial' },
{ text: 'schachnovelle', link: '/community-projects/schachnovelle' },
{ text: 'StackBlitz Codeflow', link: '/community-projects/stackblitz-codeflow' },
{ text: 'StackBlitz Web Publisher', link: '/community-projects/stackblitz-web-publisher' },
{ text: 'SvelteKit', link: '/community-projects/sveltekit' },
{ text: 'API Security Academy', link: '/community-projects/api-security-academy' },
+ { text: 'Otto Engineer', link: '/community-projects/otto-engineer' },
+ { text: 'Stylelint Playground', link: '/community-projects/stylelint-playground' },
+ { text: 'builder.io playground', link: '/community-projects/builder-io-playground' },
+ { text: 'VSLite', link: '/community-projects/vslite' },
+ { text: 'pkg-size', link: '/community-projects/pkg-size' },
+ { text: 'clack.cc', link: '/community-projects/clack' },
];
export const footerSections = [
@@ -61,7 +70,7 @@ export const footerSections = [
items: [
{ text: 'Docs', link: 'https://developer.stackblitz.com/' },
{ text: 'Enterprise', link: 'https://stackblitz.com/enterprise' },
- { text: 'Pricing', link: 'https://stackblitz.com/membership' },
+ { text: 'Pricing', link: 'https://stackblitz.com/pricing' },
{ text: 'Case Studies', link: 'https://stackblitz.com/case-studies' },
],
},
diff --git a/docs/.vitepress/theme/styles/fixes.scss b/docs/.vitepress/theme/styles/fixes.scss
index 0661fea..47a66b3 100644
--- a/docs/.vitepress/theme/styles/fixes.scss
+++ b/docs/.vitepress/theme/styles/fixes.scss
@@ -33,7 +33,7 @@
// We would like to have single pages in the sidebar (e.g. API Reference, Enterprise).
// VitPress expects to have you section title text + items and when you only have one item it looks like there are extra spacing.
-// These styles are to adjust spacing between groups.
+// These styles are to adjust spacing between groups.
#VPSidebarNav .group {
padding-top: 0;
}
@@ -130,6 +130,11 @@ padding-top: 8px;
}
}
+// Hide social links in the nav bar
+.VPSocialLinks.VPNavBarSocialLinks {
+ display: none;
+}
+
// New body styles
.vp-doc p,
.vp-doc li {
@@ -322,7 +327,7 @@ h2 .header-anchor {
margin-top: 24px;
}
// Hide extraneous visual elements when parent group is collapsed
-// without messing with individual elements themselves.
+// without messing with individual elements themselves.
.VPSidebarGroup.collapsed .items {
opacity: 0;
}
@@ -476,7 +481,7 @@ h2 + .custom-block {
margin: 2px 0 0;
font-size: 14px;
line-height: 1.8;
-
+
&.custom-block-title {
position: relative;
margin-bottom: 8px;
@@ -521,14 +526,6 @@ h2 + .custom-block {
transition-duration: 0.1s;
}
-.vp-doc .custom-block code {
- color: var(--vp-c-text-1);
- box-shadow: 0 0 0 1px rgba(0,0,0,0.1);
- :root.dark & {
- box-shadow: 0 0 0 1px rgba(255,255,255,0.16);
- }
-}
-
.vp-doc .custom-block ul {
margin-bottom: 0;
}
diff --git a/docs/ai.md b/docs/ai.md
new file mode 100644
index 0000000..efeb028
--- /dev/null
+++ b/docs/ai.md
@@ -0,0 +1,20 @@
+---
+layout: page
+title: &title In-browser code execution for AI
+description: &description Execute, interpret, and refactor AI-generated code directly in the browser, a secure, sandboxed environment with zero latency, zero compute costs, and zero virtual machines.
+head:
+ - ['meta', { property: 'og:title', content: *title }]
+ - [
+ 'meta',
+ { property: 'og:image', content: 'https://webcontainers.io/img/og/ai.png' },
+ ]
+ - ['meta', { name: 'twitter:title', content: *title }]
+ - ['meta', { name: 'twitter:description', content: *description }]
+---
+
+
+
+
diff --git a/docs/api.md b/docs/api.md
index c847e00..c6727a2 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -30,11 +30,22 @@ The main export of this library. An instance of `WebContainer` represents a runt
Gives access to the underlying file system.
+
+
+#### path: string
+
+The default value of the `PATH` environment variable for processes started through [`spawn`](#▸-spawn).
+
+
+
+#### workdir: string
+
+The full path to the working directory (see [FileSystemAPI](#filesystemapi)).
+
### `WebContainer` Methods
### ▸ `boot`
-
-Boots a [WebContainer](#webcontainer). Only a single instance of WebContainer can be booted.
+Boots a WebContainer. Only a single instance of WebContainer can be booted concurrently (see [`teardown`](#▸-teardown)). Booting WebContainer is an expensive operation.
Signature
@@ -51,14 +62,15 @@ Boots a [WebContainer](#webcontainer). Only a single instance of WebContainer ca
Returns a [`WebContainer`](#webcontainer) instance.
```ts
-interface Options {
+interface BootOptions {
coep?: 'require-corp' | 'credentialless' | 'none';
workdirName?: string;
+ forwardPreviewErrors?: boolean | 'exceptions-only';
}
```
@@ -66,11 +78,9 @@ interface Options {
#### `coep?: 'require-corp' | 'credentialless' | 'none'`
-The value of the [COEP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) header
-used to load your application.
+The value of the [COEP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) header used to load your application.
-Choosing `'none'` will result in no cross-origin isolation headers being used. This will only work on Chromium-based
-browsers as long as an Origin Trial is supported.
+Choosing `'none'` will result in no cross-origin isolation headers being used. This will only work on Chromium-based browsers as long as an Origin Trial is supported.
This value is fixed the first time a WebContainer is booted, and cannot be changed in successive reboots.
@@ -80,16 +90,36 @@ Sets the _folder name_ for the working directory of your WebContainer instance.
This is mostly a "cosmetic" option.
+#### `forwardPreviewErrors?: boolean | 'exceptions-only'`
+
+Configure whether errors occurring in embedded preview iframes should be forwarded to the parent page. Captured errors originate from:
+
+ - Calls to `console.error`
+ - Any `unhandledrejection` events on `window`
+ - Any uncaught `error` events on `window`
+
+If set to `exceptions-only`, `console.error`s are not forwarded.
+
+Default value is `false`, so no errors are emitted.
+
+To receive the events, you register an event handler like this:
+
+```js
+webcontainerInstance.on('preview-message', (message) => {
+ // process the message received from a preview
+});
+```
+
### ▸ `mount`
-Mounts a [`FileSystemTree`](#filesystemtree) into the file system.
+Mounts a tree of files into the filesystem. This can be specified as a [FileSystemTree](#filesystemtree) object or as a binary snapshot generated by [`@webcontainer/snapshot`](https://www.npmjs.com/package/@webcontainer/snapshot).
-mount(tree: FileSystemTree | Uint8Array, options?: Options): Promise
+mount(tree: FileSystemTree | Uint8Array | ArrayBuffer, options?: Options): Promise
Options
@@ -114,7 +144,7 @@ Listens for an `event`. The `listener` is called every time the `event` gets emi
@@ -163,6 +193,55 @@ Listens for `error` events, emitted when an internal error is triggered.
+
+ ▸ on(event: 'preview-message', listener: PreviewMessageListener): () => void
+
+
+Listens for `preview-message` events, emitted when an internal error is triggered.
+
+`PreviewMessageListener` (Function)
+
+```ts
+(message: PreviewMessage): void
+```
+
+
+
+```ts
+type PreviewMessage = (UncaughtExceptionMessage | UnhandledRejectionMessage | ConsoleErrorMessage) & BasePreviewMessage;
+
+interface BasePreviewMessage {
+ previewId: string;
+ port: number;
+ pathname: string;
+ search: string;
+ hash: string;
+}
+
+interface UncaughtExceptionMessage {
+ type: PreviewMessageType.UncaughtException;
+ message: string;
+ stack: string | undefined;
+}
+
+interface UnhandledRejectionMessage {
+ type: PreviewMessageType.UnhandledRejection;
+ message: string;
+ stack: string | undefined;
+}
+
+interface ConsoleErrorMessage {
+ type: PreviewMessageType.ConsoleError;
+ args: any[];
+ stack: string;
+}
+```
+
+
+
▸ on(event: 'server-ready', listener: ServerReadyListener): () => void
@@ -231,9 +310,85 @@ Spawns a process with additional arguments.
Spawns a process without additional arguments.
+### ▸ `export`
+
+Added in version `1.4.0`.
+
+Exports the filesystem.
+
+
+
+export(path: string, options?: ExportOptions): PromiseFileSystemTree>
+
+
+
+```js
+const data = await webcontainerInstance.export('dist', { format: 'zip' });
+
+const zip = new Blob([data]);
+```
+
+
+
+Returns a [`FileSystemTree`](#filesystemtree) when the format is `json`, otherwise a `Uint8Array`.
+
+### ▸ `setPreviewScript`
+
+Added in version `1.5.0`.
+
+Configure a script to be injected inside all previews. After this function resolves,
+every preview iframe that is either added or reloaded will now include this extra
+script on all HTML responses.
+
+Notably, existing previews won't include the script until they have been reloaded.
+
+To reload a preview you can use [`reloadPreview`](#reloadpreview)
+
+:::warning
+This API is an advanced feature that should only be used if it is your only option.
+Since you can control servers running in WebContainer, it's preferable to add this code when serving the content itself.
+
+
+
+In particular, this might break existing WebContainer features or ones that will be added later.
+:::
+
+
+
+setPreviewScript(scriptSrc: string, options?: PreviewScriptOptions): Promise<void>
+
+
+
+```js
+const script = `
+ console.log('Hello world!');
+`;
+
+await webcontainerInstance.setPreviewScript(script);
+
+// now all previews will always print hello world to the console if they serve HTML
+```
+
### ▸ `teardown`
-Destroys a [`WebContainer`](#webcontainer) instance and releases its resources.
+Destroys the WebContainer instance, turning it unusable, and releases its resources. After this, a new WebContainer instance can be obtained by calling [`boot`](#▸-boot).
+
+All entities derived from this instance (e.g. processes, the file system, etc.) also become unusable after calling this method.
Signature
@@ -244,6 +399,234 @@ Destroys a [`WebContainer`](#webcontainer) instance and releases its resources.
---
+## `reloadPreview`
+
+Added in version `1.2.2`.
+
+Reload the provided iframe by sending a message to the iframe and falling back to resetting the `src` if the iframe didn't respond in time.
+
+
+
+
+
+
+ reloadPreview(preview: HTMLIFrameElement, hardRefreshTimeout?: number = 200): Promise<void>
+
+
+
+
+
+
+Returns a `Promise` that resolves when the reload has completed.
+
+## `configureAPIKey`
+
+Added in version `1.3.0`.
+
+Configure an API key to be used for commercial usage of the WebContainer API. See https://webcontainers.io/enterprise for more information.
+
+
+
+
+
+
+
+This function will throw an exception if `WebContainer.boot` was called before `configureAPIKey`.
+
+## `auth`
+
+The authentication API is exported under the `auth` namespace. It allows you to authenticate users visiting your website via StackBlitz. In order for users to be authenticated via this method, they must:
+
+ * Be logged in on StackBlitz.
+ * Belong to the organisation you used to generate your `clientId` for use with the WebContainer API.
+ * Authorize your website.
+
+Once logged in, you'll be able to install private packages that those users have access to within WebContainer.
+
+### `auth` Functions
+
+### ▸ `init`
+
+Intialize the authentication for use in WebContainer. This method should be called as soon as possible as part of the loading phase of your page. For example at the top of a module that gets loaded as soon as the page loads. This is important for multiple reasons:
+
+ * If you do client side routing, and the OAuth flow is happening, then query parameters might be populated with values related to the OAuth flow. The `init` function removes them after they've been consumed.
+
+ * If you do the authentication in popup mode, you likely want the popup to be closed as soon as the authentication completed.
+
+
+
+init(options: AuthInitOptions): { status: 'need-auth' | 'authorized' } | AuthFailedError
+
+This function will throw an exception if `WebContainer.boot` was called before `auth.init`.
+
+
+
+
+
+```ts
+interface AuthInitOptions {
+ /**
+ * StackBlitz' origin.
+ *
+ * @default https://stackblitz.com
+ */
+ editorOrigin?: string;
+
+ /**
+ * The client id for this OAuth application.
+ */
+ clientId: string;
+
+ /**
+ * OAuth scope. The value can be found under your `Teams Settings` > `API`.
+ *
+ * @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
+ */
+ scope: string;
+}
+```
+
+
+
+```ts
+interface AuthFailedError {
+ status: 'auth-failed';
+
+ /**
+ * A short description of the error.
+ */
+ error: string;
+
+ /**
+ * A detailed description of the error.
+ */
+ description: string;
+}
+```
+
+### ▸ `startAuthFlow`
+
+This starts the OAuth flow, redirecting the current page to the StackBlitz editor to authenticate the user unless `popup` is set to true in which case it's done in a popup.
+
+startAuthFlow(options?: { popup?: boolean }): void
+
+### ▸ `loggedIn`
+
+Returns a promise that resolves when the user authorized your application. This promise is guaranteed to never be rejected.
+
+If the user never authorizes or declines your application, this promise never resolves.
+
+
+
+loggedIn(): Promise
+
+
+
+```ts
+const instance = await WebContainer.boot();
+
+// wait until the user is logged in
+await auth.loggedIn();
+
+// we can now fetch private packages from our organisation
+await instance.spawn('npm', ['install']);
+```
+
+### ▸ `logout`
+
+Logout the user and clear any credentials that were saved locally.
+
+If `ignoreRevokeError` is set and the revocation failed, the locally-saved credentials are discarded nonetheless.
+
+
+
+logout(options?: { ignoreRevokeError?: boolean }): Promise
+
+### ▸ `on`
+
+Listens for an `event`. The `listener` is called every time the `event` gets emitted.
+
+
+
+
+
+
+ on(event: 'logged-out' | 'auth-failed', listener: () => void | (reason: { error: string, description: string }) => void): () => void
+
+
+
+
+
+
+Returns a function to unsubscribe from the events. Once unsubscribed, the `listener` will no longer be called.
+
+
+
+
+
+
+
+
+ ▸ on(event: 'logged-out', listener: () => void): () => void
+
+
+Listens for `logged-out` events, which are emitted when the credentials are revoked, meaning the user needs to re-authenticate.
+
+
+
+
+ ▸ on(event: 'auth-failed', listener: (reason: { error: string, description: string }) => void): () => void
+
+
+Listens for `auth-failed` events, which are emitted when the user declines authorization in another tab / popup.
+
+The property `error` corresponds to a constant that your code can match against, while `description` is a human readable error that can be useful for development. The possible values of `error` are:
+
+ - `access_denied`: The user denied the authorization request.
+ - `invalid_scope`: The scope is invalid, unknown or malformed.
+
+More might be addded in the future, which is reason behind having `error` typed as a `string` instead of an union.
+
+---
+
## `DirEnt`
A representation of a directory entry, see [the Node.js API](https://nodejs.org/dist/latest-v16.x/docs/api/fs.html#class-fsdirent).
@@ -529,7 +912,7 @@ Specifies the character encoding to be used for the filename passed to the liste
#### `recursive?: boolean`
-Indicates whether all subdirectories should be watched, or only the current directory. This applies when a directory is specified, and only on supported platforms. Default: `false`.
+Indicates whether all subdirectories should be watched, or only the current directory. This applies when a directory is specified. Default: `false`.
Listener
@@ -586,11 +969,11 @@ A tree-like structure to describe the contents of a folder to be mounted.
```ts
interface FileSystemTree {
- [name: string]: FileNode | DirectoryNode;
+ [name: string]: FileNode | SymlinkNode | DirectoryNode;
}
```
-Also see [`FileNode`](#filenode) and [`DirectoryNode`](#directorynode).
+Also see [`FileNode`](#filenode), [`SymlinkNode`](#symlinknode), and [`DirectoryNode`](#directorynode).
Example
@@ -606,7 +989,12 @@ const tree = {
contents: 'const x = 1;',
},
},
- .envrc: {
+ 'bar.js': {
+ file: {
+ symlink: './foo.js',
+ },
+ },
+ '.envrc': {
file: {
contents: 'ENVIRONMENT=staging'
}
@@ -641,6 +1029,26 @@ Represents a file with contents. Also see [`FileSystemTree`](#filesystemtree).
---
+## `SymlinkNode`
+
+```ts
+interface SymlinkNode {
+ file: {
+ symlink: string;
+ };
+}
+```
+
+### `SymlinkNode` Properties
+
+
+
+#### ▸ `file: { symlink: string }`
+
+Represents a symlink pointing to another location. Also see [`FileSystemTree`](#filesystemtree).
+
+---
+
## `DirectoryNode`
```ts
@@ -665,6 +1073,7 @@ Options that control spawning a process.
```ts
export interface SpawnOptions {
+ cwd?: string;
env?: Record;
output?: boolean;
terminal?: { cols: number; rows: number };
@@ -675,6 +1084,14 @@ export interface SpawnOptions {
+#### ▸ `cwd?: string`
+
+Current working directory for the process, relative to [`workdir`](#workdir-string) this instance (which you can change when [booting `WebContainer`](#▸-boot)).
+
+By default, the working directory of the spawned process is [`workdir`](#workdir-string).
+
+
+
#### ▸ `env?: Record`
Environment variables to set for the process.
@@ -693,6 +1110,76 @@ The size of the attached terminal.
---
+## `ExportOptions`
+
+Options that control exporting data.
+
+```ts
+export interface ExportOptions {
+ format?: 'json' | 'binary' | 'zip',
+ includes?: string[];
+ excludes?: string[];
+}
+```
+
+### `ExportOptions` Properties
+
+
+
+#### ▸ `format?: 'json' | 'binary' | 'zip'`
+
+The format of the exported data. The `json` and `binary` format can be used as `tree` when calling [`mount`](#▸-mount).
+
+The default value is `json`.
+
+
+
+#### ▸ `includes?: string[]`
+
+Globbing patterns to include files from within excluded folders.
+
+
+
+#### ▸ `excludes?: string[]`
+
+Globbing patterns to exclude files from the export.
+
+---
+
+## `PreviewScriptOptions`
+
+Options that control attributes on a script injected into previews.
+
+```ts
+export interface PreviewScriptOptions {
+ type?: 'module' | 'importmap';
+ defer?: boolean;
+ async?: boolean;
+}
+```
+
+### `PreviewScriptOptions` Properties
+
+
+
+#### ▸ `type?: 'module' | 'importmap'`
+
+The type attribute to use for the script. For more information, check the [MDN page on the script: type attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type).
+
+
+
+#### ▸ `defer?: boolean`
+
+If set to true, then the `defer` attribute will be set on the script tag. For more information, check the [MDN page on the script: defer attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#async).
+
+
+
+#### ▸ `async?: boolean`
+
+If set to true, then the `async` attribute will be set on the script tag. For more information, check the [MDN page on the script: async attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#async).
+
+---
+
## `WebContainerProcess`
A running process spawned in a [WebContainer](#webcontainer) instance.
diff --git a/docs/changelog.md b/docs/changelog.md
index 85fb5aa..f0e9318 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -10,6 +10,51 @@ head:
# Changelog
+## 1.5.1
+
+* Fix ESM import issue introduced in `1.4.0`.
+
+## 1.5.0
+
+* Add support for injecting a script in previews with [`setPreviewScript`](api#▸-setPreviewScript).
+
+## 1.4.0
+
+* Add support for exporting the file system with [`export`](api#▸-export).
+
+## 1.3.0
+
+* Breaking change: we now throw if [`auth.init`](api#▸-init) is called after [`WebContainer.boot`](api#▸-boot)
+* Add [`configureAPIKey`](api#configureapikey) to use the API with an API key.
+* Add `stack` information to `console.error` messages coming from previews.
+
+## 1.2.4
+
+* Bug fix: [`reloadPreview`](api#reloadpreview) was always doing a hard refresh as the port was not transferred.
+
+## 1.2.3
+
+* Make `@webcontainer/api` ESM and SSR friendly again.
+* Emit preview messages on the webcontainer's [`on('preview-message')`](api#on-overloads) event handler.
+
+## 1.2.2
+
+* Add [`reloadPreview`](api#reloadpreview) utility, also exported under `@webcontainer/api/utils`.
+
+## 1.2.1
+
+:::warning
+It's recommended to use version `>= 1.2.3` to use `forwardPreviewErrors` as you cannot add an
+event listener in the `webcontainerInstance` in that version.
+:::
+
+* Add `forwardPreviewErrors` to [`BootOptions`](api#boot-options) which lets you capture "errors" from previews.
+
+## 1.2.0
+
+* Add support for [`authentication`](api#auth).
+* Add [`cwd`](api#▸-cwd-string) option to [`SpawnOptions`](api#spawnoptions).
+
## 1.1.8
* Add [`fs.watch`](api#▸-watch).
diff --git a/docs/community-projects/angular-tutorial.md b/docs/community-projects/angular-tutorial.md
new file mode 100644
index 0000000..e4ddab7
--- /dev/null
+++ b/docs/community-projects/angular-tutorial.md
@@ -0,0 +1,26 @@
+---
+title: &title Angular Tutorial
+description: &description The official Angular Tutorial at angular.dev.
+outline: [2, 3]
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-community_inspirations.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+
+
+
+This interactive tutorial will teach you the basic building blocks to start building great apps with Angular.
+
+You'll need to have basic familiarity with HTML, CSS and JavaScript to understand Angular.
+
+Each step represents a concept in Angular. You can do one, or all of them.
+
+If you get stuck, click "Reveal answer" at the top.
+
+
diff --git a/docs/community-projects/builder-io-playground.md b/docs/community-projects/builder-io-playground.md
new file mode 100644
index 0000000..d452c62
--- /dev/null
+++ b/docs/community-projects/builder-io-playground.md
@@ -0,0 +1,20 @@
+---
+title: &title builder.io playground
+description: &description Explore builder.io's visual editor fully in the browser.
+outline: [2, 3]
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-community_inspirations.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+
+
+
+Explore builder.io's visual editor fully in the browser
+
+
diff --git a/docs/community-projects/clack.md b/docs/community-projects/clack.md
new file mode 100644
index 0000000..7124216
--- /dev/null
+++ b/docs/community-projects/clack.md
@@ -0,0 +1,22 @@
+---
+title: &title clack.cc
+description: &description Build your own custom CLI with a set of feature-rich components.
+outline: [2, 3]
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-community_inspirations.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+
+
+
+Building interactive command line applications doesn't have to be so hard. `@clack/core` provides unstyled, feature-rich components designed to be a strong foundation for your custom CLIs.
+
+Of course, sometimes you just want to use something well-designed. That's why `@clack/prompts` comes out-of-the-box with beautiful prompts and a straightforward API.
+
+
diff --git a/docs/community-projects/otto-engineer.md b/docs/community-projects/otto-engineer.md
new file mode 100644
index 0000000..2983695
--- /dev/null
+++ b/docs/community-projects/otto-engineer.md
@@ -0,0 +1,26 @@
+---
+title: &title Otto Engineer | Community Projects
+description: &description The AI sidekick that tests its own code and iterates until it works.
+outline: [2, 3]
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-community_inspirations.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+
+
+
+
+Otto Engineer is an autonomous agent that takes AI-assisted coding to the next level.
+
+* **Otto checks its work and iterates**: Otto executes its code and tests it to make sure it works. If there are errors, it will keep iterating until the code works 🦾
+* **Otto executes its code safely in isolation**: Otto is built on [Web Containers](https://webcontainers.io/guides/introduction), a runtime for executing Node.js and OS commands that runs entirely in the browser, with a virtual, in-memory file system 🤓
+* **Otto requires zero setup**: Since it all runs in the browser, you just start a new chat and put Otto to work, watching it run commands and edit code in the embedded terminal and editor 🔥
+* **Otto operates in a real environment**: Otto can install and use npm packages, tweak its TS config, and write its own tests. Say goodbye to hallucinated code that doesn't actually work 👋
+
+
diff --git a/docs/community-projects/pkg-size.md b/docs/community-projects/pkg-size.md
new file mode 100644
index 0000000..cd4165a
--- /dev/null
+++ b/docs/community-projects/pkg-size.md
@@ -0,0 +1,46 @@
+---
+title: &title pkg-size
+description: &description Find the true size of an npm package.
+outline: [2, 3]
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-community_inspirations.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+
+
+
+
+
+Find the true size of an npm package.
+
+# Why?
+
+## **For Package Users**
+
+### Get Insights
+* **Get insights:** Package dependencies can be deceiving—a package with one direct dependency may actually install 100 indirect dependencies. Find out everything getting installed.
+
+### Install Cost
+* **Install cost:** The size of `node_modules` can easily get out of control. Be mindful of what you're installing and keep it in check.
+
+### Bundle Cost
+* **Bundle cost:** Importing a large dependency to your web app can easily impact its performance. It can bloat your app, slow-down load time, and increase memory usage. Optimize for ESM packages that are tree-shakeable.
+
+### **For Package Authors**
+
+### Install Speed
+* **Install speed:** This is especially important if your package is used by CLI tools that can be loaded with [npx](https://docs.npmjs.com/cli/v8/commands/npx).
+
+### Unideal Environments
+* **Unideal environments:** Your package may be downloaded with slow internet, on slow devices, with little storage. It may even be downloaded within the browser via WebContainers.
+
+### Security
+* **Security:** Keeping dependencies to a minimum will reduce points of failure: unexpected breaking changes, malicious code, and dependency bloat.
+
+
\ No newline at end of file
diff --git a/docs/community-projects/stylelint-playground.md b/docs/community-projects/stylelint-playground.md
new file mode 100644
index 0000000..af8513f
--- /dev/null
+++ b/docs/community-projects/stylelint-playground.md
@@ -0,0 +1,23 @@
+---
+title: &title Stylelint Playgound
+description: &description A live playground where you can experiment with styleling rulesets using various packages.
+outline: [2, 3]
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-community_inspirations.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+
+
+
+
+With Stylelint playground you can experiment with rulesets defined in different npm packages by specifying them in package.json!
+
+They are actually being installed – just as they would in your project
+
+
diff --git a/docs/community-projects/vslite.md b/docs/community-projects/vslite.md
new file mode 100644
index 0000000..f963c20
--- /dev/null
+++ b/docs/community-projects/vslite.md
@@ -0,0 +1,22 @@
+---
+title: &title VSLite
+description: &description A lighweight IDE-like experience with a fresh Node.js environment for you to play with.
+outline: [2, 3]
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-community_inspirations.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+
+
+
+A lighweight IDE-like experience with a fresh Node.js environment for you to play with.
+
+Use terminal and write code using autocomplete-enabled editor:
+
+
diff --git a/docs/contact.md b/docs/contact.md
index 23ff812..3b0d689 100644
--- a/docs/contact.md
+++ b/docs/contact.md
@@ -1,14 +1,18 @@
---
title: &title Contact
-description: &description Looking to use the WebContainer API for more expansive use cases? Get in touch by filling out the form.
+description: &description Contact the WebContainer API team
head:
- ['meta', {property: 'og:title', content: *title}]
- ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/contact.png'}]
- ['meta', {name: 'twitter:title', content: *title}]
- ['meta', {name: 'twitter:description', content: *description}]
---
-# Contact
+# Contact Us
-Looking to use the WebContainer API for more expansive use cases?
+For general inquiries you can reach out to us on X [@StackBlitz](https://x.com/stackblitz) or email [hello@stackblitz.com](mailto:hello@stackblitz.com).
-Get in touch by filling out [this form](https://docs.google.com/forms/d/e/1FAIpQLSertiZLl-za0ZHxsWbd2IrISVft2OpPglykEHpEllPSfnZIUg/viewform)!
+For inquiries related to free open source usage of WebContainer API [please fill out this form](https://forms.default.com/360757) and we will reach out!
+
+:::tip Want to discuss your commercial use case?
+ [Reach out here to book a meeting with our WebContainer API team!](https://forms.default.com/360757)
+:::
\ No newline at end of file
diff --git a/docs/enterprise.md b/docs/enterprise.md
index 0f57ec0..3de7741 100644
--- a/docs/enterprise.md
+++ b/docs/enterprise.md
@@ -1,5 +1,5 @@
---
-title: &title Enterprise
+title: &title Commercial Usage
description: &description Supercharge your production Node.js apps with a zero-footprint backend that eliminates the need for servers, boots in milliseconds, and provides 0ms latency backend connectivity. With WebContainer API you can create experiences that were previously impossible for your customers, employees and partners.
head:
- ['meta', {property: 'og:title', content: *title}]
@@ -7,18 +7,28 @@ head:
- ['meta', {name: 'twitter:title', content: *title}]
- ['meta', {name: 'twitter:description', content: *description}]
---
-# Enterprise
+# Commercial Usage
+The WebContainer API is powering a new class of in-browser experiences from interactive tutorials, to code editors, and advanced AI applications.
-Supercharge your production Node.js apps with a zero-footprint backend that eliminates the need for servers, boots in milliseconds, and provides 0ms latency backend connectivity. With WebContainer API you can create experiences that were previously impossible. If you're exploring the API for usage in a for-profit setting, you're in the right place!
+Our secure and scalable API is designed to be integrated into your core application and scale effortlessly to millions of users thanks to our patented in-browser compute model.
-[Reach out and start a conversation about your needs today!](https://docs.google.com/forms/d/e/1FAIpQLSertiZLl-za0ZHxsWbd2IrISVft2OpPglykEHpEllPSfnZIUg/viewform)
+If you're considering the API for commercial, for-profit use, you're in the right place.
-## Benefits of a WebContainer API License
+:::tip Want to discuss your commercial use case?
+ [Reach out here to book a meeting with our WebContainer API team!](https://forms.default.com/360757)
+:::
-WebContainers rely on hosted proxies and server-side acceleration to enable truly instant development environments. By obtaining a WebContainer API license, your business can gain access to higher API rate limits, uptime reliability, and a range of benefits designed to help you maximize the potential of the WebContainer API in your organization. This includes direct access to the development team to help you optimize performance and navigate any roadblocks during implementation, priority bug fixes, and the ability to influence the API's roadmap, ensuring that it continues to meet the evolving needs of your business. Licenses also help support the continued hosting & development of the WebContainer API for both commercial and open source use cases.
+## Who needs a commercial WebContainer API license?
+Licensing is required for *production* usage of the API in a commercial, for-profit setting. (Prototypes or POCs do not require a commercial license.) If you're using the API to meet the needs of your customers, prospective customers, and/or employees, you need a license to ensure compliance with our [Terms of Service](https://stackblitz.com/terms-of-service). Usage of the API in violation of these terms may result in your access being revoked.
+
+## WebContainer API for Enterprise
+For the most security conscious organizations in the world, the WebContainer API Enterprise offering provides the features you need to meet the requirements of your security team:
+- Self hosted, on-premises, and VPC installation options behind the firewall
+- Use your private packages with support for private NPM registries
+- Enterprise SSO - Integrate with any SAML2-based authentication provider
+- Priority implementation & uptime support from our team
-Licensing is required for *production* usage of the API in a for-profit setting (feel free to prototype as much as you like without a license). If you're using the API to meet the needs of your customers, prospective customers, and/or employees you need a license to ensure continued access to the API as you scale.
Ready to supercharge your production Node.js apps? Contact us to see if your use case is a good fit and learn more about our pricing and support options.
-[Start a conversation!](https://docs.google.com/forms/d/e/1FAIpQLSertiZLl-za0ZHxsWbd2IrISVft2OpPglykEHpEllPSfnZIUg/viewform)
+[Start a conversation!](https://forms.default.com/360757)
\ No newline at end of file
diff --git a/docs/guides/ai-agents.md b/docs/guides/ai-agents.md
new file mode 100644
index 0000000..43c8f70
--- /dev/null
+++ b/docs/guides/ai-agents.md
@@ -0,0 +1,83 @@
+---
+title: &title Runtime Test Cases For AI Agents
+description: &description A suite of WebContainer test cases you can independently run on any runtime.
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-runtime_test_cases_for_ai_agents.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+# Runtime Test Cases For AI Agents
+
+To help developers validate whether WebContainer is right for their use case, we've compiled a suite of test cases that you can independently run on any runtime of your choosing (serverless, VMs, WebContainers, etc). These tests represent the most common patterns, libraries, tools, commands and environments that developers and toolchains rely on in the Node.js ecosystem, and thus serve as a good baseline for what capabilities LLM generated code would require.
+
+## Evaluating in-browser versus server runtimes
+
+When building AI agents you often need to execute arbitrary code. The most ideal place to do this tends to be inside the user's browser tab, as it is secure, long lived, scales infinitely, is cost effective, and boots instantly which provides an extremely fast user experience.
+
+While creating a simple in-browser proof-of-concept is straightforward, compatibility is usually the main issue with in-browser runtimes, and this is especially the case for AI agents where you need to execute the arbitrary code LLMs produce.
+
+Inversely, using servers (whether VMs or serverless solutions) often provide compatibility guarantees but at the expense of being short lived, expensive to scale, difficult to secure, and suffering from increased latency and cold starts.
+
+WebContainers is the first technology that has merged the best of both these worlds by bringing the entire Node.js runtime, ecosystem and tooling into the browser with excellent compatibility — no servers required. To validate this, we encourage developers to run real world test cases like the ones below both in WebContainer as well as any other runtime they are evaluating.
+
+
+## Test Cases
+The following test cases cover a broad spectrum of essential tools and frameworks in web development, ensuring AI agents are versatile, efficient, and capable of handling *real-world* coding tasks. These tools, frameworks, and runtime features are driven by real world data from the usage of over 3 million developers on StackBlitz.com every month and npm trends.
+
+**To run these test cases**: First, download the files from the StackBlitz example and have the environment arbitrarily install the npm packages, execute the dev or start command, when applicable check the server is booted properly, and validate the results are as expected.
+
+### NodeJS
+*Multiple processes, Async promises, FS Operations, Built-ins, Http Server, Streams, Child processes, Inter, process, communication, timers, Event Emitter*
+
+[View test cases](https://stackblitz.com/edit/stackblitz-starters-9ozakx)
+
+NodeJS is crucial because it evaluates the agent's ability to handle concurrency, manage child processes, and ensure performance efficiency. NodeJS's event-driven architecture makes it ideal for I/O-heavy tasks, and by leveraging multiple processes, the agent's proficiency in creating robust, performant applications is tested.
+
+### Package managers
+*NPM, Yarn, PNPM*
+
+[View test cases](https://stackblitz.com/edit/node-yahmwv?file=package.json)
+
+Handling package managers ensures the ability to manage dependencies, resolve version conflicts, and execute scripts. It also demonstrates adaptability to different package management systems and optimizes for faster, more efficient builds.
+
+### Command Line (CLI)
+[View test case](https://stackblitz.com/edit/node-xrxygh?file=.stackblitzrc)
+
+CLI operations assess the capability to interact with the system shell, execute commands, and handle various command-line tools. It also tests the ability to parse command-line arguments and provide meaningful outputs or perform actions based on those commands.
+
+### Vite
+[NPM trend](https://npmtrends.com/vite) - [View test case](https://vite.new)
+
+Using Vite evaluates the ability to configure and optimize modern development environments. It also assesses proficiency in handling hot module replacement, faster builds, and leveraging Vite's advanced features to enhance developer productivity.
+
+### Next.js
+[NPM trend](https://npmtrends.com/next) - [View test case](https://stackblitz.com/edit/nextjs-lsmwnd?file=README.md)
+
+NextJS assesses the capability to manage both client-side and server-side code, handle complex routing, and optimize performance for SEO. It also tests the ability to integrate with various APIs and manage state in a universal JavaScript application.
+
+### shadcn-ui
+[NPM trend](https://npmtrends.com/shadcn-ui) - [View test case](https://stackblitz.com/edit/vitejs-vite-7g7gcc)
+
+Using Shadcn ensures effective integration and utilization of CLI-driven component architectures. It also assesses the ability to customize and extend the library to meet specific project requirements.
+
+### React Router
+[NPM trend](https://npmtrends.com/react-router) - [View test case](https://stackblitz.com/github/remix-run/react-router/tree/dev/examples/basic)
+
+React Router evaluates the ability to manage complex navigation structures, handle dynamic routing, and ensure seamless transitions between different parts of an application. It also tests proficiency in managing route parameters, query strings, and nested routes.
+
+### Nuxt
+[NPM trend](https://npmtrends.com/nuxt) - [View test case](https://stackblitz.com/github/nuxt/starter/tree/v3)
+
+NuxtJS assesses the ability to handle server-side rendering, auto-imports, file system conventions, and zero config TypeScript support. It also tests the capability to work with Nuxt's automation with conventions methodology.
+
+### LibSQL
+[NPM trend](https://npmtrends.com/@libsql/client) - [View test case](https://stackblitz.com/edit/node-ox2oqu)
+
+Using LibSQL evaluates the ability to perform database operations such as querying, updating, and managing transactions. It also tests proficiency in handling database connections, optimizing queries, and ensuring data integrity and security.
+
+### Drizzle ORM
+[NPM trend](https://npmtrends.com/drizzle-orm) - [View test case](https://stackblitz.com/edit/github-9wp31h-ghh5jl?file=readme.md)
+
+Drizzle ORM assesses the ability to map database tables to objects, handle complex relationships, and perform CRUD operations efficiently. It also tests the ability to optimize database access and integrate with other parts of the application seamlessly.
diff --git a/docs/guides/api-support.md b/docs/guides/api-support.md
new file mode 100644
index 0000000..90d25e6
--- /dev/null
+++ b/docs/guides/api-support.md
@@ -0,0 +1,21 @@
+---
+title: &title API Versioning and Support
+description: &description The WebContainer API has a deprecation policy.
+head:
+ - ['meta', {property: 'og:title', content: *title}]
+ - ['meta', {property: 'og:image', content: 'https://webcontainers.io/img/og/guide-api_support.png'}]
+ - ['meta', {name: 'twitter:title', content: *title}]
+ - ['meta', {name: 'twitter:description', content: *description}]
+---
+
+# API Versioning and Support
+
+_Last Updated: January 2024_
+
+**TL;DR**: if there is ever a major change in the underlying runtime, applications _might_ need to upgrade their version of `@webcontainer/api`.
+
+The WebContainer API is comprised to two different components. One is the "client library" at `@webcontainer/api`, an NPM package that these docs discuss in detail. However, there is a second, implicit component that is invisible to consumers of the former: the actual implementation of the runtime, hosted on [StackBlitz](https://stackblitz.com).
+
+A good way to think about this split is to consider the difference between a REST API and the client library used to access it. That is, the difference between the [GitHub API](https://docs.github.com/en/rest) and [Octokit](https://github.com/octokit), between [AWS](https://aws.amazon.com/) and the [AWS SDK](https://aws.amazon.com/sdk-for-javascript/), etc. The versioning of these client libraries is generally straightforward, as they tend to use semantic versioning. The versioning of the underlying REST API or service is however _decoupled_ from the library: it is instead a matter of support policies.
+
+The `@webcontainer/api` library does, of course, follow semantic versioning. On the other hand, the underlying "engine" API is not explicitly exposed. **We currently do not have any plans for a future version**: should that happen, it would mean that only certain versions of the client library would target the newer runtime. Moreover, we do not have any plans to _retire_ the existing version: that would mean that older versions of the client library would cease to work. If we ever consider doing that, we will have an ample deprecation phase.
diff --git a/docs/guides/introduction.md b/docs/guides/introduction.md
index eb73632..cf8fa37 100644
--- a/docs/guides/introduction.md
+++ b/docs/guides/introduction.md
@@ -11,11 +11,12 @@ head:
**WebContainers are a browser-based runtime for executing Node.js applications and operating system commands, entirely inside your browser tab.** Apps that previously required cloud VMs to execute user code, in WebContainers can run entirely client-side with [a number of benefits over the legacy cloud VM](#webcontainers-versus-cloud-vm-approach).
-**WebContainer API is perfect for interactive coding experiences.** Among its most common use cases are production-grade IDEs, programming tutorials, next-generation documentation, AI applications, or employee onboarding platforms. WebContainers have been [battle-tested by millions of users](#who-s-using-webcontainers) of StackBlitz classic editor, Codeflow, the official SvelteKit tutorial, and Cloudflare Wrangler workers, among others.
+**WebContainer API is perfect for interactive coding experiences.** Among its most common use cases are AI applications, adding in-browser code execution to your existing product, programming tutorials, next-generation documentation, browser based IDEs, and employee onboarding platforms. WebContainers have been [battle-tested by millions of users](#who-s-using-webcontainers) of StackBlitz, and inside the interactive learning environments built by the [Svelte](https://learn.svelte.dev/tutorial/welcome-to-svelte), [Angular](https://angular.dev/tutorials/first-app), and [Nuxt](https://learn-dev.nuxt.com/) teams among others.
-Ready to try it? Check out this WebContainer API starter in an editor running on... WebContainers as well!
-[](https://webcontainer.new)
+:::tip Ready to try it out for yourself?
+Check out this [WebContainer API starter](https://webcontainer.new/) or see [our Quickstart guide](./quickstart) to get familiar with what's possible!
+:::
## Key features
@@ -34,13 +35,13 @@ WebContainers enables you to build applications that previously required running
- **Scales to millions.** Leverages modern CDN caching and client-side compute.
- **No risk of bad actors.** Say goodbyte to bitcoin miners, malware, and phishing sites.
-To explore the API, check out the WebContainer starter:
+If you want to skip [the Quickstart guide](./quickstart) and jump stright into exploring the API, you can open the WebContainer starter project in StackBlitz here:
[](https://webcontainer.new)
## Who's using WebContainers?
-Initially [announced at Google I/O](https://blog.stackblitz.com/posts/introducing-webcontainers/), **WebContainers are developed by [StackBlitz](https://stackblitz.com) and have been battle-tested by millions of developers every month in StackBlitz [classic editor](https://node.new) and in the new [Codeflow IDE](https://stackblitz.com/codeflow)**. Externally, WebContainers also power a number of instant coding experiences such as Cloudflare Wrangler's [workers.new](https://blog.cloudflare.com/cloudflare-stackblitz-partnership/#powering-a-better-developer-experience-and-documentation) and the Svelte team's [interactive fullstack tutorial](http://learn.svelte.dev/) for SvelteKit.
+Initially [announced at Google I/O](https://blog.stackblitz.com/posts/introducing-webcontainers/), **WebContainers are developed by [StackBlitz](https://stackblitz.com) and have been battle-tested by millions of developers every month as they power the StackBlitz editor**. Externally, WebContainers also power a number of popular interactive learning environments including those built by the [Svelte](https://learn.svelte.dev/tutorial/welcome-to-svelte), [Angular](https://angular.dev/tutorials/first-app), and [Nuxt](https://learn-dev.nuxt.com/) teams.
To see more examples of how WebContainers have been used so far, check out our [Community Projects page](/community-projects/all-projects).
diff --git a/docs/guides/quickstart.md b/docs/guides/quickstart.md
index b3a3164..1845fba 100644
--- a/docs/guides/quickstart.md
+++ b/docs/guides/quickstart.md
@@ -15,10 +15,10 @@ This page provides the bare-minimum overview on how to start building with WebCo
We have prepared a [step-by-step walkthrough](../tutorial/1-build-your-first-webcontainer-app) for you!
:::
-**The WebContainer API starter is the fastest way to explore the API**. Open it in StackBlitz editor:
+**The WebContainer API starter is the fastest way to explore the API**. Open it in StackBlitz editor:
[](https://webcontainer.new)
-or in Codeflow IDE, our full-fledged web environment:
+or in Codeflow IDE, our full-fledged web environment:
[](https:///pr.new/github.com/stackblitz/webcontainer-api-starter)
If you prefer to develop locally, follow the steps below.
@@ -100,7 +100,7 @@ async function startDevServer() {
## 4. Preview
-After you have started the dev server, get the URL from `port-ready` event and mount it in an iframe:
+After you have started the dev server, get the URL from `server-ready` event and mount it in an iframe:
```js
webcontainerInstance.on('server-ready', (port, url) => (iframeEl.src = url));
diff --git a/docs/guides/running-processes.md b/docs/guides/running-processes.md
index 6cb6efa..e773fcf 100644
--- a/docs/guides/running-processes.md
+++ b/docs/guides/running-processes.md
@@ -52,7 +52,7 @@ Calling `spawn` returns a `WebContainerProcess`. Every process has an `output` p
The output property is a `ReadableStream`. That’s because it is, in fact, a stream that can emit strings numerous times, just like the actual `stdout` or `stderr` from a process in Node.js. The advantage of streams is that they allow composition, meaning we can pipe data from one stream into another stream, for example `source.pipeTo(destination)`. Furthermore, streams can be transferred via `postMessage` from one context to a different context, for example a web worker. A `ReadableStream` also keeps a buffer of the data which is only flushed once you start reading.
-If you want to read data from output you can pipe it into a `WriteableStream` just like in the example above.
+If you want to read data from output you can pipe it into a `WriteableStream` just like in the example below.
:::
@@ -61,7 +61,7 @@ An example of a usage could be the following:
```js
const installProcess = await webcontainerInstance.spawn('npm', ['install']);
-
+
installProcess.output.pipeTo(new WritableStream({
write(data) {
console.log(data);
diff --git a/docs/guides/working-with-the-file-system.md b/docs/guides/working-with-the-file-system.md
index 1572dd7..67a3654 100644
--- a/docs/guides/working-with-the-file-system.md
+++ b/docs/guides/working-with-the-file-system.md
@@ -258,6 +258,47 @@ await webcontainerInstance.mount(files, { mountPoint: 'my-mount-point' });
:::
+## Generating snapshots
+
+The `mount()` method not only accepts the tree-like format we described above, but a binary snapshot format that can be automatically generated, using the
+[`@webcontainer/snapshot`](https://www.npmjs.com/package/@webcontainer/snapshot) package.
+Suppose we want our WebContainer API application to mount a source code folder that is present on our server. In that case, we could do the following:
+
+```typescript
+import { snapshot } from '@webcontainer/snapshot';
+
+// snapshot is a `Buffer`
+const folderSnapshot = await snapshot(SOURCE_CODE_FOLDER);
+
+// for an express-based application
+app.get('/snapshot', (req, res) => {
+ res
+ .setHeader('content-type', 'application/octet-stream')
+ .send(snapshot);
+});
+
+// for a SvelteKit-like application
+export function getSnapshot(req: Request) {
+ return new Response(sourceSnapshot, {
+ headers: {
+ 'content-type': 'application/octet-stream',
+ },
+ });
+}
+```
+
+Now, on the client side of our application we can fetch that snapshot and mount it:
+```typescript
+import { WebContainer } from '@webcontainer/api';
+
+const webcontainer = await WebContainer.boot();
+
+const snapshotResponse = await fetch('/snapshot');
+const snapshot = await snapshotResponse.arrayBuffer();
+
+await webcontainer.mount(snapshot);
+```
+
## File System operations (`fs`)
WebContainers expose an `fs` property on the WebContainer instance (`webcontainerInstance`). Currently, `fs` supports a few methods:
diff --git a/docs/public/img/ai/wc_api-ai.png b/docs/public/img/ai/wc_api-ai.png
new file mode 100644
index 0000000..0fd95d0
Binary files /dev/null and b/docs/public/img/ai/wc_api-ai.png differ
diff --git a/docs/public/img/community/angular-tutorial.png b/docs/public/img/community/angular-tutorial.png
new file mode 100644
index 0000000..b5527ec
Binary files /dev/null and b/docs/public/img/community/angular-tutorial.png differ
diff --git a/docs/public/img/community/builder-io-playground.png b/docs/public/img/community/builder-io-playground.png
new file mode 100644
index 0000000..144a4b6
Binary files /dev/null and b/docs/public/img/community/builder-io-playground.png differ
diff --git a/docs/public/img/community/clack.png b/docs/public/img/community/clack.png
new file mode 100644
index 0000000..c3cce9c
Binary files /dev/null and b/docs/public/img/community/clack.png differ
diff --git a/docs/public/img/community/otto_engineer.png b/docs/public/img/community/otto_engineer.png
new file mode 100644
index 0000000..3126e25
Binary files /dev/null and b/docs/public/img/community/otto_engineer.png differ
diff --git a/docs/public/img/community/pkg-size.png b/docs/public/img/community/pkg-size.png
new file mode 100644
index 0000000..4e85576
Binary files /dev/null and b/docs/public/img/community/pkg-size.png differ
diff --git a/docs/public/img/community/stylelint-playground.png b/docs/public/img/community/stylelint-playground.png
new file mode 100644
index 0000000..d9d2b6c
Binary files /dev/null and b/docs/public/img/community/stylelint-playground.png differ
diff --git a/docs/public/img/community/vslite.png b/docs/public/img/community/vslite.png
new file mode 100644
index 0000000..4a178bf
Binary files /dev/null and b/docs/public/img/community/vslite.png differ
diff --git a/docs/public/img/og/ai.png b/docs/public/img/og/ai.png
new file mode 100644
index 0000000..55166ed
Binary files /dev/null and b/docs/public/img/og/ai.png differ
diff --git a/docs/public/img/og/guide-api_support.png b/docs/public/img/og/guide-api_support.png
new file mode 100644
index 0000000..8e34118
Binary files /dev/null and b/docs/public/img/og/guide-api_support.png differ
diff --git a/docs/public/img/og/guide-runtime_test_cases_for_ai_agents.png b/docs/public/img/og/guide-runtime_test_cases_for_ai_agents.png
new file mode 100644
index 0000000..8df3604
Binary files /dev/null and b/docs/public/img/og/guide-runtime_test_cases_for_ai_agents.png differ
diff --git a/docs/tutorial/6-connect-a-terminal.md b/docs/tutorial/6-connect-a-terminal.md
index 2bef5c1..6b8b8e4 100644
--- a/docs/tutorial/6-connect-a-terminal.md
+++ b/docs/tutorial/6-connect-a-terminal.md
@@ -16,7 +16,7 @@ Your Express app is up and running and the preview window updates automatically
The terminal frontend component that we will use is [`Xterm.js`](https://xtermjs.org). It's the same terminal that is used by Visual Studio Code and many other web-based IDEs. To install it, run the following command in your development terminal:
```bash
-npm install xterm
+npm install @xterm/xterm
```
## 2. Build terminal scaffolding
@@ -62,7 +62,7 @@ First of all, import `Xterm.js`. To do so, add an import statement at the top of
:::code-group
```js [main.js]
-import { Terminal } from 'xterm'
+import { Terminal } from '@xterm/xterm'
```
:::
@@ -105,7 +105,7 @@ The terminal looks a bit plain now. Fortunately, `Xterm.js` ships its own CSS st
:::code-group
```js [main.js]
-import 'xterm/css/xterm.css';
+import '@xterm/xterm/css/xterm.css';
```
:::
diff --git a/docs/tutorial/7-add-interactivity.md b/docs/tutorial/7-add-interactivity.md
index d5b0b93..f5b36cd 100644
--- a/docs/tutorial/7-add-interactivity.md
+++ b/docs/tutorial/7-add-interactivity.md
@@ -144,7 +144,7 @@ With this change, you hooked up your terminal to the shell running in the WebCon

-## 4. Add `xterm-addon-fit`
+## 4. Add `@xterm/addon-fit`
You might've noticed that resizing the window doesn't redraw the terminal output. If you make the window very narrow, lines that are too long don't wrap to the next line, which is not a good UX practice. For example, look at the highlightened line:
@@ -152,19 +152,19 @@ You might've noticed that resizing the window doesn't redraw the terminal output
To fix this, you'll need to make the WebContainer process aware of the size of the terminal.
-First of all, let's make sure that the terminal itself gets adjusted properly when resizing the window. To do that, you can use the [`xterm-addon-fit`](http://xtermjs.org/docs/api/addons/fit/) plugin for `Xterm.js` which adjusts the terminal columns and rows depending on the element it's rendered in.
+First of all, let's make sure that the terminal itself gets adjusted properly when resizing the window. To do that, you can use the [`@xterm/addon-fit`](http://xtermjs.org/docs/api/addons/fit/) plugin for `Xterm.js` which adjusts the terminal columns and rows depending on the element it's rendered in.
First, install the plugin:
```bash
-npm install xterm-addon-fit
+npm install @xterm/addon-fit
```
And import it at the top of your `main.js` file.
:::code-group
```js [main.js]
-import { FitAddon } from 'xterm-addon-fit';
+import { FitAddon } from '@xterm/addon-fit';
```
:::