interactive, collaborative html elements with a single data attribute
playhtml is a fast, small (~300KB), library-agnostic, and expressive library for magically creating collaborative interactive HTML elements that persist their state across sessions.
The simplest example is creating a shared, movable piece of HTML "furniture":
<div id="couch" can-move style="font-size: 80px">🛋</div>
At a glance, playhtml supports:
- reactive data scoped at a per-element level
- page-level shared data channels (not tied to elements)
- per-user presence with custom named channels
- sync and data persistence behavior customization (locally persisted, real-time synced, or globally persisted)
- custom events for imperative logic
- a range of magical plug-and-play and full customization
- sharing state across pages and domains
- (coming soon) a web component library for "plug-and-play" collaborative elements
- (coming soon) permissioning for behaviors
- (coming soon) triggering behavior on a schedule (think cron)
- (coming soon) custom data sources for long-term persistence
https://github.com/spencerc99/playhtml/assets/14796580/00e84e15-2c1c-4b4b-8e15-2af22f39db7a
playhtml is still in beta and active development. Join our Discord community to get help and show off what you've built!
Usage
Head to the proper section depending on your technology preference:
vanilla html / simple browser usage
To use this library, you can import the library from a CDN (in this case we will use unpkg.com). Please make sure to do this after all the HTML elements on the page and ensure that the HTML elements you are "magic-ifying" have an id set.
<body>
<!-- ... html elements here -->
<!-- valid example -->
<img
src="https://media2.giphy.com/media/lL7A3Li0YtFHq/giphy.gif?cid=ecf05e47ah89o71gzz7ke7inrgb1ai1xcbrjnqdf7o890118&ep=v1_stickers_search&rid=giphy.gif"
can-move
id="openSign"
/>
<!-- INVALID EXAMPLE <img src="https://media2.giphy.com/media/lL7A3Li0YtFHq/giphy.gif?cid=ecf05e47ah89o71gzz7ke7inrgb1ai1xcbrjnqdf7o890118&ep=v1_stickers_search&rid=giphy.gif" can-move /> -->
<!-- import the script -->
<!-- Option 1 (simplest, no customization) -->
<script
type="module"
src="https://unpkg.com/playhtml@latest/dist/init.es.js"
></script>
<!-- Option 2 (customize options to specify the room everyone connects to (a unique ID) or use your own partykit provider) -->
<script type="module">
import { playhtml } from "https://unpkg.com/playhtml@latest";
playhtml.init({
// room: "my-room", // if you want to specify a custom room to connect to
// host: `${myPartykitUser}.partykit.dev`, // if you want to specify a custom partykit host host to connect to
// cursors: {
// enabled: true, // if you want to eanble cursors
// },
});
</script>
</body>
If you have dynamic elements that are hydrated after the initial load, you can call playhtml.setupPlayElement(element) to imbue the element with playhtml properties.
<script type="module">
import { playhtml } from "https://unpkg.com/playhtml@latest";
const newPlayElement = document.createElement("div");
newPlayElement.id = "newPlayElement";
playhtml.setupPlayElement(newPlayElement);
</script>
eventing
You can set up imperative logic that doesn't depend on a data value changing (like triggering confetti when someone clicks in an area) by registering events with playhtml. You can either pass in a list of events when you call playhtml.init or you can call playhtml.registerPlayEventListener to register an event at any time.
https://github.com/spencerc99/playhtml/assets/14796580/bd8ecfaf-73ab-4aa2-9312-8917809f52a2