---
title: "Open in playground"
description: "Add a title bar button that opens the example in an online playground, with the code already filled in."
url: "https://ewels.github.io/starlight-codeblocks/features/open-in-playground/"
markdown: "https://ewels.github.io/starlight-codeblocks/features/open-in-playground.md"
section: "Copy and run"
site: "starlight-codeblocks documentation"
context: "This page is from the documentation of starlight-codeblocks. A Starlight plugin that adds focus, line states, annotations, API auto-linking and 22 more features to the code blocks of a site."
index: "https://ewels.github.io/starlight-codeblocks/llms.txt"
---

# Open in playground

> Add a title bar button that opens the example in an online playground, with the code already filled in.

A code block in Starlight shows code that readers can copy, but not run. Many languages have an online playground that runs code in the browser. The `playground` attribute adds a button to the title bar that opens the example in one, with the code already filled in.

````md
```ts playground="typescript"
type Status = 'queued' | 'running' | 'done';

function label(s: Status): string {
  return s === 'done' ? 'Finished' : s;
}

console.log(label('done'));
```
````

The block has no title, so the plugin adds a title bar for the button. Click **Open in TS Playground** to open the TypeScript Playground in a new tab, with this code in the editor.

## Syntax

| Syntax | Where |
|---|---|
| `playground="<name>"` | Code block fence line |

The name is a built-in playground, or a playground that the site adds in its configuration.

| Name | Label | Code goes in |
|---|---|---|
| `typescript` | **Open in TS Playground** | The URL, compressed with lz-string |
| `rust` | **Open in Rust Playground** | The URL |

## Examples

### A custom playground

A Python example opens in Python Tutor, the custom playground that this site adds in its [options](#options):

````md
```py playground="pythontutor"
from statistics import median

print(median([3, 1, 4, 1, 5]))
```
````

### A playground that takes a form post

This site adds StackBlitz, which takes a project in a form post ([Add a playground](https://ewels.github.io/starlight-codeblocks/extend/add-a-playground/)). The button is then part of a form:

````md
```js title="index.js" playground="stackblitz"
const words = ['queued', 'running', 'done'];
document.body.textContent = words.join(' then ');
```
````

## Behaviour

- The button:
  - A playground that takes the code in its URL renders as a link with the look of a button. It opens in a new tab.
  - A playground that takes the code in a form post renders as a form with hidden fields. It opens in a new tab too.
- The code it sends:
  - The playground gets the copied text of the block. Directives are removed, hidden lines are kept, and a terminal session sends only its commands.
- Screen readers:
  - Screen readers announce "opens in a new tab" after the label.
- Warnings:
  - If a URL is longer than 8,000 characters, the build logs a warning, because some browsers cut long URLs.
  - If the name is not a known playground, the build logs a warning and the block has no button.
- Print:
  - The button does not print.
- Without JavaScript:
  - The button works without JavaScript. Only the values that readers type into [fill-in placeholders](https://ewels.github.io/starlight-codeblocks/features/fill-in-placeholders/) need JavaScript to reach the playground.

## Options

### `playgrounds`

Adds a button that opens the code in an online playground. Set it to `false` to turn the feature off. `playground` attributes then have no effect.

- Type: `false | object`
- Default: On

### `playgrounds.<name>`

Custom playgrounds by name, in addition to the built-in ones.

- Type: an object with a `label` and one of `url` or `post`
- Default: None

A custom playground has a label and one function. `url` returns the URL to open. `post` returns a form action and its fields. This site adds Python Tutor, which takes the code in its URL:

```js title="astro.config.mjs"
codeblocks({
  playgrounds: {
    pythontutor: {
      label: 'Open in Python Tutor',
      url: ({ code }) => `https://pythontutor.com/visualize.html#mode=edit&py=3&code=${encodeURIComponent(code)}`,
    },
  },
});
```

The guide to [adding a playground](https://ewels.github.io/starlight-codeblocks/extend/add-a-playground/) describes both functions and the form post.

- [Configuration](https://ewels.github.io/starlight-codeblocks/configuration/): Learn how to set options for the whole site, or for a single code block.

## Limitations

- The playground runs the copied text only. The code must be complete, or it fails in the playground. Put the imports and set-up in [hidden lines](https://ewels.github.io/starlight-codeblocks/features/hidden-lines/) if they distract from the example.
- A block can open one playground.
- The plugin cannot check that a custom playground accepts the code. Test each custom playground once in a browser.

## Related

- [Hidden lines](https://ewels.github.io/starlight-codeblocks/features/hidden-lines/): keep the code complete for the playground, while readers see only the part you explain.
- [Fill-in placeholders](https://ewels.github.io/starlight-codeblocks/features/fill-in-placeholders/): send the values that readers type to the playground.
- [Add a playground](https://ewels.github.io/starlight-codeblocks/extend/add-a-playground/): the interface for custom playgrounds.
