Skip to content

Protocol route reference

The canonical Studio Backend Protocol route table (protocol version 1), from @jxsuite/protocol . The dev server is the reference implementation; any backend serving these shapes can host Studio. Optional routes back optional platform-adapter members — Studio degrades without them as described.

Session / project

Route Method Path Summary Optional Degradation
activate POST /__studio/activate Bind the backend to a project root no
project GET /__studio/project Root project metadata {name, root} no
projectInfo GET /__studio/project-info Probe a directory: {isSiteProject, projectConfig?, directories?} no
resolveSite GET /__studio/resolve-site Resolve the owning site of a file path {sitePath, projectConfig?, fileRelPath?} no
sites GET /__studio/sites Enumerate site projects [{config, path}] (backs listProjects) yes The welcome screen's Projects catalogue stays hidden.
findProject GET /__studio/find-project Locate a project directory by name outside the root yes openProject falls back to config-matching only.
locateDirectory GET /__studio/locate-directory Resolve the absolute path of a showDirectoryPicker() folder by the id in its .jx-loc-id yes The New Project Location field loses its Browse… button and is typed by hand.
createProject POST /__studio/create-project Scaffold a project at a caller-chosen destination → {root, config} no
starters GET /__studio/starters Starter templates (StarterInfo[]) yes The New Project picker offers only blank/templates.
importSite POST /__studio/import-site Clone a live website into a project; streams NDJSON progress yes The New Project Import tab is unavailable.

Filesystem

Route Method Path Summary Optional Degradation
files GET /__studio/files List a directory (DirEntry[]) in stable path order; with ?glob= , search matching files project-wide no
fileRead GET /__studio/file Read a file's text content no
fileWrite PUT /__studio/file Write a file's text content no
fileDelete DELETE /__studio/file Delete a file no
fileUpload POST /__studio/file/upload Upload binary content to a path → UploadResult {path, size?}. path is the answer, not an echo: a store that de-duplicates, suffixes, or normalizes names reports what it really wrote no
documentRaw GET /__studio/raw/ A project file as its own bytes, at its own URL — the mount a canvas renders against when the editor origin does not serve the site's URL space. The project-relative path is appended to this prefix yes The canvas cannot address project files by URL, so a host whose origin does not serve the site URL space renders no component $refs and no images.
fileRename POST /__studio/file/rename Rename/move (+ refactor report). from / to are server-root-relative; every path in the report is relative to the active project (specs/server.md §4.1) no
references GET /__studio/references Where a file or a component tag is used (?path=&tag=, at least one) → ReferencesResult {files, filesReferencing, refsTotal} — the read side of the rename refactor's own walker, cached until the backend's watcher sees the tree move (backs findReferences). ?path= is server-root-relative and every path in the answer is relative to the active project; a target outside that project is a 400, never a zero-result 200 (specs/server.md §4.1) yes Usage counts are hidden: no "Used on N pages" in the inspector, no Selection: Find Usages, and delete/rename confirmations state no reference count.
locate POST /__studio/locate Find a file by name → {path | null} no
collab GET /__studio/collab Realtime co-editing: a WebSocket upgrade speaking the @jxsuite/collab wire envelope (one socket per project, documents multiplexed by path; y-protocols sync + project-level awareness in lib0 binary frames — see @jxsuite/collab/envelope for the frame layout and the docEpoch/doc-reset lifecycle). A plain GET (no Upgrade) answers {collab, protocols, version} as the capability probe, and protocols is the subprotocol negotiation: the client offers one of them as Sec-WebSocket-Protocol and the server echoes it, or the client offers none when the server advertises none, because RFC 6455 §4.1 fails a connection whose offer went unechoed. yes Realtime co-editing is unavailable; Studio edits solo with file-level saves

Documents / components / formats

