---
title: Deploying Resources
description: How to deploy your Elevasis SDK resources to the platform using elevasis-sdk deploy, including configuration, validation, and environment setup
---

Deploying your resources makes them live on the Elevasis platform and immediately available for execution. The deploy process validates your resource definitions, bundles your code into a single self-contained file, and uploads it to the platform -- no server-side dependency installation required.

---

## How Deployment Works

When you run `elevasis-sdk deploy`, the CLI performs these steps in order:

1. **Preflight** -- verifies a `.elevasis` marker is reachable from the current directory, that `.env` exists at the project root, and that `ELEVASIS_PLATFORM_KEY` is set. Fails before any side effect if any check fails.
2. **Authenticate** -- calls the API with your `ELEVASIS_PLATFORM_KEY` to verify credentials and resolve your organization name
3. **Validate** -- runs your `src/index.ts` through `ResourceRegistry`, catching the same errors as the platform
4. **Bundle** -- uses esbuild to produce a single self-contained `dist/bundle.js` file (~50-200 KB) containing your code and all dependencies
5. **Upload** -- sends the bundle and resource metadata to the platform via `POST /api/external/deploy`
6. **Go live** -- the platform registers your resources; they are immediately available for execution

There is no local dev server and no separate staging environment. Deployed resources run directly on the platform. Local testing uses `tsc --noEmit` and Vitest with direct handler calls.

---

## Invocation CWD

`elevasis-sdk` is valid from **any subdirectory inside a valid project**. Two separate anchors govern path resolution:

- **Preflight / auth / env** -- anchors on the `.elevasis` project root, found by walking up from the invocation directory. If no `.elevasis` marker is reachable, the CLI exits non-zero before running the command.
- **Build commands** (`deploy`, `check`) -- anchor on the **nearest `package.json`** (the package root). Bundle outputs land in that package's `dist/`, not the project root. The default entry point (`./src/index.ts`) also resolves from the package root.

**Single-package project** (e.g. `external/acme/`): both anchors resolve to the same directory. Invoke from anywhere inside the project tree.

**Multi-package workspace** (e.g. `external/_template/` with `operations/` as a sub-package):

```bash
# Invoke from operations/ or any subdir inside it
pnpm -C external/_template/operations exec elevasis-sdk deploy

# Both CWDs work identically:
#   .elevasis root  -> external/_template/            (auth / .env)
#   package root    -> external/_template/operations/  (bundle, dist/)
#   bundle output   -> external/_template/operations/dist/bundle.js
```

Each package in a workspace produces its own `dist/bundle.js` when deployed. Run `elevasis-sdk deploy` from within each package separately.

**Running outside a valid project** produces a hard failure before any network call:

```
Not inside an Elevasis project. Run from a directory under one containing `.elevasis`.
```

The only commands that bypass preflight are `--help` / `-h` / `--version` / `-V`.

---

## Running a Deploy

```bash
elevasis-sdk deploy
```

**Successful deploy output:**

```
  Authenticating...          done (acme-corp)
  Validating...              done (4 resources, 0 errors)
  Bundling...                done (142 KB)
  Uploading...               done

  Deployed! 4 resources live.
  Version:  v1.0.0
  Duration: 4.2s
```

Each deploy creates a new deployment record. The previous active deployment is automatically stopped. You can view all deployments with `elevasis-sdk deployments`.

---

## Validation

The CLI validates your resources before bundling. Validation uses the same `ResourceRegistry` as the platform, so errors caught locally are the same errors that would be caught at deploy time.

**Validation checks:**

- Duplicate `resourceId` within your organization
- Invalid model configuration (temperature and token bounds out of range)
- `ExecutionInterface` form fields not matching `inputSchema`
- Broken workflow step chains (`next` referencing a step that does not exist)
- Relationship declarations referencing resources that do not exist

**Validation failure output:**

```
  Authenticating...          done (acme-corp)
  Validating...
    ERROR  Duplicate resource ID 'onboard-client' in organization 'Acme Corp'

  Deploy aborted.
```

Run `elevasis-sdk check` at any time to validate without deploying.

---

## Configuration

