### Generate React Starter Project
Source: https://github.com/spencerc99/playhtml/blob/main/templates/README.md
Use this command to scaffold a new project with the React starter template. Install dependencies and start the development server.
```bash
npx degit playhtml/playhtml/templates/react-starter my-project
cd my-project
bun install
bun dev
```
--------------------------------
### Start PartyKit Dev Server
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Starts the PartyKit development server for real-time synchronization.
```bash
bun dev-server
```
--------------------------------
### Start Extension Dev Server
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Starts the browser extension development server with WXT hot reload.
```bash
bun dev-extension
```
--------------------------------
### Start Local Development Server
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/README.md
Starts the local development server, typically accessible at `localhost:4321`. This command is used for active development and previewing changes in real-time.
```bash
bun dev
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/README.md
Installs all necessary dependencies for your Astro + Starlight project. Run this after cloning the repository or creating a new project.
```bash
bun install
```
--------------------------------
### Install @playhtml/react
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/using-react.md
Install the React package for PlayHTMLL. Compatible with React 16.8 and above.
```bash
npm install @playhtml/react
```
--------------------------------
### Run Local Smoke Tests
Source: https://github.com/spencerc99/playhtml/blob/main/smoke-tests/README.md
Execute the local smoke tests after building the site. This includes installing necessary browsers if it's a one-time setup.
```bash
bun build-site
bun run -C smoke-tests install-browsers # one-time
bun smoke
```
--------------------------------
### Install playhtml React Packages
Source: https://github.com/spencerc99/playhtml/blob/main/README.md
For React projects, install the necessary playhtml packages using npm.
```bash
npm install @playhtml/react @playhtml/common
```
--------------------------------
### Create Astro Project with Starlight Template
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/README.md
Use this command to create a new Astro project pre-configured with the Starlight template. Ensure you have Bun installed.
```bash
bun create astro@latest -- --template starlight
```
--------------------------------
### Composed Grid Example
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/capabilities.mdx
Demonstrates a composed grid of interactive cards, each linking to a live experiment. These examples showcase combinations of can-play, per-user awareness, and shared state.
```html
```
--------------------------------
### Initialize PlayHTML with Basic Options
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/reference/init-options.md
Demonstrates the basic initialization of playhtml with a specified room and cursor settings. This is a common starting point for integrating playhtml into an application.
```javascript
import { playhtml } from "playhtml";
playhtml.init({
room: "my-room",
cursors: { enabled: true },
// โฆ
});
```
--------------------------------
### Vanilla HTML Setup for PlayHTMl
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/integrations/building-with-ai.md
Configure custom properties and initialize PlayHTMl for vanilla HTML elements. Ensure all properties are set before calling playhtml.init().
```javascript
const element = document.getElementById("myElement");
element.defaultData = { /* ... */ };
element.onClick = (e, { data, setData }) => { /* ... */ };
element.updateElement = ({ data }) => { /* ... */ };
import { playhtml } from "https://unpkg.com/playhtml";
playhtml.init();
```
--------------------------------
### Vanilla HTML: Import + Manual Init (npm)
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/getting-started.mdx
Install playhtml via npm and import it into your project when using a bundler. Ensure playhtml.init() runs after your interactive elements are in the DOM.
```bash
npm install playhtml
```
```javascript
import { playhtml } from "playhtml";
playhtml.init({ cursors: { enabled: true } });
```
--------------------------------
### Install Claude Code Plugin for playhtml
Source: https://github.com/spencerc99/playhtml/blob/main/README.md
Install the playhtml plugin for Claude Code to enhance its ability to build playhtml elements.
```bash
claude plugin marketplace add spencerc99/playhtml
claude plugin install playhtml@playhtml
```
--------------------------------
### Create a Changeset
Source: https://github.com/spencerc99/playhtml/blob/main/CONTRIBUTING.md
Run this command to create a changeset for your changes. It will guide you through selecting affected packages, choosing a version bump type, and providing a summary.
```bash
bun run changeset
```
--------------------------------
### Initialize PlayHTML in React
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/index.mdx
This snippet demonstrates how to set up PlayHTML within a React application using the provided components. Ensure you have installed the necessary packages.
```tsx
// npm install @playhtml/react @playhtml/common
import { PlayProvider, CanToggleElement } from "@playhtml/react";
```
--------------------------------
### React: Setup for Duplicating Elements
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/capabilities.mdx
React integration for 'can-duplicate' typically requires setupPlayElement for new clones to register correctly. Refer to 'Dynamic elements' for details.
```tsx
// React wiring for can-duplicate typically pairs with setupPlayElement
// so freshly-mounted clones register themselves. See "Dynamic elements".
```
--------------------------------
### Initialize PlayHTML with Development Mode and Capabilities
Source: https://github.com/spencerc99/playhtml/blob/main/website/test/shared-test-source.html
Initializes PlayHTML with a specified host, enabling development mode and custom capabilities like 'can-post'. This setup is crucial for enabling features such as dynamic data updates and element registration.
```javascript
import { playhtml } from "../../packages/playhtml/src";
console.log("๐ฏ Initializing PlayHTML...");
try {
// Initialize playhtml with development mode and can-post capability
await playhtml.init({
host: "localhost:1999",
extraCapabilities: {
"can-post": {
defaultData: [],
defaultLocalData: {
addedEntries: new Set()
},
updateElement: ({ data: entries, localData: { addedEntries }, setLocalData, }) => {
const entriesToAdd = entries.filter(
(entry) => !addedEntries.has(`${entry.name}-${entry.timestamp}`)
);
const guestbookDiv = document.getElementById("guestbookMessages");
if (!guestbookDiv) return;
entriesToAdd.forEach((entry) => {
const newEntry = document.createElement("div");
newEntry.classList.add("guestbook-entry");
const entryDate = new Date(entry.timestamp);
const time = entryDate.toTimeString().split(" ")[0];
const isToday = entryDate.toDateString() === new Date().toDateString();
const dateString = (() => {
const now = new Date();
if (
now.getFullYear() !== entryDate.getFullYear() ||
now.getMonth() !== entryDate.getMonth()
) {
return "Sometime before";
} else if (isToday) {
return "Today";
} else if (now.getDate() - entryDate.getDate() === 1) {
return "Yesterday";
} else if (now.getDate() - entryDate.getDate() < 7) {
return "This week";
} else {
return "Sometime before";
}
})();
newEntry.innerHTML = `${dateString} at ${time}${entry.name}${entry.message}`;
guestbookDiv.prepend(newEntry);
addedEntries.add(`${entry.name}-${entry.timestamp}`);
});
setLocalData({ addedEntries });
},
onMount: ({ getElement, getData, setData }) => {
const element = getElement();
element.addEventListener("submit", (e) => {
e.preventDefault();
e.stopImmediatePropagation();
const formData = new FormData(e.target);
const inputData = Object.fromEntries(formData.entries());
if (!inputData.name || !inputData.message) {
return false;
}
const timestamp = Date.now();
const newEntry = {
name: inputData.name,
message: inputData.message,
timestamp,
};
setData((d) => {
d.push(newEntry);
});
// Clear form
element.querySelector('input[name="message" ]').value = "";
return false;
});
},
},
},
});
// Update domain display
const currentUrl = window.location.host + window.location.pathname;
document.getElementById("current-domain").textContent = currentUrl;
document.getElementById("current-domain-lamp").textContent = currentUrl;
document.getElementById("current-domain-readonly").textContent = currentUrl;
document.getElementById("current-domain-guestbook").textContent = currentUrl;
console.log("๐ฏ Source page loaded - shared elements should be registered");
// Dynamic discovery test functionality
const sourceLogContainer = document.getElementById("source-log");
function addSourceLog(message, type = "") {
const entry = document.createElement("div");
entry.textContent = `${new Date().toLocaleTimeString()}: ${message}`;
if (type) entry.style.color = type === "discovery" ? "#007acc" : "#dc3545";
sourceLogContainer.appendChild(entry);
sourceLogContainer.scrollTop = sourceLogContainer.scrollHeight;
}
// Dynamic test for source page
let dynamicSourceAdded = false;
document
.getElementById("add-dynamic-source-btn")
.addEventListener("click", () => {
if (dynamicSourceAdded) return;
addSourceLog("Adding dynamic shared element (source)...", "discovery");
const dynamicDiv = document.createElement("div");
dynamicDiv.id = "dynamic-shared-source";
dynamicDiv.setAttribute("shared", "");
dynamicDiv.setAttribute("can-move", "");
dynamicDiv.className = "moveable-box";
dynamicDiv.innerHTML = `
๐ Dynamic Source
โจ Added after init
`;
document.getElementById("dynamic-source-container").innerHTML = "";
document
.getElementById("dynamic-source-container")
.appendChild(dynamicDiv);
// This should register it as a new shared element
playhtml.setupPlayElement(dynamicDiv);
dynamicSourceAdded = true;
document.getElementById("add-dynamic-source-btn").disabled = true;
document.getElementById("remove-dynamic-source-btn").di
});
} catch (e) {
console.error("Error initializing PlayHTML:", e);
}
```
--------------------------------
### React Setup with PlayHTMl Provider
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/integrations/building-with-ai.md
Wrap your React components with PlayProvider to enable PlayHTMl functionality. This is required for using PlayHTMl in React applications.
```javascript
import { PlayProvider } from "@playhtml/react";
function App() {
return (
);
}
```
--------------------------------
### CanPlayElement Usage Example
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/reference/react-api.md
Demonstrates using CanPlayElement to manage shared state for a toggleable button, passing state and update functions via children.
```tsx
{({ data, setData }) => (
)}
```
--------------------------------
### Add Dynamic Shared Source Element
Source: https://github.com/spencerc99/playhtml/blob/main/website/test/shared-test-source.html
Adds a dynamic shared source element and calls its setup function. This is used for testing discovery-related functionalities.
```javascript
document.getElementById("add-dynamic-source-btn").addEventListener("click", () => {
document.getElementById("dynamic-source-container").innerHTML = "Dynamic element added";
dynamicSourceAdded = true;
document.getElementById("add-dynamic-source-btn").disabled = true;
document.getElementById("remove-dynamic-source-btn").disabled = false;
addSourceLog( "Dynamic shared source element added and setup called", "discovery" );
});
```
--------------------------------
### Get Help with Astro CLI
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/README.md
Displays help information for the Astro CLI, listing available commands and their options. Useful for understanding the full capabilities of the CLI.
```bash
bun astro -- --help
```
--------------------------------
### Vanilla HTML: Cloning Elements
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/capabilities.mdx
Utilize 'can-duplicate' to clone elements. This example shows cloning a bunny image and includes a script to reset spawned clones.
```html
```
--------------------------------
### Initialize Playhtml with Cursors Enabled (JavaScript)
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/presence/cursors.md
Enable cursor tracking by setting `cursors.enabled` to true during Playhtml initialization. This is the basic setup for JavaScript projects.
```javascript
import { playhtml } from "playhtml";
playhtml.init({
cursors: {
enabled: true,
}
});
```
--------------------------------
### Initialize PlayHTML and Track Cursors
Source: https://github.com/spencerc99/playhtml/blob/main/website/test/cursor-test.html
Initializes PlayHTML for cursor tracking and sets up event listeners for mouse movement and cursor updates. This is the primary setup for enabling collaborative cursor features.
```typescript
import { playhtml } from "../packages/playhtml/src/index.ts";
const statusElement = document.getElementById("status");
const proximityElement = document.getElementById("proximity-info");
const cursorInfoElement = document.getElementById("cursor-info");
let proximityCount = 0;
function updateStatus(message) {
statusElement.textContent = message;
}
function updateCursorInfo() {
if (window.cursors) {
cursorInfoElement.innerHTML = ` Color: โ ${window.cursors.color}
Name: ${window.cursors.name}
Active Users: ${window.cursors.count}
All Colors: ${window.cursors.allColors.length} `;
}
}
// Track real cursor position
window.lastMouseX = window.innerWidth / 2;
window.lastMouseY = window.innerHeight / 2;
document.addEventListener("mousemove", (e) => {
window.lastMouseX = e.clientX;
window.lastMouseY = e.clientY;
});
// Initialize PlayHTML
playhtml.init({
onCursorUpdate: updateCursorInfo,
onProximity: addProximityEvent,
onPlayerJoin: (player) => {
updateStatus(`Player ${player.name} joined.`);
updateCursorInfo();
},
onPlayerLeave: (player) => {
updateStatus(`Player ${player.name} left.`);
updateCursorInfo();
},
});
updateStatus("Initializing cursor tracking...");
updateCursorInfo();
```
--------------------------------
### Generate HTML Starter Project
Source: https://github.com/spencerc99/playhtml/blob/main/templates/README.md
Use this command to scaffold a new project with the HTML starter template. Then, open the generated index.html file in your browser.
```bash
npx degit playhtml/playhtml/templates/html-starter my-project
open my-project/index.html
```
--------------------------------
### playhtml.init() with Options
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/reference/init-options.md
Demonstrates how to initialize playhtml with various configuration options, such as specifying a room, enabling cursors, and defining event listeners.
```APIDOC
## playhtml.init()
### Description
Initializes the playhtml library with a set of configuration options. These options control aspects like room connection, cursor display, event handling, custom capabilities, and development mode.
### Method
`playhtml.init(initOptions: InitOptions)`
### Parameters
#### `initOptions` Object
- **`room`** (string) - Optional - The room to connect users to. If not provided, it defaults to the current URL's pathname and search. It's automatically prefixed with `window.location.hostname`.
- **`cursors`** (object) - Optional - Configuration for cursor display. Example: `{ enabled: true }`.
- **`host`** (string) - Optional - The public PartyKit host. Use this to self-host the syncing server.
- **`events`** (Record) - Optional - An object where keys are event names and values are `PlayEvent` objects, used to declare event listeners inline at init time.
- **`extraCapabilities`** (Record) - Optional - An object for shipping custom capabilities alongside built-ins. Keys are capability names (e.g., `"can-pulse"`), and values are `ElementInitializer` objects.
- **`defaultRoomOptions`** (DefaultRoomOptions) - Optional - Configuration for the auto-derived URL-based room.
- **`onError`** (() => void) - Optional - A callback function executed upon connection failures.
- **`developmentMode`** (boolean) - Optional - Enables an in-page devtools panel for debugging. Defaults to `false`. Recommended for development builds only.
### Request Example
```js
import { playhtml } from "playhtml";
playhtml.init({
room: "my-room",
cursors: { enabled: true },
events: {
confetti: {
type: "confetti",
onEvent: () => window.confetti({ particleCount: 100 }),
},
},
extraCapabilities: {
"can-pulse": {
defaultData: { on: false },
updateElement: ({ element, data }) => {
element.classList.toggle("pulsing", data.on);
},
onClick: (_e, { data, setData }) => setData({ on: !data.on }),
},
},
onError: () => {
document.body.classList.add("playhtml-offline");
console.warn("playhtml could not connect");
},
developmentMode: true,
});
```
### Response
This method does not return a value. It initializes the playhtml instance.
```
--------------------------------
### React Integration for Transformed Canvas Cursors
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/presence/cursors.md
Example of initializing PlayHTMLL cursors within a React application, specifying a container element for anchoring. This setup is useful for pages with dynamic pan and zoom functionality applied via React state.
```tsx
{/* pan/zoom transform applied here via React state */}
{words.map(w => )}
```
--------------------------------
### Build Website for Production
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Builds the playhtml website for production deployment.
```bash
bun build-site
```
--------------------------------
### Build Production Site
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/README.md
Builds the production-ready version of your website, outputting the static files to the `./dist/` directory. This is the command to run before deployment.
```bash
bun build
```
--------------------------------
### Deploy PartyKit to Production
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Deploys the PartyKit real-time sync server to the production environment.
```bash
bun deploy-server
```
--------------------------------
### Acceptable Nested Data Shape Example
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/data-essentials.md
An example of an acceptable one-level nesting for `defaultData` where fields are clearly related. Deeper nesting should generally be avoided.
```javascript
defaultData: { position: { x: 0, y: 0 }, color: "#ff0000" }
```
--------------------------------
### Vanilla HTML: Import + Manual Init (CDN)
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/getting-started.mdx
This path is suitable when you need to pass options to playhtml.init() or are using a bundler. For CDN usage without a bundler, place the script at the end of the body.
```html
```
--------------------------------
### Flat Data Shape Example
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/data-essentials.md
Example of a good, flat data shape for `defaultData`. Keeping shapes flat improves performance, reduces sync bandwidth, and makes refactoring easier.
```javascript
defaultData: { x: 0, y: 0, color: "#ff0000", size: 100 }
```
--------------------------------
### Avoid Deeply Nested Data Shape Example
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/data-essentials.md
An example of a data shape to avoid in `defaultData` due to deep nesting. Deeply nested objects are harder to update, slower to sync, and more prone to conflicts.
```javascript
defaultData: {
position: { coords: { x: 0, y: 0 } },
style: { appearance: { color: "#ff0000" } },
}
```
--------------------------------
### Getting Own Identity
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/presence/index.mdx
Retrieve the identity information for the current local user.
```js
// Your own identity
const me = playhtml.presence.getMyIdentity();
```
--------------------------------
### Props-Dependent withSharedState Config
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/reference/react-api.md
Example of using a callback for the config in withSharedState when defaultData depends on component props.
```tsx
export const Reaction = withSharedState(
({ reaction: { count } }) => ({ defaultData: { count } }),
({ data, setData }, props) => /* โฆ */,
);
```
--------------------------------
### Project Structure Overview
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/README.md
This is a typical project structure for an Astro + Starlight site. Markdown and MDX files for documentation should be placed in `src/content/docs/`.
```bash
.\nโโโ public/\nโโโ src/\nโ โโโ assets/\nโ โโโ content/\nโ โ โโโ docs/\nโ โโโ content.config.ts\nโโโ astro.config.mjs\nโโโ package.json\nโโโ tsconfig.json
```
--------------------------------
### Clearing Custom Presence Channel
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/presence/index.mdx
Example of clearing a custom 'status' channel by setting its value to null.
```js
// Clear: null
playhtml.presence.setMyPresence("status", null);
```
--------------------------------
### Deploy PartyKit to Staging
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Deploys the PartyKit real-time sync server to the staging environment.
```bash
bun deploy-server:staging
```
--------------------------------
### Setting Custom Presence Channel
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/presence/index.mdx
Example of setting a custom 'status' channel to indicate a user is typing.
```js
// Set: replace semantics per channel
playhtml.presence.setMyPresence("status", { text: "typing" });
```
--------------------------------
### Get and Subscribe to Cursor Presences
Source: https://github.com/spencerc99/playhtml/blob/main/packages/common/CHANGELOG.md
Retrieve all cursor presences and subscribe to changes. The presences are keyed by a stable ID.
```typescript
const presences = playhtml.cursorClient.getCursorPresences();
const unsubscribe = playhtml.cursorClient.onCursorPresencesChange(
(presences) => {
// presences is Map
},
);
const identity = playhtml.cursorClient.getMyPlayerIdentity();
const stableId = identity.publicKey; // Persists across sessions
```
--------------------------------
### Initialize PlayProvider in App
Source: https://github.com/spencerc99/playhtml/blob/main/packages/react/README.md
Wrap your application with the PlayProvider component to initialize the playhtml client and set up the server connection. You can optionally provide initOptions for room and host configuration.
```tsx
import { PlayProvider } from "@playhtml/react";
export default function App() {
return (
{/* rest of your app... */}
);
}
```
--------------------------------
### Updating PlayHTMl Data
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/integrations/building-with-ai.md
Examples of updating data in PlayHTMl, including simple updates and array modifications using draft.js.
```javascript
- Simple: setData({ count: data.count + 1 })
- Arrays: setData((draft) => { draft.items.push(item) })
- LIMITATIONS: In mutator form, use splice() not shift()/pop()/[i]=value
```
--------------------------------
### Preview Production Build
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/README.md
Locally previews the production build of your site before deploying. This helps ensure that the deployed version will function as expected.
```bash
bun preview
```
--------------------------------
### Editable Content with Children
Source: https://github.com/spencerc99/playhtml/blob/main/website/test/playground.html
Indicates a section of content that is editable and can contain child elements. This setup is typically managed by a framework or library.
```html
CONTENT EDITABLE WITH CHILDREN
```
--------------------------------
### Initialize PlayHTML with Event Handlers
Source: https://github.com/spencerc99/playhtml/blob/main/website/test/shared-test-source.html
Initializes PlayHTML and sets up event handlers for dynamic discovery tests. Includes error handling for initialization failures.
```javascript
addSourceLog( "Dynamic discovery test handlers initialized", "discovery" );
} catch (error) {
console.error("๐ฏ Failed to initialize PlayHTML:", error);
}
```
--------------------------------
### Interactive Content Editable
Source: https://github.com/spencerc99/playhtml/blob/main/website/test/playground.html
Placeholder for content that can be edited directly. This example does not include specific JavaScript for interaction but indicates the element's capability.
```html
CONTENT EDITABLE
```
--------------------------------
### Playhtml Initialization (New Method)
Source: https://github.com/spencerc99/playhtml/blob/main/packages/playhtml/CHANGELOG.md
This snippet demonstrates the new explicit `playhtml.init()` call required for Playhtml versions 2.0.0 and above. It also shows how to optionally specify a room and host.
```html
```
--------------------------------
### Initialize PlayHTML with a Custom Host
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/reference/init-options.md
Specifies a custom PartyKit host for self-hosting the syncing server. This is recommended for enhanced control, custom server-side logic, or to meet data-residency requirements.
```javascript
playhtml.init({
host: "mypartykit.user.partykit.dev",
});
```
--------------------------------
### Use playhtml in React Application
Source: https://github.com/spencerc99/playhtml/blob/main/README.md
Integrate playhtml into your React application using the PlayProvider and CanToggleElement components. This example shows how to make an image toggleable.
```tsx
import { PlayProvider, CanToggleElement } from "@playhtml/react";
```
--------------------------------
### Get My Player Identity
Source: https://github.com/spencerc99/playhtml/blob/main/packages/react/CHANGELOG.md
Obtain the stable player identity, which includes a public key that persists across sessions. This is useful for correlating user data.
```typescript
const identity = playhtml.cursorClient.getMyPlayerIdentity();
const stableId = identity.publicKey; // Persists across sessions
```
--------------------------------
### Vanilla HTML Cursor Configuration
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/integrations/building-with-ai.md
Enable and configure cursors for real-time collaboration in vanilla HTML using playhtml.init().
```javascript
playhtml.init({ cursors: { enabled: true, room: "page" } })
```
--------------------------------
### Build Core Library Package
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Builds the core playhtml library package.
```bash
bun run -C packages/playhtml build
```
--------------------------------
### Vanilla HTML: Drop-in Script Initialization
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/getting-started.mdx
Use this method for the fastest integration without needing a build step or module syntax. Add the script tag at the end of your body to ensure interactive elements are present when playhtml initializes.
```html
```
--------------------------------
### Initialize playhtml with Vanilla HTML
Source: https://github.com/spencerc99/playhtml/blob/main/README.md
To use playhtml in a vanilla HTML project, include the script from a CDN and initialize playhtml. This enables features like 'can-toggle' on elements.
```html
```
--------------------------------
### Build All Library Packages
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Builds all library packages within the monorepo.
```bash
bun build-packages
```
--------------------------------
### React can-move Example
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/capabilities.mdx
Implements the `can-move` capability in React using the `CanMoveElement` component. It allows for draggable elements within defined boundaries, syncing their positions.
```tsx
import { CanMoveElement } from "@playhtml/react";
```
--------------------------------
### Playhtml Initialization (Old Method)
Source: https://github.com/spencerc99/playhtml/blob/main/packages/playhtml/CHANGELOG.md
This snippet shows the previous method of initializing Playhtml via a direct script import. Use this if you need to pin to a version 1.3.1 or earlier.
```html
```
--------------------------------
### Build React Bindings Package
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Builds the React wrapper components package for playhtml.
```bash
bun run -C packages/react build
```
--------------------------------
### Filter Visible Cursors with `shouldRenderCursor`
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/data/presence/cursors.md
Use the `shouldRenderCursor` function to control which cursors are displayed. This example renders only cursors from the same page, even when `room` is set to 'domain'.
```javascript
cursors: {
enabled: true,
room: "domain", // Connect everyone
shouldRenderCursor: (presence) => {
// Only render cursors from the same page
return presence.page === window.location.pathname;
}
}
```
--------------------------------
### React PlayProvider Initialization with Cursors
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/reference/init-options.md
Demonstrates how to initialize PlayHTML with cursor options within a React application using the PlayProvider component.
```tsx
import { PlayProvider } from "@playhtml/react";
{/* your app */}
;
```
--------------------------------
### Build Browser Extension
Source: https://github.com/spencerc99/playhtml/blob/main/CLAUDE.md
Builds the browser extension for Chrome.
```bash
bun build-extension
```
--------------------------------
### Vanilla HTML can-move Example
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/src/content/docs/capabilities.mdx
Demonstrates the `can-move` attribute for creating draggable elements within specified bounds. The `can-move-bounds` attribute defines the container for the draggable items.
```html
```
--------------------------------
### Initialize PlayHTML with Cursors
Source: https://github.com/spencerc99/playhtml/blob/main/claude-plugin/skills/building-playhtml-elements/SKILL.md
Enable and configure cursor synchronization for real-time presence indication. Specify the room scope ('page', 'domain', or 'section') for cursor data.
```javascript
playhtml.init({ cursors: { enabled: true, room: "page" } }); // "page"|"domain"|"section"
window.cursors.allColors.length; // user count
```
--------------------------------
### Recipe Folder Structure
Source: https://github.com/spencerc99/playhtml/blob/main/apps/docs/plans/live-editor.md
Illustrates the expected file structure for a single recipe within the project. Includes frontmatter, HTML entry, and optional React component.
```tree
recipes/
toggle-basic/
recipe.md # frontmatter + narrative body (MDX optional)
index.html # vanilla entry (required for MVP)
component.tsx # React entry (optional, future)
preview.png # static preview (optional; auto-generated fallback)
```