Route Method Path Summary Optional Degradation
components GET /__studio/components Discover components (ComponentMeta[]) no
cem GET /__studio/cem Custom-elements manifest of an npm dependency yes Dependency components lose prop/slot metadata.
formats GET /__studio/formats The project's format registry entries plus a sibling extensions array — per enabled extension its manifest identity and project-section contributions (ExtensionsInfo[]; backs listFormats and listExtensions). yes Only .json documents open (backs listFormats); descriptor-contributed settings sections do not appear.
projectSchemas GET /__studio/project-schemas The project's generated entry documents (project.schema.json / document.schema.json), PRE-BUNDLED into self-contained schemas — {project, document} (backs fetchProjectSchemas). Regenerated on demand when missing or older than project.json. yes The JSON editor falls back to the bundled core schemas (extension sections get no editor validation/completion).
format POST /__studio/format Dispatch a format capability {format, action: parse|serialize, source?|doc?} yes Non-JSON documents cannot be parsed/serialized (backs formatAction).
pluginSchema GET /__studio/plugin-schema Extract a $studio schema from a class source yes Plugin property panels fall back to generic JSON editing.
codeFormat POST /__studio/code/format Format posted source {code, path?} → {code, errors} yes Code editors skip format-on-open/save (codeService returns null).
codeMinify POST /__studio/code/minify Minify posted source {code} → {code} yes Compiled-output minification is skipped.
codeLint POST /__studio/code/lint Lint posted source {code, path?} → {diagnostics} yes Code editors show no lint markers.

Site build

Route Method Path Summary Optional Degradation
buildSite POST /__studio/build Build or render the site → {routes, files, errors, mode?, url} yes Build Site reports that this target cannot build.
previewSite POST /__studio/preview Preview the working tree at a route → {routes, files, errors, mode, url, reused} yes Open in Browser falls back to buildSite.
previewOverlay POST /__studio/preview/overlay Publish (POST) or retract (DELETE) a document's unsaved bytes → 204 yes A live preview shows the last saved state instead of the editor's.

Packages

Route Method Path Summary Optional Degradation
packages GET /__studio/packages List dependencies (PackageInfo[]) no
packagesAdd POST /__studio/packages/add Add a dependency no
packagesRemove POST /__studio/packages/remove Remove a dependency no
packagesInstall POST /__studio/packages/install Run the package manager install yes Install/reinstall affordances are hidden; manifest-only edits still work.
packagesNeedsInstall GET /__studio/packages/needs-install Whether node_modules is stale yes The install-on-open prompt never shows.
packagesVersions GET /__studio/packages/versions Newest published version of each dependency (PackageVersionInfo[]) yes The Latest column stays empty and the update affordances are hidden.
packagesSetVersions POST /__studio/packages/set-versions Rewrite dependency ranges and install yes Bulk version updates are hidden.

Git

Route Method Path Summary Optional Degradation
gitStatus GET /__studio/git/status Working-tree status (GitStatusResult) no
gitBranches GET /__studio/git/branches Branch list (GitBranchesResult) no
gitLog GET /__studio/git/log Recent commits (GitLogEntry[]) no
gitStage POST /__studio/git/stage Stage files no
gitUnstage POST /__studio/git/unstage Unstage files no
gitCommit POST /__studio/git/commit Commit staged (else all dirty) files no
gitPush POST /__studio/git/push Push (cloud: sync check — commits land on push) no
gitPull POST /__studio/git/pull Pull/fast-forward; 409 {conflicts} on overlap no
gitFetch POST /__studio/git/fetch Refresh remote tracking state no
gitCheckout POST /__studio/git/checkout Switch branches no
gitCreateBranch POST /__studio/git/create-branch Create a branch no
gitDiff GET /__studio/git/diff Unified diff of dirty files (or one path) no
gitShow GET /__studio/git/show File content at a ref no
gitDiscard POST /__studio/git/discard Discard working changes no
gitInit POST /__studio/git/init Initialize a repository no
gitAddRemote POST /__studio/git/add-remote Add a remote no
gitClone POST /__studio/git/clone Clone a repository yes The welcome screen hides Clone Git Repository.
gitPr POST /__studio/git/pr Open a pull request → PullRequestInfo yes Studio falls back to a direct GitHub API call with the user's token.

Data surface (connector domain owner console)

