Output windows, Remote Output and Freeze

The output normally sits next to the editor, in an inline frame. This guide shows how to move it into a browser tab or a popup, how to keep several outputs in sync, how to link another device to your output with Remote Output, and how to escape a runaway loop with Freeze. Remote Output and Freeze are experimental: they work, but they are work in progress and may change.

Where the output runs

The output runs in its own origin, separate from the editor's. The inline frame loads from out.rtcode.io, or from out.rtcode.net when the playground is embedded in another page or the browser provides no origin-keyed agent cluster. Output tabs and popups always open on out.rtcode.net. The two output origins have separate service workers, IndexedDB (the playground's KV) and session state. The console is a third page, on co.rtcode.io: see Console and network.

The origin separation is the isolation. Whether the browser also runs the output in its own process is the browser's decision: out.rtcode.net is a separate site, while out.rtcode.io relies on an origin-keyed agent cluster.

The inline frame is given these permissions, so the code in it can request them: clipboard-write, clipboard-read, screen-wake-lock, midi, geolocation, microphone, camera, display-capture, encrypted-media, fullscreen and payment. See Architecture.

Opening tabs and popups

Commands

CommandKeysAlso in
New Output Window (popup)…Alt+Shift+B / ⌥+⇧+BOpen menu (Alt+K) ▸ Output ▸ Popup, and the editor's context menu
New Output Window (tab)…Ctrl+Alt+B / ⌘+⌥+BOpen menu ▸ Output ▸ Tab, and the editor's context menu

The Popup item of the menu shows the hint Alt+B. The key that opens a popup is Alt+Shift+B. The Popup item is hidden on touch-only devices, and the Tab and Remote items stay.

Each command opens out.rtcode.net in a window named O[N], as a popup or as a tab, at the position and size that slot last had. A slot without one starts from the size of the inline output. Every output reports its geometry every second, when it resizes and when it unloads. The playground waits up to 5 seconds for the new window to report that it is ready, and then initializes the output in it.

What happens to the inline output

The first external window replaces the inline output. The frame is removed, so its page state is lost, and the split moves fully to the input. A placeholder reads "Output in external window." ("…windows." with several). Later windows add more outputs. Every output receives the sync updates and the per-document output settings.

The settings and tools that need the inline frame have no effect once it is gone: the fixed viewport, zoom, Auto-fit, Output: Metrics and Fullscreen Output, and the scripting globals that measure or query the inline output. See Which outputs a setting reaches.

Closing windows

Closing the last external window reloads the playground, which brings the inline output back. Reloading or leaving the playground closes every output window it opened.

Popups must be allowed

Output tabs and popups need the browser to allow popups from rtcode.io. Allow them before you open the first output window. If the output does not come back after a blocked window, see Troubleshooting.

Keeping windows in sync

Every output in the set receives every hot patch: the inline frame, or the popup and tab windows, which never coexist with it. A change made in one output is written back into the editor and then hot-patched into the others. A newly opened window gets its own full initialization. See Live sync and reloads.

With several outputs open, your code runs once per output, so its console logs repeat once per output. All of them land in the same console and badges.

Moving between input and output

KeysWhat they do
Ctrl+O / ⌘+OFocus Output. Restores the element that had focus in the output when you left it. Otherwise it focuses the first visible [autofocus] element, then the first focusable element, open shadow roots included, then the frame itself.
Ctrl+I / ⌘+I, outside the editorFocus Input. Saves the output's focused element first.
Ctrl+F10, Ctrl+F11, Ctrl+F12 / ⌘ in the editor, ⌃ elsewhereFullscreen Input, Fullscreen (the whole playground) and Fullscreen Output. Pressing the same key again exits. Fullscreen Output covers the output pane with its fixed-viewport and zoom framing, and then focuses the output. These commands exist only where the Fullscreen API is available.
Alt+/ / ⌥+/Toggle Layout: side by side or stacked.
Alt+P / ⌥+PToggle Panels: swaps input and output and mirrors the split.
Ctrl+Alt+Home or End / ⌃+⌥+Home or EndScrolls every output to the top or the bottom without leaving the editor.
Ctrl+Alt+PageUp or PageDownScrolls every output by one page minus one line.
Ctrl+Alt+← or →, and Ctrl+Alt+[ or ]Scroll every output by 135 px, horizontally and vertically.

With Shift, the Home, End, PageUp, PageDown and bracket keys scroll horizontally. Pressed inside an output, the same Ctrl+Alt navigation keys move the editor's cursor instead, while Ctrl+Alt+[ and ] still scroll the outputs. The layout is saved in the URL as h=1 for stacked and se=io or se=oi for the order, and the script form is s.layout. See Keyboard shortcuts and Selection and layout globals.

Remote Output

Experimental Remote Output links another device to your playground's output over WebRTC, with a link and a QR code. It is work in progress.

Note: Remote Output is experimental and under development, and it may change. Script edits that need a full output reload are not applied on remote devices, and keyboard shortcuts are not forwarded from them.

