# playground-elements **Repository Path**: mirrors_google/playground-elements ## Basic Information - **Project Name**: playground-elements - **Description**: Serverless coding environments for the web. - **Primary Language**: Unknown - **License**: BSD-3-Clause - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-10-22 - **Last Updated**: 2026-01-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

playground-elements


Serverless coding environments for the web.





OverviewGetting StartedProject filesModule resolutionTypeScriptHiding & FoldingCustom layoutsExtending the editorBundlingSandbox securityComponentsStylingSyntax highlightingContributingFAQ

## Overview Playground Elements are a set of components for creating interactive editable coding environments on the web, with live updating previews. You can use Playground Elements to: - Embed editable code examples in your documentation. - Build interactive tutorials and example galleries. - Build full-featured coding sandboxes (think Glitch or JSBin). #### 🤯 No backend required Unlike other coding environments, Playground never sends code to a backend server. Instead, Playground uses a [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) to create a virtual URL-space that runs 100% within the browser. If you can host static files, you can host a Playground. #### TypeScript support Playground automatically compiles `.ts` files using TypeScript, and automatically fetches typings for your imports in order to display errors. Compilation happens in a Web Worker on a separate thread, so your page stays responsive. #### 🧩 Web Components Playground uses Web Components, so it doesn't require a framework. But it will play nicely with any framework you're already using, like React, Vue, and Angular. #### 🍱 Mix-and-match for flexible layout Playground is broken up into small components like an editor, file picker, and preview. Mix-and-match components to create any layout you want, or just use `` for an easy out-of-the-box experience. #### 🎨 Themable Playground is fully themeable with CSS Custom Properties, down to the color of each kind of syntax-highlighted token. You can import themes from VSCode using the [configurator](https://google.github.io/playground-elements/), and it comes with a number of presets too. ---

Try the demo and configurator!

