Configuration files
The CLI reads two files from your app's working directory.
orion.config.ts
CLI configuration. Generated by orion init and edited by orion config host / orion config sandbox. Keep the shape simple and use string literals only — the CLI reads the file directly at startup, so imports, computed values, and other dynamic TypeScript expressions won't be picked up.
/**
* Orion App Configuration
*
* This file is auto-generated by the Orion CLI.
* - `host` is the developer's home tenant URL — used by login + publish.
* Set via `orion config host`.
* - `sandboxUrl` is the scratch tenant for `orion dev` tunnels only.
* Set via `orion config sandbox`.
*/
export default {
clientId: '<your-client-id>',
host: 'https://your-tenant.staging.orionsoftware.io',
sandboxUrl: 'https://sandbox-acmemedical.orion.local',
tenantUuid: '<your-tenant-uuid>',
app: {
name: 'my-app',
slug: 'my-app',
},
};Fields
| Field | Required | Source of truth |
|---|---|---|
clientId | yes | Set at orion init --client-id <id>. The OAuth client your developer-portal admin created for this app. |
host | for login + publish + reads | Set via orion config host. Your home tenant URL. See Host vs Sandbox. |
sandboxUrl | for orion dev only | Set via orion config sandbox. Optional otherwise. |
tenantUuid | filled automatically | Fetched from the configured host/sandbox by orion config host and orion config sandbox. Empty after orion init; don't hand-edit. |
app.name / app.slug | yes | Set at orion init <name>. The slug becomes the URL/CLI identifier (orion apps info <slug>). |
Don't commit secrets
orion.config.ts itself contains no secrets — clientId and tenantUuid are public IDs. Tokens live separately in your platform's Conf directory (~/Library/Preferences/orion-cli-nodejs/ on macOS).
orion publish excludes orion.config.ts from the source archive anyway, since it's a developer-machine artifact, not part of the app.
orion-app.json
The marketplace manifest. Owns app metadata, scope declarations, and extension catalogs.
{
"name": "My App",
"slug": "my-app",
"version": "1.0.0",
"sdkVersion": "1.1.0",
"description": "Short marketplace listing copy.",
"scope": [
"user/Patient.read",
"user/ActivityDefinition.read"
],
"entryPoint": "./src/main.tsx",
"extensions": {
"navigation": [
{
"id": "home",
"title": "Home",
"icon": "Activity",
"placement": "sidebar",
"target": "/home"
}
],
"pages": [
{
"id": "home",
"path": "/home",
"title": "Home",
"component": "HomePage",
"layout": "app"
}
],
"blocks": [],
"widgets": [],
"actions": [],
"writableExtensions": []
}
}Top-level fields
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | yes | Display name. |
slug | string | yes | URL-safe identifier. Locked at first publish. |
version | semver | yes | Bumped by you between publishes. The marketplace rejects re-uses. |
sdkVersion | semver | yes | The @orion-ehr/app-bridge SDK version your bundle targets (e.g. 1.1.0). |
scope | string[] | yes | SMART-on-FHIR scopes the app needs (e.g. user/Patient.read, launch/patient, openid). The reviewer must approve any new scope. |
entryPoint | string | yes | Relative path to the source entry the bundler should compile (e.g. ./src/main.tsx). |
description / author / homepage / support / icon | string | no | Marketplace listing metadata. |
extensions | object | no | Container for navigation, pages, blocks, widgets, actions, and writableExtensions arrays. See Manifest schema. |
See Manifest schema for the per-extension shapes.