The CLI reads `elevasis.config.ts` from your project root. All fields are optional -- the organization name is resolved from your API key, not from config.

```typescript
// elevasis.config.ts
import type { ElevasConfig } from '@elevasis/sdk'

export default {} satisfies ElevasConfig
```

The `ElevasConfig` type is exported from `@elevasis/sdk`. You can leave the config empty or extend it as options are added in future SDK versions.

---

## Environment Variables

| Variable                | Required | Description                                                                 |
| ----------------------- | -------- | --------------------------------------------------------------------------- |
| `ELEVASIS_PLATFORM_KEY` | Yes      | Your `sk_...` API key. Used for authentication and organization resolution. |
| `ELEVASIS_API_URL`      | No       | Override the API base URL. Useful for pointing at a staging environment.    |

The CLI also accepts a `--api-url` flag on every command, which takes priority over `ELEVASIS_API_URL`.

**API URL resolution order:**

1. `--api-url` flag (highest priority)
2. `--prod` flag (forces production URL, overrides `NODE_ENV=development`)
3. `ELEVASIS_API_URL` environment variable
4. `NODE_ENV`-based default (production: `https://api.elevasis.io`, development: localhost)

**Setting `ELEVASIS_PLATFORM_KEY` via `.env` file:**

```
ELEVASIS_PLATFORM_KEY=sk_***
```

Place `.env` in your project root (the directory containing `.elevasis`). The CLI walks up directories to find both the `.elevasis` marker and the `.env` file, so running from subdirectories like `operations/` works automatically. Never commit this file.

---

## Deployment Lifecycle

Each call to `elevasis-sdk deploy` creates a new deployment. The platform tracks all deployments for your organization.

| Status      | Meaning                                                      |
| ----------- | ------------------------------------------------------------ |
| `deploying` | Bundle is being processed and resources are being registered |
| `active`    | Resources are live and available for execution               |
| `stopped`   | Superseded by a newer deployment                             |
| `failed`    | Deploy did not complete (validation or bundle error)         |

Only one deployment can be `active` at a time. Deploying again automatically moves the previous active deployment to `stopped`.

**View deployment history:**

```bash
elevasis-sdk deployments
```

```
  deploy_abc123   active    2026-02-25 14:00:00   4 resources
  deploy_abc122   stopped   2026-02-24 09:30:00   3 resources
  deploy_abc121   stopped   2026-02-23 11:15:00   3 resources
```

---

## Bundle Details

The deploy bundle is a single CJS file produced by esbuild. It includes:

- Your resource definitions from `src/index.ts`
- The `@elevasis/sdk/worker` runtime that handles execution messages from the platform
- All your npm dependencies (fully self-contained, no `node_modules` needed on the server)

The bundle is stored on the platform for durability and restart recovery. If the platform API restarts, it re-downloads your bundle and re-registers your resources automatically -- no action required on your part.

---

## Provided Features

The SDK includes more than workflow execution. The published `@elevasis/ui` package provides system manifests, pages, hooks, and headless provider exports for building shell-aware applications.

### Shared Shell Contract

`ElevasisSystemsProvider` reads the canonical `OrganizationModel`, including `navigation.sidebar`, and exposes a shell model plus sidebar projection helpers. System manifests provide implementation hooks such as icons and subshell sidebars; they do not own structural navigation.

```tsx
import { Outlet } from '@tanstack/react-router'
import { ElevasisSystemsProvider, SystemShell } from '@elevasis/ui/provider'
import { leadGenManifest } from '@elevasis/ui/features/lead-gen'
import { crmManifest } from '@elevasis/ui/features/crm'
import { deliveryManifest } from '@elevasis/ui/features/delivery'
import { monitoringManifest } from '@elevasis/ui/features/monitoring'
import { settingsManifest } from '@elevasis/ui/features/settings'
import { canonicalOrganizationModel } from '@core/config/organization-model'

const systems = [
  leadGenManifest,
  crmManifest,
  deliveryManifest,
  monitoringManifest,
  settingsManifest
]

export function AppShell() {
  return (
    <ElevasisSystemsProvider systems={systems} organizationModel={canonicalOrganizationModel}>
      <SystemShell>
        <Outlet />
      </SystemShell>
    </ElevasisSystemsProvider>
  )
}
```