Starting a session

  1. Press Alt+Q / ⌥+Q. You can also use the palette item New Remote Output…, Open ▸ Output ▸ Remote, or the editor's context menu.
  2. A dialog warns: "Remote output is work in progress! <script> edit→load is not implemented. To try it now, 1. click Try 2. open the highlighted URL in remote device/browser". Choose Try, or Cancel.
  3. A toast shows the link https://rt.ht/<id>, with rt.ht/<id> highlighted, and a QR code of it. The id is four characters long. Share hands the link to the browser's share sheet, titled "Remote Output", and Cancel or Esc ends the session.
  4. Open the link on the other device, or scan the QR code.

The playground waits for a device to join without a time limit. Once the device announces itself, both data channels must open within 10 seconds. The connection uses one WebRTC data channel named sync in each direction, set up through a signaling service.

While a device is connected

When a device connects, a toast names its browser for two seconds, and a card for the session appears in View Remote Outputs. If the connection fails or ends, a toast names the device's browser, the session is removed, and a new session with the same id starts waiting, until you press Cancel. The device itself shows "Remote output terminated! Session lasted <duration>.".

View Remote Outputs… opens with Alt+Y / ⌥+Y, from the palette, or from the cast button that appears in the toolbar, with a count, while sessions exist. Its title is a cast icon and "×N".

Session card

The device's browser, its link (rt.ht/<id>), its location (city, region, country), its IP address, the start time (absolute and relative) and the round trip in milliseconds for a trivial evaluation, or ❌ on a timeout. The location and IP address are looked up from the device with ip.rt.ht.

WebRTC stats

Focusing a card shows the packets and bytes received and sent, the local and remote candidate types and protocols, and the round-trip time. The numbers refresh every 5 seconds while the dialog is open.

Actions

Click a card to end the session, after the confirmation "Terminate this remote output session?" (Terminate). Right click a card to copy its transport stats as JSON.

Limits

  • Script edits that need a full output reload are not applied on remote devices.
  • Keyboard shortcuts are not forwarded from the remote device.
  • Worker requests in an output that is connected only over WebRTC see request.rt.user === null.
  • Both devices need WebRTC. Share needs Web Share; where the browser lacks it, you get the link and the QR code only.

Freeze

Experimental Freeze takes the playground to frozen.rt.ht, away from the code that hangs it, and offers a way back that does not run the output.

Note: Freeze is experimental and may change.

Commands

Both commands are in the F1 palette and on the keyboard. They have no menu item.

CommandKeysEffect
Freeze This WindowCtrl+Alt+D / ⌘+⌥+DFreezes this playground tab.
Freeze All WindowsCtrl+Alt+F / ⌘+⌥+FAlso freezes every other playground tab or window of rtcode.io in the same browser profile. Pages that are already frozen, and sign-in pages, ignore it.

The keys with ⌘ are for the editor on macOS. Elsewhere on the page, use Ctrl or ⌘ with Alt. The output and the console forward these keys to the playground, but only while their own page still responds, and a hung output cannot forward anything. The console drops ⌘, so on macOS use ⌃+⌥+F and ⌃+⌥+D there.

Because the output runs in a separate origin, and in a separate process where the browser provides one, a runaway loop in it can leave the playground responsive enough to navigate away. If keyboard focus is inside the hung output, click the editor or the toolbar before you press the keys.

The frozen page

Freeze saves the URL state and navigates the playground to frozen.rt.ht, carrying the playground's URL and state. Leaving the page closes the output windows, and the unload guard may ask for confirmation while an Agent Folder Share is active or the URL state is unsaved.

  • Heading and message. "Code is frozen!" with "Review scripts for infinite loops." when the code has scripts, and "Code is frozen." with "No scripts; ready to unfreeze." when it has none.
  • Button. "Review and unfreeze ›" or "Unfreeze ›". For the first 5 seconds the button is dimmed and has no link. Then it gets its link and takes focus.
  • Preview. A non-interactive, color-inverted preview of the code sits beside the text. It is the playground in frozen mode: the editor is read-only, the split is disabled, and no output is created.

Unfreezing

Review and unfreeze ›

Returns to the playground with the editor loaded, but without starting the output. A message that you cannot close reads "Infinite loop? Fix code and reload! Ctrl+R" (⌘+R on macOS), and the editor has focus. The unfreeze flag is removed from the URL at once, so Ctrl+R or any reload then runs the fixed code.

Unfreeze ›

Returns to the same URL and runs the code normally.

Recovering from a runaway loop

Clicking Start in this page hangs the output with an endless loop.

html
<button id=go>Start</button>
<script>
  go.onclick = () => { for (;;) {} }; // runaway loop: the output hangs after the click
</script>
  1. Click into the editor, so keyboard focus leaves the hung output.
  2. Press Ctrl+Alt+D / ⌘+⌥+D. Use Ctrl+Alt+F / ⌘+⌥+F to freeze every open playground window.
  3. On frozen.rt.ht ("Code is frozen!"), wait 5 seconds and choose Review and unfreeze ›.
  4. The playground opens without starting the output and shows "Infinite loop? Fix code and reload!". Remove the loop and press Ctrl+R / ⌘+R.

Browser requirements

FeatureRequires
Output tabs and popupsThe browser must allow popups from rtcode.io. The Popup menu item is hidden on touch-only devices.
Fullscreen commandsThe Fullscreen API, with the webkit prefix accepted. Without it, the menu section is hidden.
Remote Output ExperimentalWebRTC on both devices. Share needs Web Share.

See Browser support.

See also