--- ## Getting Started ### Install Install from NPM: ```sh npm i playground-elements ``` ```html ``` ### Hello World Create a `` element in your HTML, and specify your project files inline: ```html ``` ### Serve Use a server like [@web/dev-server](https://modern-web.dev/docs/dev-server/overview/) to handle bare module import resolution automatically: ```sh npm i -D @web/dev-server npx web-dev-server --node-resolve --watch ``` Or, use a tool like [Rollup](https://rollupjs.org/guide/en/) to resolve bare module imports to paths at build time. If you need more help with building and serving, check out the [Modern Web Guides](https://modern-web.dev/guides/). ### Compatibility Playground is supported by all modern browsers. It requires support for custom elements, JS modules, service workers, and web workers.     **Supported:**   Supported Chrome     Supported Firefox     Supported Safari     Supported Edge **Unsupported:**   Unsupported Internet Explorer ## Project files There are 3 ways to specify the files of a playground project: ### Option 1: Inline scripts Add one or more `` tags within your source as `</script>`. ```html ``` ### Option 2: JSON configuration Set the `project-src` attribute or `projectSrc` property to a JSON file with format: | Property | Description | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `files` | An object mapping filenames to file data. | | `files.content` | Optional text content of the file. If omitted, a `fetch` is made to retrieve the file by filename, relative to the manifest URL. | | `files.contentType` | Optional MIME type of the file. If omitted, type is taken from either the `fetch` response `Content-Type` header, or inferred from the filename extension when `content` is set. | | `files.label` | Optional label for display in `playground-tab-bar`. If omitted, the filename is displayed. | | `files.hidden` | If `true`, the file won't be visible in `playground-tab-bar`. | | `files.selected` | If `true`, this file's tab will be selected when the project is loaded. Only one file should have this field set. | | `extends` | Optional URL to another JSON config file to extend from. Configs are deeply merged. URLs are interpreted relative to the URL of each extendee config. | | `cdnBaseUrl` | Optional URL for the underlying npm CDN base url. Confirmed tested are `htts://unpkg.com` and `https://cdn.jsdelivr.net/npm` | ```html ``` ```json { "files": { "index.html": {}, "typescript.ts": { "content": "console.log('hello');" }, "javascript.js": { "contentType": "text/javascript" }, "styles.css": { "label": "Style" } } } ``` ### Option 3: Config property In JavaScript, directly set the `config` property to an object. The format is identical to the JSON config file. ```js const ide = document.querySelector('playground-ide'); ide.config = { files: { 'index.html': {}, 'typescript.ts': { content: "console.log('hello');", }, }, }; ``` If both `project-src` and `config` are set, then the one set most recently has precedence. When either are set, inline scripts are ignored. ## Module resolution By default, bare module specifiers in JavaScript and TypeScript files are transformed to special `./node_modules/` URLs, and fetched behind-the-scenes from unpkg.com by default at the latest version. ```js // What you write: import {html} from 'lit'; // What playground serves: import {html} from './node_modules/lit@2.0.2/index.js'; // What playground fetches behind-the-scenes unless you set `cdnBaseUrl`: // https://unpkg.com/lit@latest ``` ### `package.json` To customize the version of a module you import, create a file called `package.json` in your project containing a [`dependencies`](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#dependencies) map. This works exactly like it does when using NPM locally. ```json { "dependencies": { "lit": "^2.0.2" } } ``` > TIP: Use the `hidden` [attribute](#option-1-inline-scripts) or > [property](#option-2-json-configuration) to hide the `package.json` file from > being displayed in the list of project files, if you don't want the end-user > to be able to see or modify it. ### Export conditions Playground supports Node-style [export conditions](https://nodejs.org/api/packages.html#packages_exports) when resolving modules in dependencies, and sets the following [conditions](https://nodejs.org/api/packages.html#packages_conditional_exports): `module`, `import`, `development`, and `browser`. ### Import maps For full control over module resolution, you can configure an _import map_. You may want to do this to change CDNs or point to a locally served copy of a module: ```js { "files": { ... }, "importMap": { "imports": { "lit": "https://cdn.skypack.dev/lit@^2.0.2", "lit/": "https://cdn.skypack.dev/lit@^2.0.2/" } } } ``` When using inline project files, you can specify your import map like so: ```html ... ``` If an import map is defined, but does not contain an entry for a bare module, then playground defaults to the `unpkg.com` URL unless `cdnBaseUrl` is set. ## TypeScript Playground automatically compiles `.ts`, `.tsx`, and `.jsx` files using [TypeScript](https://www.typescriptlang.org/). The following compiler settings are used: | Name | Value | | ------------------------------------------------------------------------------------------ | ---------- | | [`target`](https://www.typescriptlang.org/tsconfig#target) | `es2021` | | [`module`](https://www.typescriptlang.org/tsconfig#module) | `esnext` | | [`moduleResolution`](https://www.typescriptlang.org/tsconfig#moduleResolution) | `nodenext` | | [`experimentalDecorators`](https://www.typescriptlang.org/tsconfig#experimentalDecorators) | `true` | | [`allowJs`](https://www.typescriptlang.org/tsconfig#allowJs) | `true` | | [`jsx`](https://www.typescriptlang.org/tsconfig#jsx) | `react` | Note that when you import from another project module, the import statement should use the `.js` extension (the same as you would do when running `tsc` locally): ```ts import './my-other-module.js'; ``` You may also include any Definitely Typed (`@types`) packages for type checking during compilation by listing it as a dependency in the project's [`package.json` file](#packagejson). ## Hiding & folding If a region of code in a Playground project file is surrounded by `playground-hide` and `playground-hide-end` comments, then that region won't be visible or editable by the user, but it will still be compiled and served. Similarly, if a region is surrounded by `playground-fold` and `playground-fold-end` comments, then the region will be replaced with a `…` that expands to reveal the original editable code when clicked. Use these special regions to help users focus on a particular part of a file, by de-emphasizing boilerplate or unrelated code. #### JavaScript fold example Note that JavaScript `//` style comments are not supported. ```ts /* playground-fold */ import {html, LitElement} from 'lit'; /* playground-fold-end */ class MyElement extends LitElement { render() { return html`Hello !`; } } /* playground-fold */ customElements.define('my-element', MyElement); ``` Result: #### HTML hide example ```html Boring stuff World ``` Result: #### Disabling Hiding and folding is enabled by default, but can be disabled by setting the `pragmas` property to `"off"` (disabled with comments hidden) or `"off-visible"` (disabled with comments visible). The `pragmas` property is available on `ide`, `file-editor`, and `code-editor`. ## Custom layouts `` provides a complete out-of-the-box experience that's a good start for many use-cases, but you can mix-and-match the various Playground sub-components to make your custom layouts. For example, say we need a layout with an editor above, a preview below, and only one particular file from the project visible — like this: To do this, first import just the components you need. The main `playground-elements` import loads all Playground elements, but when making a custom layout it's a good idea to only load the sub-components you're actually using. This will make your JavaScript bundle smaller. ```html ``` Next create a ``, with some inline project files. We could also write our project files separately, and specify them in a JSON manifest. This project element manages the virtual file system, and coordinates with the Playground workers. We give it a unique `id`, which we'll use to connect up the editor and preview. ```html ``` Next create an editor and preview. Connect both to the project by setting the `property` attribute to the project element's `id`. We could also directly set the `project` _property_ to the project element, if we were using JavaScript. By setting the `filename` attribute on the editor, we've pinned it to one particular file. Since we didn't include a ``, there's no way for the user to see or switch to other files in the project. ```html
``` Finally, add a little style: ```html ``` ## Extending the editor Playground's code editor is built on [CodeMirror 6](https://codemirror.net/), and can be extended with any CodeMirror extension. This allows for deep customization of the editor's behavior, such as adding new themes, keymaps, autocompletion sources, and more. There are two ways to apply extensions: programmatically and declaratively. ### Programmatic extensions The ``, ``, and `` components all have an `extensions` property which accepts a CodeMirror `Extension` object (or an array of them). ```js import {EditorView} from '@codemirror/view'; const ide = document.querySelector('playground-ide'); const myTheme = EditorView.theme({ '&': { backgroundColor: 'lightpink', }, }); ide.extensions = myTheme; ``` ### Declarative extensions For simpler use-cases, or for when you want to package an extension as a reusable HTML element, you can use declarative extensions. A declarative extension is a custom element that provides one or more CodeMirror extensions. Playground elements will automatically find any declarative extension elements placed in their `extensions` slot and apply them. Here's an example of a custom theme packaged as a declarative extension: ```html ``` The `codemirrorExtensionMixin` handles the communication with the playground editor. Your class just needs to implement the `getExtensions()` method. ## Bundling Playground uses a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to perform TypeScript compilation. If you are bundling or otherwise modifying the layout of the `playground-elements` NPM package, you may need to add special handling for this file. ### Rollup Use the Rollup [`@web/rollup-plugin-import-meta-assets`](https://github.com/modernweb-dev/web/tree/master/packages/rollup-plugin-import-meta-assets#readme) plugin to automatically copy the worker script into the correct location. See [examples/rollup](https://github.com/google/playground-elements/tree/main/examples/rollup) for an example configuration. ### Webpack Webpack 5+ [automatically supports loading Web Workers](https://webpack.js.org/guides/web-workers/) with no additional plugins. See [examples/webpack](https://github.com/google/playground-elements/tree/main/examples/webpack) for an example configuration. ### Other If you are bundling in another way, you'll need to configure your build so that the file `node_modules/playground-elements/playground-typescript-worker.js` is copied into the same directory as your bundle. For example, if you bundled playground elements into `./js/app.js`, then you should copy the worker module to `./js/playground-typescript-worker.js`. ## Sandbox security > ⚠️ Changing the sandbox base URL from the default can create a security > vulnerability for your site if not done carefully. Do not change the default > unless you have a specific reason to, and please read this entire section > carefully. The `sandboxBaseUrl` property and `sandbox-base-url` attribute can be used to override the origin where untrusted code will execute when displaying Playground previews. The default origin is unpkg.com, which is secure because it is unprivileged and cannot modify the host window. You may wish to override this default sandbox base URL if you do not want a dependency on `unpkg.com`, e.g. for isolation from outages, or because your network does not have access to it. Note that Playground currently also uses `unpkg.com` by default (unless you set `cdnBaseUrl`) to retrieve imported bare modules that are not otherwise handled by an [import map](#module-resolution), so to remove the dependency on unpkg, you should also set `cdnBaseUrl`. See the API docs for more info. ### Background Playground previews work by using a [service worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API). This service worker takes control over requests to a particular URL space, allowing it to respond to HTTP requests using the files from your local project, instead of from a remote server. The playground preview component contains an `