preact-playground.landing Open editor

playground/preact

A Preact Playground for Hooks, Signals and htm Templates

Answer a small Preact question in the time it takes to ask it — a hook firing, a signal updating, a component re-rendering, with the console sitting beside the preview.

modequick loop
consolebeside the app
sharelive link
installnone
probe.js
import { render } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import { html } from 'htm/preact';

// does this effect fire on every click?
function Probe() {
  const [n, setN] = useState(0);
  useEffect(() => console.log('effect', n), [n]);
  return html`<button onClick=${() => setN(n + 1)}>${n}</button>`;
}

render(html`<${Probe} />`, document.body);
a question, running · console open

01 platform

Why a Preact idea is quickest to check by running it

Most Preact questions are not really questions about Preact — they are questions about what your code does right now. The fastest answer is to run it and look, and this is a place built for exactly that.

  • A question, not a project

    Open the playground and there is already a running component. You are one edit away from testing an idea, with no folder to set up and no files you did not ask for.

  • The console is right there

    console.log output lands beside the app, not in a separate tab, so a useEffect firing or a value changing is visible the instant it happens.

  • Real Preact, not a sketch

    Hooks run against the real preact/hooks runtime, so what you observe is how Preact actually behaves — the point of running it is to trust the answer.

  • Share the running thing

    Hand over a live preview link and the other person sees your experiment running, which settles a debate faster than a paste of the code does.

02 deep dive

A hook firing, with the console beside it

The classic uncertainties — when an effect runs, what a dependency array changes — are things to watch, not memorise.

Log inside the effect. A console.log in a useEffect tells you exactly when it runs and with what values, printed next to the app as you click. The dependency array stops being a guessing game.

Change one line, see the difference. Add or remove a dependency, flip a piece of state, and the console shows the new behavior immediately — the loop is fast enough that comparing two versions is a matter of seconds.

Custom hooks run for real. Pull a hook into the file and call it; because it is genuine Preact, a bug in your hook shows up here the same way it would in an app, which is the whole reason to test it.

when
log in the effect
deps
watch, don't guess
state
flip and compare
runtime
real preact/hooks
deps.js
useEffect(() => {
  console.log('A: runs once');
}, []);

useEffect(() => {
  console.log('B: runs when count changes', count);
}, [count]);
which log prints, and when?

03 pipeline

Testing a Preact component, start to finish

The loop for turning a hunch into an answer, with nothing to install between you and the running component.

  1. Open

    The playground loads with a live component and the console visible. There is no new-project step; the experiment is already running when the tab finishes loading.

  2. Edit

    Change the component, add a hook, drop in a console.log. Because the starter uses htm, there is no compile between the edit and the reload — a save is a reload.

  3. Watch

    Read the console beside the app to see effects fire, state settle and renders happen. This is where the question gets answered, in the output rather than in your head.

  4. Share

    Copy the live preview link. Whoever opens it sees the same running component and the same console, so the answer travels with the code that produced it.

04 features

What the playground gives a Preact experiment

A small surface on purpose — everything a quick test of a hook or a few components needs, and nothing that turns a five-minute question into a project.

  • npm when a test needs it

    Install a package to reproduce a bug or try an idea — @preact/signals, a utility, a date library — resolved through esm.sh with no node_modules to manage.

  • The console, front and center

    Logs, warnings and errors print beside the running app, attributed to where they came from, so a misbehaving effect is easy to catch.

  • Live preview to share

    A shareable URL renders the running experiment for anyone who opens it — no build to send, no screenshot to explain.

  • htm, so no build waits

    Templates are tagged literals with nothing to compile, which is what keeps the edit-and-look loop instant enough to be worth using.

  • Grows up when you want

    If a quick test turns into something real, the same code opens in the full Preact editor with a file tree, Git and a terminal.

  • Nothing to install

    The whole loop runs client-side, so a locked-down or borrowed machine is enough to test a Preact idea properly.

05 deep dive

Watching @preact/signals update the DOM

Signals are easiest to understand by seeing what they do not do — namely, re-run a component.

Install and read a signal. Add @preact/signals from the npm panel, create a signal, and render count.value. Only that text node is bound to the signal, and the console confirms the component function did not run again.

Compare it to state. Put a useState counter beside a signal counter, log inside the component, and watch: the state version logs on every click, the signal version does not. The difference is the whole idea, made visible.

Derive with computed. computed(() => a.value + b.value) updates only where it is read. Seeing a derived value change without a re-render is the fastest way to trust it.

install
@preact/signals
read
count.value
derive
computed()
re-render
none
signal.js
import { signal, computed } from '@preact/signals';

const count = signal(0);
const doubled = computed(() => count.value * 2);

// clicking updates one text node,
// and the component function never re-runs.
count.value++;
no component re-render — watch the console

06 workflow

A state bug in Preact, then the fix

A stale-closure bug is the kind of thing you argue about in theory and settle in ten seconds by running it.