Route Method Path Summary Optional Degradation
dataConnections GET /__studio/data/connections Connector connections with configured/missingSecrets/isDefault state, reachable table names, and registry-descriptor provider metadata (DataConnectionsResponse; backs dataConnections) yes The connections settings section shows no status, and data-domain actions stay hidden.
dataConnectionTest POST /__studio/data/connections/test Probe a connection {connection} → DataConnectionTestResult (backs dataConnectionTest) yes The Test Connection action is hidden.
dataPush POST /__studio/data/push Additive schema push {connection?, dryRun?} → DataPushResult (plan of DataPushStep[], applied, warnings/errors; backs dataPush) yes The Push Schema action is hidden; schemas deploy via jx db push instead.
dataRows GET /__studio/data/rows Page a table (DataRowsQuery params) → DataRowsResult {rows, total, columns} (backs dataRows) yes The data grid is unavailable.
dataInsertRow POST /__studio/data/rows Insert a row {table, connection?, values} → {row} (backs dataInsertRow) yes The data grid hides its add-row footer.
dataUpdateRow PUT /__studio/data/rows Update a row keyed on its primary key {table, connection?, pk, set} → {row} (backs dataUpdateRow) yes Data grid cells are read-only.
dataDeleteRow DELETE /__studio/data/rows Delete a row (?table=&pk=&connection=) → {ok} (backs dataDeleteRow) yes The data grid hides row deletion.

Secrets (names only)

Route Method Path Summary Optional Degradation
secretsList GET /__studio/secrets Configured secret env-var NAMES, never values (SecretsListResponse; backs listSecrets) yes Secret fields cannot show set/unset state.
secretsSet PUT /__studio/secrets Write/remove secrets in the backend store (.dev.vars locally) {set?, remove?} → names (backs setSecrets) yes The secret form control renders disabled; secrets are edited in .dev.vars by hand.

AI proxy

Route Method Path Summary Optional Degradation
aiChat POST /__studio/ai/chat StreamEvent SSE chat proxy {messages, tools, systemPrompt, model} no
aiModels GET /__studio/ai/models Model catalogue (AiModelsResponse) no

Cloudflare publish surface

Route Method Path Summary Optional Degradation
cfProxy POST /__studio/cf/proxy Allowlisted Cloudflare API passthrough {path, method?, body?} (backs cfApi) yes The Publish panel explains the git-push publishing path instead.

Failures

Every failure is an RFC 9457 problem document at application/problem+json . The type URI is what a client keys on; detail is the line a human reads, and title describes the type rather than the occurrence. The status belongs to the type — a type answerable with two statuses is two types.

error is emitted as a deprecated alias of detail for one release, so a client written against the older shape keeps working. Do not write new readers against it.

The request

Name Status Type Title Extensions
invalidRequest 400 https://jxsuite.com/problems/invalid-request The request was malformed or incomplete
notFound 404 https://jxsuite.com/problems/not-found The requested resource does not exist
methodNotAllowed 405 https://jxsuite.com/problems/method-not-allowed That method is not allowed on this route
conflict 409 https://jxsuite.com/problems/conflict The request conflicts with the current state conflicts
payloadTooLarge 413 https://jxsuite.com/problems/payload-too-large The request body is too large

Access

Name Status Type Title Extensions
unauthorized 401 https://jxsuite.com/problems/unauthorized Credentials are missing or not accepted
forbidden 403 https://jxsuite.com/problems/forbidden The request was refused
needsInstallationAccess 403 https://jxsuite.com/problems/needs-installation-access The GitHub App is not installed for that account installUrl
pathOutsideProject 403 https://jxsuite.com/problems/path-outside-project The path resolves outside the active project

Backend state

Name Status Type Title Extensions
noActiveProject 409 https://jxsuite.com/problems/no-active-project No project is active on this backend
capabilityUnavailable 501 https://jxsuite.com/problems/capability-unavailable This backend does not provide that capability
upstreamFailure 502 https://jxsuite.com/problems/upstream-failure An upstream service failed upstream
internalError 500 https://jxsuite.com/problems/internal-error The backend failed to complete the request