Hosted vs local

When you finish this page you can say, for any piece of Sorb™, whether it runs on your machine or on Sorb Cloud, and what — if anything — that piece sends off your machine. You need to have read Getting started once; nothing here is setup.

The short answer

sorb-juice — the bridge — is the same binary either way. Run it yourself with sorb dev and it is the local loop: single-tenant, no account, nothing leaves your machine except what a Figma plugin you are running locally sends to 127.0.0.1. Point the plugin or the React SDK at bridge.sorbcloud.com instead and the identical bridge code runs multi-tenant behind Sorb Cloud's auth and storage — the hosted platform. Nothing about the endpoint paths changes between the two; only whether a database URL is configured on the process you're talking to.

What runs where

LOCAL LOOP (free, single-tenant)                 HOSTED PLATFORM (Sorb Cloud)
─────────────────────────────────                ─────────────────────────────
Figma plugin (Canopy)                             Figma plugin (Canopy)
  │ POST /preview, GET /artifacts                   │ POST /preview, GET /artifacts
  ▼                                                  ▼  (Bearer <key>)
sorb dev — on YOUR machine                        bridge.sorbcloud.com — sorb-juice,
  127.0.0.1:7777, no auth                            hosted mode, key-authenticated
  reads sorb.config.json,                            reads/writes org + project data
  .sorb/resolved.json on disk                        in Postgres, preview payloads in
  │                                                   Redis (TTL, see below)
  ▼                                                  │
Your React app (@sorb/leaf)                         ▼
  applies CSS vars, polls the                      app.sorbcloud.com — sorb-cloud
  local bridge over loopback                         (accounts, orgs, projects, keys,
                                                       billing)
                                                     │
                                                     ▼
                                                     Your React app (@sorb/leaf)
                                                     applies CSS vars, polls the
                                                     hosted bridge over HTTPS

Both loops run the identical @sorb/leaf SDK in your app and the identical sorb-juice bridge code. The only thing that changes is which process answers POST /preview and whether that process was started with a database configured.

What leaves your machine

Local loopHosted platform
Runs onYour machine (sorb dev, 127.0.0.1:7777)bridge.sorbcloud.com + app.sorbcloud.com
AuthNone — anything that can reach the port can call itEvery request carries an API key or a signed-in session
Token values, preview payloadsNever leave your machineSent to the hosted bridge over HTTPS; held in Redis, TTL 24h on the free plan
Org/project/account dataDoesn't exist — there's no accountStored in Postgres by sorb-cloud (orgs, projects, members, API keys)
Figma plugin trafficLoopback onlyHTTPS to bridge.sorbcloud.com, key-authenticated
CostFree, no accountFree during the public beta — see Cloud & accounts

The bridge itself decides which mode it's in with a single switch: hosted mode turns on when the process it's running as has a database URL configured, and that gate controls auth, entitlement checks, and CORS — no route ever moves between the two modes.

Which key type does what

The hosted bridge and app.sorbcloud.com authenticate every request with an API key issued from your org's dashboard. There are two types, and the type — not any setting you choose — determines what the key can do:

Key typePrefixScopeUse it for
Publishablesorb_pk_Read-onlyEverything the Figma plugin gets on sign-in pairing today: reading tokens, opening and editing previews, and the plugin's "Save to project" publish; the React SDK reading resolved tokens and previews; anywhere a key might end up visible client-side
Secret(shown once at creation, never printed again)Read-writeServer-side or CI writes — opening a token PR, and any call the bridge write-gates (POST /verify, POST /tokens/figma)

A publishable key is read-only by design — scope is derived directly from the key's type, publishable always maps to read, secret always maps to write, and there is no setting on a key that overrides it. POST /verify and POST /tokens/figma on the bridge both fail closed with a 403 on a publishable key rather than silently upgrading it — see Troubleshooting for what that looks like and how to fix it. One deliberate, bounded exception today: the cloud's "Save to project" publish route accepts a publishable key too, because that's what plugin pairing currently issues — it can only overwrite the project that key already belongs to, never another one.

What stays true either way

  • Your tokens/*.json and the generated .sorb/resolved.json live in your repo in both modes — the bridge reads them off disk locally, and the hosted platform only ever sees the values you explicitly publish or preview.
  • The vocabulary guard, the sanitizer, and the banner states in @sorb/leaf run identically against either bridge — the SDK doesn't know or care which mode answered its request.
  • Switching from local to hosted (or back) is a config change — the preview.origin your app points at and the key you configure — not a code change.

Next

Works with Figma. Not affiliated with, or endorsed by, Figma. Figma is a trademark of Figma, Inc.