Getting started
playhtml turns any HTML element into a live, collaborative one with a single attribute. This guide gets you from empty page to a working shared toggle.
Pick your setup:
Install
Section titled “Install”Add the package with your package manager, or load it from a CDN without a build step:
npm install playhtml<script type="module" src="https://unpkg.com/playhtml"></script>Initialize
Section titled “Initialize”Call playhtml.init() once on page load. Cursors are opt-in.
<script type="module">
import { playhtml } from "playhtml";
playhtml.init({ cursors: { enabled: true } });
</script>If you loaded playhtml from the CDN <script> tag above, the library is available as a global — no import needed:
<script>
playhtml.init({ cursors: { enabled: true } });
</script>Add a capability
Section titled “Add a capability”Mark any element with a capability attribute — for example, can-toggle:
<button id="my-lamp" can-toggle>lamp</button>Give every interactive element a unique id. That’s how state is keyed and synced across everyone on the page.
Install
Section titled “Install”npm install @playhtml/react @playhtml/commonInitialize
Section titled “Initialize”Wrap your tree in PlayProvider once, then drop in a capability component. Cursors are opt-in.
import { PlayProvider, CanToggleElement } from "@playhtml/react";
export function App() {
return (
<PlayProvider initOptions={{ cursors: { enabled: true } }}>
<CanToggleElement>
<button id="my-lamp">lamp</button>
</CanToggleElement>
</PlayProvider>
);
}Need more control? Use CanPlayElement with a render prop to read and write the shared data directly:
import { CanPlayElement } from "@playhtml/react";
import { TagType } from "@playhtml/common";
<CanPlayElement
tagInfo={[TagType.CanToggle]}
id="my-lamp"
defaultData={{ on: false }}
>
{({ data, setData }) => (
<button onClick={() => setData({ on: !data.on })}>
{data.on ? "on" : "off"}
</button>
)}
</CanPlayElement> Try it live
Section titled “Try it live”This toggle is shared with everyone reading this page right now. Click it and watch.
Where to next
Section titled “Where to next”- Core concepts — the four kinds of shared state (element data, page data, presence, events) and when to use each.
- Using React — if your app is a React app, start here; concept pages show React inline.
- Capabilities — every built-in
can-*attribute with live demos. - Data essentials — shape, update, and clean up
defaultData. - Presence & cursors — multiplayer cursors and ephemeral per-user state.
- Shared elements — cross-page and cross-domain state.
- Building with AI — Claude Code plugin + a prompt template for any LLM.
- API reference — the full
playhtml.init()options table and React API types.