Skip to content

Tectly Editor Widget

The widget embeds our floor plan editor into your web page so your users can review and edit the geometry Tectly extracts. It renders as an iframe inside a container of your choice on your site.

The widget loads a single Tectly project. Whether to upload a floor plan to that project from your backend before mounting is up to you — users will land directly on the editor. Otherwise the widget prompts the user to upload a plan themselves.

Call widget.save() to persist the current state of the floor plan back to Tectly.

Installation

sh
npm i @tectly/widget

Or via CDN — the package exposes a TectlyWidget global:

html
<script src="https://unpkg.com/@tectly/widget"></script>

Quick start

html
<div id="tectly-container"></div>
ts
import { TectlyWidget } from "@tectly/widget";

const widget = new TectlyWidget({
  projectId: "my-project-id",
  token: "my-project-scoped-session-token",
});

widget.start("#tectly-container");

Authentication

The widget authenticates with a project-scoped session token that you can issue from your backend. Tokens are valid for 12 hours.

sh
curl -X POST https://platform.tectly.com/projects/{id}/issue-session-token \
    -H "Authorization: Bearer <your-account-token>"

WARNING

Never pass your account bearer token to the client. It can access every project in your account. Always issue a project-scoped session token server-side.

Integration flow

Configuration

OptionTypeRequiredDescription
projectIdstringYesThe id of the project to load.
tokenstringYesA project-scoped session token. See Authentication.
environmentUrlstringNoThe Tectly environment. Defaults to https://sandbox.platform.tectly.com. Use https://platform.tectly.com for production.
originstringNoOverride the parent origin used to validate postMessage traffic. Defaults to window.location.origin; only set this if the parent's effective origin differs (e.g. nested iframes or a reverse proxy).

API

  • start(container: string | HTMLElement) — mount the editor iframe into container, given as a CSS selector or DOM element. Calling start() twice on the same instance is a no-op and logs a warning.
  • destroy() — remove the iframe, tear down the message bridge, and clear all event listeners.
  • save() — ask the editor to persist the current floor plan. Resolves via the saved event; only call once connected has fired.
  • on(event, callback) / off(event, callback) — subscribe or unsubscribe from events.

You can mount multiple widget instances on the same page — each owns its own iframe and message channel.

Events

EventPayloadDescription
connectedThe editor has loaded and is ready to receive commands.
saved{ success: boolean }Emitted after a save() call completes.
ts
widget.on("connected", () => console.log("Editor ready."));
widget.on(
  "saved",
  ({ success }) => success && console.log("Floor plan saved."),
);

TypeScript

The package ships its own type definitions. The full public surface:

ts
type EventCallback = (...args: any[]) => void;

interface TectlyWidgetOptions {
  projectId: string;
  token: string;
  environmentUrl?: string;
  origin?: string;
}

class TectlyWidget {
  constructor(options: TectlyWidgetOptions);
  start(container: string | HTMLElement): void;
  destroy(): void;
  save(): void;
  on(event: string, callback: EventCallback): void;
  off(event: string, callback: EventCallback): void;
}

Framework examples

ts
import { TectlyWidget } from "@tectly/widget";

const widget = new TectlyWidget({
  projectId: "my-project-id",
  token: "my-project-scoped-session-token",
});

widget.start("#tectly-container");

document
  .querySelector("#save-button")
  ?.addEventListener("click", () => widget.save());