Embedding & white-labelling
Orvanta’s editing surfaces — the script editor, the flow builder, the run viewers — can be embedded inside your own application and presented as part of your product rather than as Orvanta. Your users build and run automations without ever seeing a second brand or a second login.
This page covers the React path, which is the supported one today.
What you can embed
Section titled “What you can embed”Nine components ship in the React SDK:
| Component | What it is |
|---|---|
ScriptEditor | The bare code pane — Monaco, with Orvanta’s language support and completions. |
SchemaEditor | The argument-schema editor for a script or flow. |
ResourceEditor | The form for creating or editing a resource. |
ScriptBuilder | The full script surface: code, metadata, triggers, settings, history, deploy. |
FlowBuilder | The full flow surface: the graph, step configuration, triggers, settings, deploy. |
FlowViewer | A read-only view of a flow, with its graph, summary and inputs. |
FlowStatusViewer | A live view of one run, streaming updates over SSE. |
FlowHistory | The version history of a flow, optionally with restore. |
OrvantaProvider | Not a visual component — the wrapper that points the others at your Orvanta instance. |
Note the distinction between ScriptEditor and ScriptBuilder: the first is
just the code pane, the second is the whole authoring experience. Most
integrations want one or the other, not both.
Availability
Section titled “Availability”The SDK ships as two npm packages, both published to GitHub Packages at
version 3.3.0:
@orvanta-cloud/orvanta-components— the prebundled Svelte components@orvanta-cloud/orvanta-react-sdk— the React wrappers around them
They always ship together on the same version.
Requirements
Section titled “Requirements”- React 17, 18 or 19.
reactandreact-domare peer dependencies. - Node 18 or newer to build.
- No Svelte toolchain. Orvanta’s components are written in Svelte, but they ship precompiled with their own Svelte runtime bundled in. You do not need a Svelte compiler, loader or plugin in your build. A plain Create React App + webpack project works.
Installing
Section titled “Installing”Both packages are private on GitHub Packages, so npm needs two things: where the
@orvanta-cloud scope resolves, and a token allowed to read it. Both are
required — the scope line alone gets you a 401.
In your project’s .npmrc:
@orvanta-cloud:registry=https://npm.pkg.github.com//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}Export NODE_AUTH_TOKEN as a GitHub token with the read:packages scope, then:
npm install @orvanta-cloud/orvanta-react-sdk @orvanta-cloud/orvanta-componentsWrite the token as ${NODE_AUTH_TOKEN} rather than pasting its value — npm
expands environment variables in .npmrc, so the file stays safe to commit and
your CI supplies the token as a secret. Your build system needs the same
variable set, or npm ci will fail there even though it works on your machine.
Install both packages explicitly. The components package is declared as an optional peer of the React SDK, so npm will not pull it in for you — see One copy of the components package below, which is the most important thing on this page.
A minimal integration
Section titled “A minimal integration”import * as orvanta from '@orvanta-cloud/orvanta-components'import { OrvantaProvider, setOrvantaComponents, ScriptEditor } from '@orvanta-cloud/orvanta-react-sdk'import '@orvanta-cloud/orvanta-react-sdk/styles'
// Once, at application startup.setOrvantaComponents(orvanta)
export function App({ token }) { return ( <OrvantaProvider components={orvanta} baseUrl="https://your-instance.example.com/api" token={token} workspace="acme" > <div style={{ height: '80vh' }}> <ScriptEditor path="u/admin/my-script" lang="python3" code={initialCode} onChange={(code, schema) => save(code, schema)} /> </div> </OrvantaProvider> )}<OrvantaProvider> takes baseUrl, token (a bearer token, or a getter —
prefer a plain string, because the run stream and the file uploader need it
synchronously), credentials, workspace, and customIcon. Changing
workspace performs a real workspace switch, not just an assignment.
Three things catch people out on the first attempt:
- Give the container an explicit height. Every component fills its parent
(
height: 100%), because the code editor and the split-pane layouts measure the box they are given. Dropped into an auto-height container, they collapse to nothing. - Content props are uncontrolled.
code,schema,pathand a builder’smodeare read once, when the component mounts. This is deliberate — it lets you feedonChangestraight back into your own state without fighting the user’s cursor. To load a different script or flow, change React’skeyand let the component remount. - One configuration per page. The components share a single API client, so two providers configure the same thing and the last one wins. Nesting providers that agree is fine and stays silent; development builds warn when two of them genuinely disagree. A single page cannot show two workspaces at once.
White-labelling
Section titled “White-labelling”Three independent levers, which you can use in any combination.
1. Hide the parts you do not want
Section titled “1. Hide the parts you do not want”Every builder and editor accepts a customUi object that switches individual
pieces of the interface off — top-bar actions, settings tabs, graph controls,
metadata fields, the AI builder, tutorials, and so on. Everything defaults to
visible, so you only name what you are removing.
import { useMemo } from 'react'
const customUi = useMemo(() => ({ topBar: { tutorials: false, aiBuilder: false }, settingsPanel: { metadata: { path: false } }}), [])
<FlowBuilder mode={{ type: 'edit', path }} flow={loaded} customUi={customUi} />Memoize it. customUi is an object, so a fresh literal on every render
re-runs work inside the embedded component. Development builds warn if you
forget.
Full TypeScript types for the whole customUi family are exported from the
package root, so your editor will complete the available fields.
2. Replace the logo
Section titled “2. Replace the logo”customIcon.normal = 'https://example.com/logo.svg'customIcon.white = 'https://example.com/logo-white.svg'or, equivalently, pass customIcon={{ normal, white }} to <OrvantaProvider>.
3. Choose how much of Orvanta’s CSS you take
Section titled “3. Choose how much of Orvanta’s CSS you take”import '@orvanta-cloud/orvanta-react-sdk/styles' // alwaysimport '@orvanta-cloud/orvanta-react-sdk/styles/preflight' // opt-in-
/stylesis required. It carries the component styling plus the vendor CSS the code editor and data grid need for their own furniture. Without it the editor renders without its scrollbars, gutters and menus. -
/styles/preflightis optional, and this is the real white-labelling decision. It is a global CSS reset. With it, the components are guaranteed to look exactly as designed — but it also restyles your headings, lists, buttons and form controls, because a global reset is global.Leaving it out is the supported “blend into my design system” mode. Everything still works, and any element the components do not style explicitly inherits your defaults instead of a blank slate. If your application already has its own design system, start without preflight.
Orvanta’s own rules are wrapped in a CSS cascade layer, so your unlayered styles
win over them regardless of specificity. You do not need !important to
override Orvanta’s look.
One copy of the components package
Section titled “One copy of the components package”The single most important operational detail, because the failure it causes is invisible at install time.
@orvanta-cloud/orvanta-components bundles its own copy of the Svelte runtime.
There must be exactly one copy of that package in your dependency tree. Two
copies do not share the internal state that Svelte’s reactivity depends on, and
the result is not a crash: the application installs cleanly, builds cleanly, and
the embedded components simply stop updating when data changes.
To make that failure impossible to reach silently, the React SDK declares the
components package as a peer dependency rather than a normal dependency. A
normal dependency would let npm resolve a version conflict by quietly nesting a
second copy inside the SDK’s own node_modules. A peer dependency turns the same
conflict into a message npm shows you at install time, while you can still fix
it.
Practically, this means:
- Install
@orvanta-cloud/orvanta-componentsyourself, as a direct dependency. - Keep it at the version the SDK’s peer range names — the two ship together on the same release, and the pin is exact.
- If npm reports a peer conflict, resolve it. Do not force past it with
--legacy-peer-deps; that reinstates exactly the silent-nesting failure the peer edge exists to prevent.
It is marked optional so that npm does not download the (large) components bundle for an integration that does not need any of the visual components. That flag is about installation, not runtime: if a visual component mounts without the components package having been registered, the SDK raises a clear, named error rather than failing obscurely.
A correct install looks like this — note deduped, and that the SDK has no
nested copy of its own:
├── @orvanta-cloud/orvanta-components@3.3.0├─┬ @orvanta-cloud/orvanta-react-sdk@3.3.0│ ├── @orvanta-cloud/orvanta-components@3.3.0 deduped│ └── react@17.0.2 deduped└── react@17.0.2Run npm ls @orvanta-cloud/orvanta-components after installing. One line, or a
line plus deduped, is what you want. Two different versions listed at two
different depths is the failure described above — fix it before you build.
Authentication and run streaming
Section titled “Authentication and run streaming”<OrvantaProvider token> supplies the bearer token every embedded component
uses. It also reaches the live run stream: FlowStatusViewer subscribes over
Server-Sent Events, and because EventSource cannot send headers, the token
travels as a query parameter. Rotating the token reaches the next connection
without remounting the viewer, which matters — remounting a status viewer drops
the stream and the run state it has accumulated.
With no token configured, the components fall back to the session cookie, which is what you want if your application and your Orvanta instance share an origin and a session.
Languages
Section titled “Languages”ScriptEditor and ScriptBuilder accept any language the Orvanta instance
supports, named by its wire identifier — python3, go, bash, powershell,
php, rust, java, kotlin, dart, csharp, ruby, groovy, nu,
rlang, ansible, the SQL dialects (postgresql, mysql, mssql,
oracledb, bigquery, snowflake, duckdb), mongodb, graphql, and the
JavaScript/TypeScript runtimes.
The JS/TS runtimes are named bun, bunnative, deno and nativets — there
is no node or nodejs identifier. The TypeScript type for this field is left
open deliberately, so a language added to a newer Orvanta release is not a
compile error in your application before you upgrade the SDK.
Getting help
Section titled “Getting help”For access to the packages, a scoped evaluation, or questions about what a particular integration needs, contact sales@orvanta.cloud.