huddlesDevelopersBack to the space

Put live huddles inside your platform.

One script and your people can talk, draw and go live without leaving your page — a notch-style bar that unfolds into the whole product. Your users never make a Huddles account: you vouch for them, or they walk in as visitors.

Your product
Main Space3 here · 1 huddle
huddles
Design crit4m
huddles
Voice, camera & screenWhiteboards & documents Go live to an audienceReactions & chat No account requiredThird-party-cookie proof

Who this is for: products with a community already on them — a course with classmates, a stream with viewers, a workspace with a team. The bar stays out of the way (your users drag it to any edge); the island holds the conversation at notch size; the full product is one press away, and only if you allow it.

Quickstart

Two lines on your page.

html
<script src="https://huddles.space/embed.js"></script>
<script>
  Huddles.init({
    embedder: 'your-app-id',
    // Minted by YOUR server — see Auth. Or omit entirely for walk-ins.
    getToken: () => fetch('/api/huddles-token').then(r => r.text()),
  });
</script>

Huddles.init also takes position: 'top-left' … 'bottom-right' (people can drag it anyway) and exposes Huddles.open(), Huddles.pop(), Huddles.close(), Huddles.move().

Auth, shape one: the platform vouches

Your user already logged in — to you. Making them log in again would be absurd, so your server mints a short-lived token that says who they are, signed with your app's secret. You never call our API to do it, and we never see your user database.

js — your server (any JWT library)
import { SignJWT } from 'jose';

const token = await new SignJWT({ name: user.displayName })
  .setProtectedHeader({ alg: 'HS256' })
  .setSubject(user.id)          // your id for them — any stable string
  .setIssuedAt()
  .setExpirationTime('5m')      // tokens are per page load, not per person
  .sign(new TextEncoder().encode(process.env.HUDDLES_APP_SECRET));
  • Identity is stable: we derive the Huddles user from (appId, sub), so the same person keeps their avatar, huddles and boards across visits. Rename them on your side and they rename here.
  • The token never rides a URL. The widget hands it to the iframe by postMessage; the iframe trades it for a session whose cookie is Partitioned — which is why this works in every browser that killed third-party cookies.
  • "Server" is generous — a Cloudflare Worker or Netlify function is plenty.

Auth, shape two: walk-ins

No backend, no tokens, no accounts anywhere: omit the token and every visitor gets an identity on the fly — a numbered name and an avatar, renameable from the bar. The stream-chat shape.

html
<script src="https://huddles.space/embed.js"></script>
<script>Huddles.init({ embedder: 'your-app-id' });</script>
Off by default, on deliberately. Walk-ins change who may exist: anyone who can load your page becomes a member of your space. Enable anonymous on the app when that is what you want; requests are rate-limited per IP, visitor identities live in the (partitioned) cookie — same browser, same visitor tomorrow; cleared cookie, new person.

The hybrid is the polished end state: start everyone as a walk-in, and once they log in to your platform, call Huddles.init with a real token — they become a stable person without losing the room they are standing in.

Feature shaping

You choose what your people experience. A feature turned off is an affordance that is not there — never a disabled button advertising something you decided against. Absent keys mean allowed.

KeyOff means
cameraVoice only — no camera verb, no tiles.
goLiveNo broadcasting from the island.
board / docNo whiteboard / document entries.
popOutIsland-only: voice and company, that is the room.
anonymous(Default) Only vouched-for users get in.

Shaping is a Premium feature of the app's space — see Limits.

The bar & the island

Three folds of one object. The bar (idle: your space, who is here, the visitor's own name; in a huddle: title and a speaking pulse; notices flash through it). The island — the huddle experience at notch size: tap a face and you are talking, mute, react, camera, leave, with the eq badge on whoever is speaking. The panel — the whole product, reached only by the person's press. One persistent iframe underneath, so folding never ends a conversation.

Your page can listen for nothing and send nothing: the widget is self-contained. State flows iframe → bar; the only inputs are the person's own presses.

Reference

EndpointWhat it does
GET /embed.jsThe widget. Cacheable, self-contained, ~6 KB.
GET /embed/:appIdThe app document — framable only by your registered origins.
POST /api/embed/session{ embedder, token } → partitioned session. 401 on a bad or expired token.
POST /api/embed/anon{ embedder } → visitor session. 403 unless anonymous is on. Rate-limited.
GET /api/embed/:appId/presence{ space, here, huddles } — counts, never a roster.
GET /api/embed/:appId/configThe resolved feature shaping.

Token claims

Claim
subRequired. Your stable id for the user (≤128 chars).
nameRequired. Display name (≤40 chars).
expRequired, ≤15 minutes out. Tokens are per page load.
avatarOptional: { type: 'grad', i: 0–11 }.

Limits & Premium

An embedded space is a space: the free limits exist here exactly as everywhere — huddles of 8 for 20 minutes, 3 boards and 3 documents, kept 7 days — until the app's space is on Premium, which lifts them for everyone in it and unlocks feature shaping. One plan, at the price you choose; billed to the space, never per seat and never per visitor.

Your apps

An app is an id (public — it rides the iframe URL), a secret (shown once, signs your tokens), the origins allowed to frame it, and the space it opens into. Any admin of a space can create one; revoking deletes the id on the spot.

Loading…

huddles.space · For Mac · Premium · Terms · Privacy · © 2026 Huddles.Space