Host apps still own TanStack route registration, topbar behavior, branding, auth wiring, and any root dashboard composition.

### Contract Matrix

| Contract type                           | What is published                                                                           | Current examples                                               |
| --------------------------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| Manifest-backed shared subshell systems | System manifest plus shared sidebar/pages, mounted through `@elevasis/ui/provider`          | Lead Gen, CRM, Projects, Operations                            |
| Shared feature pages and hooks          | Pages, hooks, and helpers that can be composed inside host routes                           | Monitoring, Settings, Dashboard widgets                        |
| Headless provider contract              | Provider, hooks, and shell model helpers                                                    | `ElevasisSystemsProvider`, `useElevasisSystems`, `SystemShell` |
| Compatibility barrel                    | Existing imports remain available while newer integrations prefer feature/provider subpaths | `@elevasis/ui/components`                                      |

### System Map

| System     | Primary route space | Shared UI surface                                                  | Best SDK entry point                                                                      |
| ---------- | ------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
| Lead Gen   | `/lead-gen/*`       | Lead Gen pages, sidebars, list detail page, run dialogs            | `@elevasis/ui/features/lead-gen`, `@elevasis/ui/hooks`, `@elevasis/sdk/worker`            |
| CRM        | `/crm/*`            | CRM sidebar, overview widgets, deal/detail pages, workbench panels | `@elevasis/ui/features/crm`, `@elevasis/ui/hooks`, `@elevasis/sdk/worker`                 |
| Projects   | `/projects/*`       | Projects list page, milestones/tasks/notes sidebars and pages      | `@elevasis/ui/features/delivery`, `@elevasis/ui/hooks/delivery`, `elevasis-sdk project:*` |
| Operations | `/operations/*`     | Command View, resources, organization graph, sessions              | `@elevasis/ui/features/operations`                                                        |
| Dashboard  | `/` host-owned      | Dashboard and overview components only                             | `@elevasis/ui/features/dashboard`                                                         |
| Monitoring | `/monitoring/*`     | Monitoring pages/components                                        | `@elevasis/ui/features/monitoring`                                                        |
| Settings   | `/settings/*`       | Settings/account/org components                                    | `@elevasis/ui/features/settings`                                                          |

### Organization Model Alignment

Manifest `systemId` values must match Organization Model System IDs. Sidebar placement is authored in the Organization Model navigation domain:

```ts
systems: {
  dashboard: { id: 'dashboard', order: 10, label: 'Dashboard', lifecycle: 'active' },
  clients: { id: 'clients', order: 20, label: 'Clients', lifecycle: 'active' }
},
navigation: {
  sidebar: {
    primary: {
      dashboard: { type: 'surface', order: 10, label: 'Dashboard', path: '/', surfaceType: 'dashboard', targets: { systems: ['dashboard'] } },
      business: {
        type: 'group',
        order: 20,
        label: 'Business',
        children: {
          clients: { type: 'surface', order: 20, label: 'Clients', path: '/clients', surfaceType: 'list', targets: { systems: ['clients'] } }
        }
      }
    },
    bottom: {}
  }
}
```

Dashboard appears before Business in the primary sidebar. Business is a navigation group only; `/clients` is the canonical client route.

### Choosing the Right Surface

- Need packaged sidebar/page composition? Use `ElevasisSystemsProvider`, `SystemShell`, and manifests from `@elevasis/ui/features/*`.
- Need a root dashboard? Keep that route host-owned and compose dashboard components.
- Need list-scoped lead-gen runtime behavior? Use the `list` adapter, then `acqDb` for broader acquisition CRUD.
- Need project/task automation? Use `elevasis-sdk project:*`.

---

## Documentation

- [Command Center](command-center.mdx) - Resource graph, relationships, node types, and post-deployment UI reference
- [Execution Reference](execution-reference.mdx) - REST endpoints for executing resources, managing deployments, and React UI components for custom Run dialogs
- [Platform Adapters](../platform-tools/adapters-platform.mdx) - `approval.create()` and all platform service adapters
