Controlling embeds with the SDK’s VM interface
INFO
These methods only apply to projects embedded on a page.
All of the embed methods of the StackBlitz JS SDK automatically connect to the embedded StackBlitz VM, giving you programmatic access to the embedded project.
Use the VM to:
- control the UI of an embedded StackBlitz project;
- change the currently open file(s);
- read and write files from the project’s virtual filesystem.
Getting access to the VM
With embed methods
The embedProject
, embedProjectId
, and embedGithubProject
methods of the SDK return a Promise resolving to an instance of the SDK’s VM
class. We recommend using await
in an async
function to keep track of the VM instance. For example:
import sdk from '@stackblitz/sdk';
async function start() {
// Embeds a project and keeps track of the VM
const vm = await sdk.embedProjectId('embed', 'react-ts');
// Performs an action with VM
const deps = await vm.getDependencies();
await vm.applyFsDiff({
create: {
'hello.txt': 'Hello, this is a new file!',
'deps.txt': JSON.stringify(deps, null, 2),
},
destroy: [],
});
}
start();
With connect(iframe)
The SDK’s connect
method can be used to retrieve the VM
instance for an existing StackBlitz iframe.
Argument | Required | Type | Description |
---|---|---|---|
iframe | Yes | HTMLIframeElement | An iframe embedding a StackBlitz project. |
Example:
import sdk from '@stackblitz/sdk';
const EMBED_ID = 'embed';
// Embeds iframe
sdk.embedProjectId(EMBED_ID, 'react-ts');
// Retrieves and uses the VM when clicking a button
document.getElementById('test-button').addEventListener('click', async () => {
const iframe = document.getElementById(EMBED_ID);
const vm = await sdk.connect(iframe);
const deps = await vm.getDependencies();
console.log(deps);
});
VM properties and methods
applyFsDiff(diff)
Updates project files. Returns a promise resolving to null
.
Argument | Required | Type | Description |
---|---|---|---|
diff | Yes | Object | Specifies files to create or delete |
diff.create | Yes | Object | Object with file paths as keys and contents as values |
diff.destroy | Yes | Array | File paths of the files to delete |
INFO
When modifying existing files, the new content of the modified files must be provided in full.
Example:
await vm.applyFsDiff({
create: {
'index.js': `console.log('Hello World!')`,
'package.json': `{ "scripts": { "start": "node index.js" } }`,
},
destroy: ['test.js', 'error.log'],
});
getDependencies()
Gets the project’s defined dependencies. Returns a promise resolving to a ProjectDependencies object.
In EngineBlock projects, it returns the dependencies as resolved by the built-in package manager, with exact versions as values. For example: { 'react': '18.2.0' }
.
Since 1.7.0: in project running on WebContainers, it reads the contents of the top-level package.json
file and returns an object merging dependencies
and devDependencies
, with the original version specifiers as values. For example, { 'react': '^18.0.0' }
.
Example:
const deps = await vm.getDependencies();
if (typeof deps['vue'] === 'string') {
console.log('Looks like a Vue.js project');
}
getFsSnapshot()
Gets a snapshot of the project files and their content. Returns a promise resolving to a ProjectFiles object.
Example:
const files = await vm.getFsSnapshot();
console.log(files); // { 'index.js': '…', 'package.json': '…', … }
editor.openFile(path)
Opens one or several files in tabs and/or split panes. Returns a promise resolving to null
.
Argument | Required | Type | Description |
---|---|---|---|
path | Yes | OpenFileOption (String or array of strings) | Path(s) of file(s) to open |
Example:
// opens a single file
await vm.editor.openFile('src/App.css');
// opens two editor panes
await vm.editor.openFile(['README.md', 'index.js']);
editor.setCurrentFile(path)
Since 1.7.0. Experimental: exact behavior may change.
Sets a project file as the currently selected file. Returns a promise resolving to null
.
Argument | Required | Type | Description |
---|---|---|---|
path | Yes | String | Path of the file to set as current |
- This may update the highlighted file in the file explorer, and the currently open and/or focused editor tab.
- If the provided path does not match a currently open tab, a new editor tab will not open. See
vm.editor.openFile
to open files.
Example:
await vm.editor.setCurrentFile('src/App.css');
editor.setTheme(theme)
Since 1.7.0.
Changes the editor’s color theme. Returns a promise resolving to null
.
Argument | Required | Type | Description |
---|---|---|---|
theme | Yes | UiThemeOption (String) | The color theme name. |
await vm.editor.setTheme('light');
editor.setView(view)
Since 1.7.0.
Changes the display mode of the project. Returns a promise resolving to null
.
Argument | Required | Type | Description |
---|---|---|---|
view | Yes | UiViewOption (String) | The display mode name. |
await vm.editor.setView('preview');
editor.showSidebar(visible)
Since 1.7.0.
Changes the display mode of the sidebar. Returns a promise resolving to null
.
Argument | Required | Type | Description |
---|---|---|---|
visible | No | Boolean | Use true (default) to show the sidebar, false to hide. |
await vm.editor.showSidebar(true);
preview.origin
A string with the origin (protocol and domain) of the preview iframe. Every project created with the embedProject
method gets a unique preview URL.
Because it is unknown ahead of time if the project will run a web server (and if so, on which port), vm.preview.origin
will always be null
in projects running on WebContainers. You can use vm.preview.getUrl
instead.
Example:
if (vm.preview.origin) {
console.log('Preview is running at ' + vm.preview.origin);
}
preview.getUrl()
Since 1.7.0. Experimental: exact behavior may change.
Gets the current preview URL. Returns a promise resolving to a string or to null
.
The preview URL may not reflect the exact path of the current page if the user or page code has triggered a navigation within the preview iframe.
In WebContainers projects, the preview URL will be null
initially, and until the project starts a web server.
Example:
const url = await vm.preview.getUrl();
if (url != null && url.startsWith('/about')) {
console.log('Looks like the About page!');
}
preview.setUrl(path)
Since 1.7.0. Experimental: exact behavior may change.
Changes the path of the preview URL. Returns a promise resolving to null
.
Argument | Required | Type | Description |
---|---|---|---|
path | Yes | String | A URL path starting with / . |
The provided path must start with /
and cannot change the origin of the preview URL.
In WebContainers projects, calls to vm.preview.setUrl
will be ignored if there is no web server running currently.
Example:
// Navigates to the About page
await vm.preview.setUrl('/about');