Skip to content

Embedded Designer

Let organizers create and edit charts inside your product with workspace-scoped, reviewable browser sessions.

Updated View as Markdown

Embed the full SeatLayer Designer in your CMS without creating a SeatLayer login for every organizer. Your server owns tenancy and mints a short-lived session; the SDK owns iframe lifecycle and message validation.

End-to-end flow

  1. Create or select a chart in the organizer workspace.
  2. Authorize the current host user and decide their Designer authority.
  3. Mint a dse_… session from your backend.
  4. Mount the returned designerUrl.
  5. React to saved, published, close, and error events.
  6. Replace the session before or after expiry.
  7. Revoke it when access ends.

Mint from the server

server/designer-session.tsts
export async function createDesignerSession(input: {
  workspaceId: string;
  chartId: string;
  allowedOrigin: string;
}) {
  const response = await fetch(
    "https://api.seatlayer.io/v1/designer/sessions",
    {
      method: "POST",
      headers: {
        authorization: `Bearer ${process.env.SEATLAYER_SECRET_KEY}`,
        "content-type": "application/json",
      },
      body: JSON.stringify({
        ...input,
        authority: "edit",
        mode: "safe",
        expiresInSeconds: 3600,
      }),
    },
  );

  if (!response.ok) throw new Error("Unable to open Designer");
  return response.json();
}

Use read-only for review, edit for draft work, or publish only when the host user is allowed to release a chart. Safe mode is a useful default for delegated venue editors.

Mount with JavaScript

browser/designer.jsjs
import { EmbeddedDesigner } from "@seatlayer/js";

let editor;

async function mountDesigner() {
  const { session } = await fetch("/api/designer-session", {
    method: "POST",
  }).then((response) => response.json());

  editor = new EmbeddedDesigner({
    container: "#designer",
    designerUrl: session.designerUrl,
    expectedChartId: session.chartId,
    expectedWorkspaceId: session.workspaceId,
    height: "fill",
    minHeight: 560,
    showLoadingState: true,
    onReady: () => markEditorReady(),
    onSaved: (message) => saveHostRevision(message.chartId),
    onPublished: (message) => refreshChart(message.chartId),
    onClose: () => closeEditor(),
    onError: (message) => reportSafeError(message.code),
    onRequestRelaunch: async () => {
      const next = await fetch("/api/designer-session", {
        method: "POST",
      }).then((response) => response.json());
      editor.setDesignerUrl(next.session.designerUrl);
    },
  });

  editor.mount();
}

height: "fill" detects whether the container has a definite height. It fills that box or uses the remaining viewport height, with a minimum of 480 by default. A numeric height opts into fixed-pixel behavior and legacy resize messages.

React

components/VenueEditor.tsxtsx
import { EmbeddedDesigner } from "@seatlayer/react";

export function VenueEditor({ session, relaunch }) {
  return (
    <EmbeddedDesigner
      designerUrl={session.designerUrl}
      expectedChartId={session.chartId}
      expectedWorkspaceId={session.workspaceId}
      onSaved={({ chartId }) => refreshVenue(chartId)}
      onPublished={({ chartId }) => activateRevision(chartId)}
      onRequestRelaunch={relaunch}
    />
  );
}

Message safety

The SDK accepts only documented seatlayer.designer.* messages from the exact iframe window and Designer origin. expectedChartId and expectedWorkspaceId add host-side resource checks.

Event Host response
ready Remove outer loading state
saved Update host draft status
published Refresh event/chart state and show release result
close Navigate away or collapse editor
error Show safe recovery UI; do not expose raw tokens

Do not build business logic from the legacy resize message.

Session replacement

The SDK can proactively relaunch when onRequestRelaunch exists. It uses the session expiry received from the iframe and replaces the iframe with the new fragment URL. A slept device that wakes after expiry gets one automatic recovery attempt before the error card appears.

Call destroy() when the host unmounts the editor.

Publication behavior

Publishing updates the chart. Existing events are separately protected: pristine events may auto-refresh; events with inventory state can require an explicit map update, and an update fails if booked or held labels would vanish. Surface this result to the organizer.

Verification

  • The secret key is never present in browser code or network responses.
  • Workspace and chart ownership are checked before minting.
  • Origin matching is exact in production.
  • Authority matches the host user’s role.
  • Safe mode and feature policy match the editing job.
  • Save, publish, close, expiry, relaunch, and revoke flows are tested.
  • The container works at narrow widths and has a usable minimum height.
  • Host code destroys the embed during teardown.

See embed sessions, publishing and versioning, and Designer MCP.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close