# Develop and preview a widget set Use dev mode to preview unpublished widget code in Foundry while you develop. Dev mode replaces the published assets for your user account only, so other users continue to see the published version. This page explains how to start a development server, connect it to your widget set, and confirm that Foundry is displaying your changes. ## Before you begin You need a widget set and its source code. If you have not created one, follow [Create a widget set](../create/index.md) first. Choose where you want to run the development server: | Development environment | Setup | Command | | --- | --- | --- | | Local machine | Clone the widget set's code repository and create a user-generated token. | `npm run dev` | | VS Code Workspaces | Open the widget set's code repository in a workspace. Authentication is managed by Foundry. | `npm run dev:remote` | :::callout{theme="warning" title="Preview a new widget in Workshop"} You can preview an unpublished widget in the custom widgets playground and in Code Workspaces. In Workshop however, you still need to [publish it](../publish/index.md) once before being able to select it. After the first publication, dev mode can be used in Workshop similar to the custom widgets playground and Code Workspaces. ::: ## Start a development session ### Develop on your local machine 1. Clone the widget set's code repository. For a Foundry Code Repository, follow the **Work locally** instructions in VS Code Workspaces or the Code Repositories application. 2. Create a [user-generated token](../../platform-security-third-party/user-generated-tokens/index.md). 3. In a terminal, set the `FOUNDRY_TOKEN` environment variable. Replace `` with your token. ```bash export FOUNDRY_TOKEN= ``` 4. From the project directory, install the project dependencies. ```bash npm install ``` 5. Start the local development server. ```bash npm run dev ``` 6. Keep the development server running and open the setup link printed in the terminal. The link connects the server to your widget set and opens the widget set overview page. 7. Select a widget to open it in the custom widgets playground. 8. Edit and save a source file. The playground updates with your development version. ![The npm run dev command and dev mode setup link in the terminal.](../../../assets/2f440ebd7c008fa174a852ecbe80c84885a6b4e43102a3593277700b74ab5948.webp) If the widget does not update, first confirm that the terminal still shows a running development server and that you opened the most recent setup link. ### Develop in a VS Code workspace 1. Open the widget set's code repository in a VS Code workspace. 2. Wait for the workspace to start. The development server starts automatically for widget set templates. 3. If the server is not running, start it from the project directory. ```bash npm run dev:remote ``` 4. In the VS Code preview panel, select the widget that you want to preview. 5. Edit and save a source file. The preview panel updates with your development version. ![A widget running from a development server in VS Code Workspaces.](../../../assets/75153d0f473800c9ef9ee6036d4a9f1d0649d96d04277be96e5da452a56c44aa.webp) The same workspace development server can provide overrides to the custom widgets playground and Workshop. You do not need to run a second server. ## Confirm that dev mode is active Dev mode controls show which version of a widget you are viewing: | State | Version displayed | What to do | | --- | --- | --- | | **Disabled** | Published version | Start a development session and enable dev mode to preview changes. | | **Enabled** | Development version | Continue editing. The control identifies the source as localhost or a VS Code workspace. | | **Enabled (inactive)** | Published version | Nothing, if you are not developing the widget you are viewing. Otherwise, confirm that the development server is running and contains the widget, and then reapply dev mode. | | **Paused** | Published version | Resume dev mode when you want to return to the development version. | ### Start dev mode When dev mode is disabled, the **Start dev mode** control is displayed. Start your development server before selecting the control so that dev mode can find the widget overrides. The Start dev mode control is displayed when dev mode is disabled. ### Understand an inactive session An inactive session means that your development server has no overrides for the widget you are viewing. This state does not always need to be resolved. For example, dev mode reports an inactive session when you open a widget from a different widget set to compare it, or when you view a Workshop application in which you are developing only some of the custom widgets. In these cases, the published version is the version you expect to see. If you do intend to develop the widget you are viewing, start the development server, confirm that it includes the widget, and then reapply dev mode. The dev mode menu reports that no widget overrides are configured for an inactive session. ### Resume or stop a paused session Select **Resume** to display the development version again. Select **Stop** to end the dev mode session and continue using the published version. The dev mode menu provides controls to resume or stop a paused session. ### Identify the development source An active local session identifies localhost as its source: Dev mode is enabled and using a development server on localhost. An active VS Code Workspaces session identifies the workspace as its source: Dev mode is enabled and using a development server in VS Code Workspaces. Dev mode is personal and temporary. It does not change what other users see, and it expires after 24 hours. ## Choose a preview environment After dev mode is active, use the environment that matches what you need to test: | Preview environment | Use it to | | --- | --- | | Custom widgets playground | Test one widget in different dimensions, change parameter values, and inspect emitted events and parameter updates. | | Workshop | Test the widget with its Workshop parameter bindings, events, surrounding components, and application layout. | | VS Code preview panel | Preview a widget without leaving your development workspace. | The playground displays controls for parameters and a message log for events: ![A widget in dev mode in the custom widgets playground.](../../../assets/261f1952ccb6601aedf2ba72c2e61dbd525fe5af35514c23a64a9532edc2349f.webp) Workshop displays the development version in the application where you use the widget: ![A widget in dev mode in Workshop.](../../../assets/63e772d8e7ec1f50cae46edd88747b6d65611c3adfd595bde256f7249e7cf917.webp) ## Preview different types of changes Dev mode handles source code and widget configuration changes differently: | Change | How to preview it | | --- | --- | | Component code or styles | Save the file. The widget updates automatically while the development server is running. | | Parameters or events in a widget configuration file | Save the file, and then reapply dev mode. For a local server, open the setup link from the terminal again. In VS Code Workspaces, refresh the preview panel. | ### Add or modify parameters and events Widget templates define parameters and events in a configuration file such as `main.config.ts`. The following example defines three parameters and two events: ```ts tab="main.config.ts" import { defineConfig } from "@osdk/widget.client"; export default defineConfig({ id: "", // The unique identifier of the widget within your project name: "", // A user friendly name for your widget description: "", // A user friendly description of your widget type: "workshop", parameters: { headerText: { displayName: "Widget title", type: "string", }, showWarning: { displayName: "Show warning callout", type: "boolean", }, todoItems: { displayName: "Todo items", type: "array", subType: "string", }, }, events: { updateHeader: { displayName: "Update header", parameterUpdateIds: ["headerText"], }, updateTodoItems: { displayName: "Update todo items", parameterUpdateIds: ["todoItems"], }, }, }); ``` Dev mode can preview parameter and event changes with `@osdk/widget.vite-plugin` version `3.34.0` or later. For supported types and examples of reading parameters and emitting events from a widget, see [Parameters and events](../parameters-and-events/index.md). ## Understand runtime limitations ### Browser storage The custom widgets runtime does not support browser APIs that persist data, including: * [Web Storage API ↗](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API) (`localStorage` and `sessionStorage`) * [IndexedDB API ↗](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) To share state between widgets, use parameters configured through the host application, such as Workshop variables. To persist state, use saved states for Workshop variables or write data to the Ontology. ### Web Workers API The custom widgets runtime supports dedicated web workers through the [Web Workers API ↗](https://developer.mozilla.org/en-US/docs/Web/API/Worker). You can use dedicated workers to run JavaScript tasks without blocking the browser's main thread. The runtime does not support [shared workers ↗](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker) or [service workers ↗](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). ### Widget state in Workshop By default, Workshop unmounts custom widgets when their containing layout is hidden. This discards state held in the widget's iframe. To preserve local state across navigation, configure [widget display optimization](../../workshop/widget-display-optimization/index.md) to keep the widget mounted. ### Network requests The custom widgets runtime uses a restrictive content security policy that you cannot configure. The runtime blocks external requests and does not support non-Ontology APIs. To access an external service, use a Foundry resource that wraps the request, such as a function or webhook. ## Theming You can use CSS media queries and JavaScript to detect the parent application's color scheme. For implementation details and examples, see [Dark theme support](../dark-theme/index.md). ## Troubleshooting For help with browser crashes, performance problems, or unexpected behavior while developing custom widgets, see [Troubleshooting](../troubleshooting/index.md).