preact-probe — xcodx
  • run: increment in a setInterval
  • console: count stuck at 1
  • // stale closure — deps missing
  • useEffect captured count = 0 once
  • fix: setN(v => v + 1)
  • console: 1, 2, 3, 4 … climbing
  • share preview link
  • copied · opens the running fix
  • The answer is in the output

    A stale closure is obvious the moment the console shows the number stuck — no reasoning about it required, just a look.

  • The fix is one edit away

    Switch to the updater form, save, and the console starts climbing — the before and after are seconds apart.

  • Send the settled answer

    The shared link opens the corrected version running, so the explanation is the code, not a description of it.

07 ecosystem

The same fast loop for any framework

The quick playground loop is not Preact-only — the same editor answers a small question in React, Vue, Svelte or Solid, picking the compiler per file.

  • React
  • Vue
  • Angular
  • Svelte
  • SolidJS
  • Lit
  • HTMX
  • Vite
  • TypeScript
  • JavaScript
  • HTML
  • CSS
  • SCSS
  • Less
  • Pug
  • Tailwind
  • Bootstrap
  • Vuetify
  • Ant Design
  • shadcn/ui
  • Phaser
  • Node.js
  • Python
  • Java
  • C++
  • C#
  • Go
  • Rust
  • Ruby
  • PHP
  • Kotlin
  • Swift
  • SQL
  • Bash

08 languages

What else the playground can run

A Preact experiment sits beside every other language the editor compiles, renders or executes on demand.

Compiled in your browser11

Zero build step. Transform runs on a Web Worker, so typing never blocks.

  • JSX
  • TSX
  • TypeScript
  • Vue SFC
  • Svelte
  • Angular (JIT)
  • SolidJS
  • SCSS
  • Sass
  • Less
  • Pug

Rendered natively8

Straight to the live preview, no transform in the way.

  • HTML
  • CSS
  • JavaScript
  • JSON
  • Markdown
  • Jupyter (.ipynb)
  • SVG
  • YAML

Executed on demand22

70+ languages run through a self-hosted Piston engine. stdout, stderr, images and tracebacks land in the console.

  • Python
  • Java
  • C
  • C++
  • C#
  • Go
  • Rust
  • Ruby
  • PHP
  • Kotlin
  • Swift
  • Lua
  • Scala
  • Perl
  • Haskell
  • Elixir
  • Dart
  • R
  • Julia
  • SQLite
  • Bash
  • PowerShell

09 questions

Using the Preact playground — common questions

How is this different from the full Preact editor?

The playground opens straight into a running component with the console beside it, tuned for answering one question fast. The full Preact editor adds a file tree, Git, a terminal and multi-file projects for when a quick test turns into something you want to keep.

Is this a Preact REPL?

In spirit, yes — you type Preact and see it run immediately, which is what a REPL is for. It goes further than most, because you can install packages from npm and share the running result as a live link, not only a snippet.

Can I test a custom hook here?

Yes. Write the hook in the file and call it from the component; because this is the real preact/hooks runtime, a bug in the hook behaves exactly as it would in an app, which is the point of testing it here.

Can I use @preact/signals in the playground?

Yes. Install @preact/signals from the npm panel and read a signal in your markup. Logging inside the component shows it updating the DOM without re-running the component, which is the behavior signals exist for.

Do I need to install anything to try Preact?

No. The playground runs entirely in the browser — the Preact runtime, htm and the console are all client-side, so a Chromebook or a borrowed laptop is enough to test a Preact idea properly.

Can I share what I built in the playground?

Yes. Copy the live preview link and anyone who opens it sees the same component running with the same console output, so an answer or a bug report travels as a working example rather than a description.

Does the console show Preact warnings?

Yes. Preact's development warnings, your own logs and any runtime errors all print in the console beside the app, attributed to where they came from, so a problem is easy to trace while you experiment.

Do I need to install anything to use XCODX Studio?

No. XCODX Studio is a browser-based IDE — the editor, the compilers and the preview all run client-side. There is no download, no package manager to set up and no configuration file to write. Opening the editor is the whole setup step.

Where is my code stored?

In your own browser. Projects, file history and Git objects live in local storage on your device and are never uploaded to a server. That also means XCODX works offline: it is a Progressive Web App, so you can install it and keep coding with no connection.

Is XCODX Studio free?

Yes. The editor, the live preview, the 70+ language runtimes, npm installs, Git and the integrated terminal are all free to use.

Can I use XCODX on a tablet or Chromebook?

Yes. The editor is a responsive web app, so a Chromebook, an iPad or an Android tablet gets the same compilers and the same preview a laptop does — there is no desktop-only build, because there is no build to install at all. The layout adapts to the screen rather than shrinking a desktop UI into it.

Can I export a project or move it to my own machine?

Yes. Export the whole project as a zip with its folder structure intact and open it locally, or commit it and push. It is ordinary source on disk from that point on — no proprietary format and no lock-in, which is also why importing an existing repository from GitHub works the same way in reverse.