Skip to content

Concepts

Stageory is workspace software for staging businesses: projects, inventory, photos, clients, invoices. An app integration extends a workspace from the outside — reading workspace data through scoped APIs, mirroring content into destinations the customer authorizes, and contributing small pieces of UI to the surfaces customers already use.

Piece What it is
Catalog entry Your app’s listing: name, blurb, category, icon, the scopes it needs, and its UI contributions. Everything the store shows a customer before they install.
Installation A workspace’s copy of your app. Created on Install as pending_destination, flipped to active when a destination connects, soft-deleted on uninstall.
Destination Where your app writes — e.g. a Google Drive or Dropbox folder the customer authorizes via OAuth. Tokens are encrypted at rest and never reach your bundle.
Sync jobs The unit of background work. Enqueued by data-change events, the reconcile schedule, connect-time kickoff, or the customer’s “Sync now” — one queue, one worker, per-installation dedupe.
Extension bundle A single JavaScript file exporting your UI renderers. It runs in a Web Worker, not the page.
Activity events Feed rows your sync emits (“3 photos delivered · Photo Delivery”), attributed to your app — never to a person.

Every bundle — first-party included — runs under the same isolation rules. Nothing about the runtime changes when community bundles arrive; only the loader’s URL scheme widens.

  • No DOM, no credentials. Renderers run in a Worker and return plain-JSON component specs. All network access goes through api.get(), which the host executes page-side with the customer’s session against an allowlist — the worker never holds a token.
  • Structured clone only. Messages are data. Anything malformed counts as a crash.
  • Timeboxes. 100 ms soft budget per render (logged), 1 000 ms hard budget — then the worker is terminated and restarted with backoff.
  • Crash policy. Three strikes (crash, timeout, malformed message) within ten minutes disables your app’s UI for that session. Slots render an error glyph with a “re-enable in settings” tooltip instead of your contribution — never a broken page.
  • Size caps. ≤ 200 nodes and depth ≤ 8 per slot tree; ≤ 64 KB per response. Overflow fails that slot only.
  • Kill switch. Workspace owners can hide your app’s UI with one toggle, independent of uninstalling.

The corollary: a hanging or crashing integration degrades to a small glyph in its own slots. It cannot slow down, break, or restyle the page around it — and that guarantee is why integrations get to render inside the product at all.

Your code Runs Talks to
UI renderers (the bundle) Web Worker in the customer’s browser api.get() → host fetch proxy
Sync logic The platform’s integration runner (first-party today; hosted write-API planned) Scoped workspace APIs + the connected destination