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 mostly back optional platform-adapter members; a few ( filesRead ) back no member and let an adapter serve one it already has more cheaply, and their degradation names the route they stand in for. Studio degrades without any of 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 Browse… reports that the folder could not be placed; the Location 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; an entry may carry an opaque content version the backend vouches for; with ?glob= , search matching files project-wide no —
fileRead GET /__studio/file Read a file's text content no —
filesRead POST /__studio/files/read Read many files' text content {paths} → ReadFilesResult {files: [path, {content} | {error: {status, code?, message}}][], omitted}. At most READ_FILES_MAX_PATHS (200) paths and a backend byte budget per call: the excess is listed in omitted (never a 400) and the first path is always answered. Per-path errors: 404 missing/deleted, 415 binary, 413 too large, 502 upstream. Allowed for read-only sessions; keeps fileRead's server-side effects yes Adapters fall back to one fileRead per path.
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 —
fileBytes GET /__studio/file/bytes A project file's raw bytes, undecoded — the read side of fileUpload , for a caller that must not go through UTF-8 yes Studio can only read a project file as text, so any surface that must decode one stays hidden.
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.
extensionCatalog GET /__studio/catalog Extensions this backend can OFFER (ExtensionCatalogEntry[]) — the shipped first-party catalogue plus any package in the project's own dependencies exporting a jx-extension.json, each marked with whether the host resolves it without a project install and whether the project has it installed. A capability rather than a constant: a Worker ships a fixed set of extension packages (specs/extensions.md §5.5). Backs listExtensionCatalog. yes The Extensions section offers no catalogue; adding an extension stays a typed package name.
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 —
actionRequired 403 https://jxsuite.com/problems/action-required An action is required first actions , heading , retry

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 —