Skip to content

Open in playground

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.

Readers see

Open in TS Playground (opens in a new tab)
type Status = 'queued' | 'running' | 'done';
function label(s: Status): string {
return s === 'done' ? 'Finished' : s;
}
console.log(label('done'));

You write

```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 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

A Python example opens in Python Tutor, the custom playground that this site adds in its options:

Open in Python Tutor (opens in a new tab)
from statistics import median
print(median([3, 1, 4, 1, 5]))

This site adds StackBlitz, which takes a project in a form post (Add a playground). The button is then part of a form:

index.js
const words = ['queued', 'running', 'done'];
document.body.textContent = words.join(' then ');
  • 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 need JavaScript to reach the playground.

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

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:

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 describes both functions and the form post.

  • 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 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.