[Skip to content](#main-content)

[![Jx Suite](/favicon.svg)
Suite](/)Search⌘KESC

Jump to

[Install Jx Studio](/docs/start/install)[Build your first project](/docs/start/first-project)[Document format](/docs/framework/concepts/documents)[Formula catalog](/docs/framework/reference/formulas)

↵
select↑↓
navigateesc
close

[Studio](/studio)[Framework](/framework)[Templates](/templates)[Compare](/compare)[Docs](/docs/start/first-project)[GitHub](https://github.com/jxsuite/jx)[Download](/download)

✕

[Studio](/studio)[Framework](/framework)[Templates](/templates)[Compare](/compare)[Docs](/docs/start/first-project)[GitHub](https://github.com/jxsuite/jx)

Color scheme&#xA;

[Download](/download)

☰

Docs menu

Start here[Overview](/docs/start/)Get started[Install Jx Studio](/docs/start/install/)[Your first project](/docs/start/first-project/)[A tour of Jx Studio](/docs/start/studio-tour/)Tutorials[Tutorial: interactive component](/docs/start/first-component/)[Tutorial: blog with collections](/docs/start/first-collection/)[Video tutorials](/docs/start/videos/)Coming from another tool[Coming from WordPress](/docs/start/coming-from-wordpress/)[Coming from Webflow or Framer](/docs/start/coming-from-webflow/)[Coming from Wix or Squarespace](/docs/start/coming-from-wix/)[Coming from Lovable or Builder.io](/docs/start/coming-from-ai-builders/)Studio[Overview](/docs/studio/)[The desktop app](/docs/studio/desktop/)The workspace[Overview](/docs/studio/interface/)[Welcome screen](/docs/studio/interface/welcome-screen/)[Editors and views](/docs/studio/interface/modes/)[The canvas](/docs/studio/interface/canvas/)[Documents and panes](/docs/studio/interface/tabs/)[Quick Access](/docs/studio/interface/quick-access/)[Keyboard shortcuts](/docs/studio/interface/shortcuts/)[Preferences](/docs/studio/interface/preferences/)[Languages](/docs/studio/interface/languages/)[Problems and progress](/docs/studio/interface/problems-and-progress/)[Commands](/docs/studio/interface/commands/)Projects[Overview](/docs/studio/projects/)[Create a project](/docs/studio/projects/create/)[Pages, layouts, components](/docs/studio/projects/pages-layouts-components/)[The Content workspace](/docs/studio/projects/browse/)[Starter templates](/docs/studio/projects/starters/)[Media](/docs/studio/projects/media/)[Content types](/docs/studio/projects/content-types/)[Project settings](/docs/studio/projects/settings/)[Dependencies and imports](/docs/studio/projects/dependencies/)Edit mode[Overview](/docs/studio/editing/)[Writing and formatting](/docs/studio/editing/writing/)[Slash commands](/docs/studio/editing/slash-commands/)[Frontmatter and metadata](/docs/studio/editing/frontmatter/)[Grid mode](/docs/studio/editing/grid/)Design mode[Overview](/docs/studio/design/)[Outline](/docs/studio/design/layers/)[Insert](/docs/studio/design/elements/)[Content tab](/docs/studio/design/properties/)[Style inspector](/docs/studio/design/style-inspector/)[Breakpoints](/docs/studio/design/breakpoints/)[States and selectors](/docs/studio/design/states-and-selectors/)[Design tokens](/docs/studio/design/tokens/)[Project Styles](/docs/studio/design/stylebook/)[Working with components](/docs/studio/design/components/)[Repeaters](/docs/studio/design/repeaters/)Logic[Overview](/docs/studio/logic/)[Formulas and expressions](/docs/studio/logic/formulas/)[Formula workspace](/docs/studio/logic/formula-workspace/)[Statements](/docs/studio/logic/statements/)[Logic tab](/docs/studio/logic/events/)[Data](/docs/studio/logic/data/)[Data sources](/docs/studio/logic/data-sources/)[Code editing](/docs/studio/logic/code/)Databases[Overview](/docs/studio/data/)[Connections](/docs/studio/data/connections/)[Data tables](/docs/studio/data/tables/)[Data grid](/docs/studio/data/grid/)[Auth and secrets](/docs/studio/data/auth-and-secrets/)AI assistant[Overview](/docs/studio/ai/)[The AI assistant](/docs/studio/ai/chat/)[Document assistant](/docs/studio/ai/document-assistant/)Publish[Overview](/docs/studio/publish/)[Source control](/docs/studio/publish/source-control/)[GitHub](/docs/studio/publish/github/)[Cloudflare Pages](/docs/studio/publish/cloudflare/)[Other hosts](/docs/studio/publish/other-hosts/)[Redirects](/docs/studio/publish/redirects/)[Real-time collaboration](/docs/studio/publish/collaboration/)Framework[Overview](/docs/framework/)Concepts[Documents](/docs/framework/concepts/documents/)[Elements](/docs/framework/concepts/elements/)[Components](/docs/framework/concepts/components/)[Props and scope](/docs/framework/concepts/props-and-scope/)[State](/docs/framework/concepts/state/)[Reactivity](/docs/framework/concepts/reactivity/)[References](/docs/framework/concepts/references/)[Expressions](/docs/framework/concepts/expressions/)[Statements](/docs/framework/concepts/statements/)[Functions and sidecars](/docs/framework/concepts/functions/)[Styling](/docs/framework/concepts/styling/)[Color schemes](/docs/framework/concepts/color-schemes/)[Popovers and overlays](/docs/framework/concepts/overlays/)[Accessibility](/docs/framework/concepts/accessibility/)[Lists and iteration](/docs/framework/concepts/lists/)[Data prototypes](/docs/framework/concepts/data-prototypes/)[Timing](/docs/framework/concepts/timing/)[Dynamic switching](/docs/framework/concepts/switching/)[Security](/docs/framework/concepts/security/)Site architecture[Overview](/docs/framework/site/)[project.json](/docs/framework/site/project-json/)[Routing](/docs/framework/site/routing/)[Layouts](/docs/framework/site/layouts/)[Content collections](/docs/framework/site/content-collections/)[Jx Markdown](/docs/framework/site/jx-markdown/)[Obsidian vault as content](/docs/framework/site/obsidian-vault/)[Relationships](/docs/framework/site/relationships/)[SEO and metadata](/docs/framework/site/seo/)[Locales and languages](/docs/framework/site/i18n/)[Images](/docs/framework/site/images/)[Redirects](/docs/framework/site/redirects/)[Feeds](/docs/framework/site/feeds/)[Site search](/docs/framework/site/search/)[Build output and adapters](/docs/framework/site/deployment/)How compilation works[Overview](/docs/framework/build/)[The dev server](/docs/framework/build/dev-server/)[CLI commands](/docs/framework/build/cli/)Working with agents[Overview](/docs/framework/agents/)[Authoring rules for agents](/docs/framework/agents/authoring-rules/)[Machine-readable docs](/docs/framework/agents/machine-readable/)Reference[Overview](/docs/framework/reference/)[Formula catalog](/docs/framework/reference/formulas/)[Operator reference](/docs/framework/reference/operators/)Extending[Overview](/docs/extending/)Extensions[Extension anatomy](/docs/extending/extensions/anatomy/)[Schema composition](/docs/extending/extensions/schema-composition/)[Custom classes](/docs/extending/extensions/classes/)[Custom formats](/docs/extending/extensions/formats/)[Capability methods](/docs/extending/extensions/capabilities/)[Project sections](/docs/extending/extensions/project-sections/)[Server mounts](/docs/extending/extensions/server/)[Connectors](/docs/extending/extensions/connectors/)[Search indexes](/docs/extending/extensions/search/)[Security and secrets](/docs/extending/extensions/security/)[Tutorial: a TOML format](/docs/extending/extensions/tutorial-toml-format/)[Tutorial: a guestbook](/docs/extending/extensions/tutorial-guestbook/)[First-party extensions](/docs/extending/extensions/first-party/)Embedding[Overview](/docs/extending/embedding/)[Hosting the Studio assets](/docs/extending/embedding/hosting/)[Writing a platform adapter](/docs/extending/embedding/platform-adapter/)[The backend protocol](/docs/extending/embedding/backend-protocol/)[Dev server internals](/docs/extending/embedding/dev-server/)[Embedding the runtime in your app](/docs/extending/embedding/runtime-host/)[Writing assistant tools](/docs/extending/embedding/assistant-harness/)UI kit[The Jx UI kit](/docs/extending/ui-kit/)Reference[Protocol routes](/docs/extending/reference/studio-routes/)[Implementation status](/docs/extending/reference/implementation-status/)[Spec changelog](/docs/extending/reference/spec-changelog/)[Standards alignment](/docs/extending/reference/standards/)Contributing[Working in the monorepo](/docs/extending/contributing/monorepo/)[Contributing to these docs](/docs/extending/contributing/docs/)[AI assistant evals](/docs/extending/contributing/ai-evals/)

# Expressions

> **Studio writes this format for you.** The **fx** mode on value fields and the formula editor ([Formulas and expressions](/docs/studio/logic/formulas)) generate everything below, and this page documents the JSON if you want to hand-edit a file, review a diff, or understand what the chips represent.

An `$expression` is a computation or state change written as JSON structure instead of JavaScript source. One operator is applied to a `target`, optionally with a `value`. Because the whole thing is data, schema tooling can validate it, Studio can render it as editable chips, and the compiler can analyze it without parsing code.

The smallest complete expression is a dark-mode toggle handler:

```json&#x20;shiki
```

Expressions sit on the middle rung of the escalation ladder. Prefer the least powerful form that does the job:

| Rung                     | Power   | Use when                                  |
| ------------------------ | ------- | ----------------------------------------- |
| `$ref` binding           | Lowest  | Reading a state value                     |
| ${} template             | Low     | Single-use computed read                  |
| `$expression`            | Mid     | Declarative computation or state mutation |
| `$prototype: "Function"` | Highest | Logic not expressible as structure        |

## Expression nodes

Every node has the same three fields:

| Field      | Required          | Description                                                             |
| ---------- | ----------------- | ----------------------------------------------------------------------- |
| `operator` | Yes               | A token from the blessed set (see below)                                |
| `target`   | Yes               | The operand the operator acts on: a `$ref`, a literal, or a nested node |
| `value`    | By operator arity | The right-hand operand: a `$ref`, a literal, an array, or a nested node |

Nodes nest: a `target` or `value` may itself be a node, with no inner `$expression` wrapper, which appears only at the state entry or handler boundary. `counter = counter + 1` becomes:

```json&#x20;shiki
```

Operands resolve exactly like any [`$ref`](/docs/framework/concepts/references). State paths are always explicit JSON Pointers (`#/state/counter`), never raw `state.counter` strings, and `$map/` paths resolve through iteration context as elsewhere.

## Pure and mutating operators

Every operator is one of two modes, and the mode is never declared; it follows from the operator:

- **Pure** operators compute and return a value, mutating nothing: unary (`!`, `-`), arithmetic, comparison, logical, conditionals, aggregates, and the method operators below. A pure expression used as a state entry is a computed value, read via `$ref` or ${} like any other.
- **Mutating** operators write to their `target` and return nothing: assignment (`=`, `+=`, `-=`, `*=`, `/=`) and the array-mutation methods (`push`, `pop`, `shift`, `unshift`, `splice`). A mutating expression is a handler, bound to events.

```json&#x20;shiki
```

```json&#x20;shiki
```

`push`/`unshift` take a single `value`; `splice` takes an argument array (`[start, deleteCount, ...items]`); `pop`/`shift` take none. The full operator set is closed and enumerated in the [operator reference](/docs/framework/reference/operators). Anything outside it is a compile-time error, and logic that needs more escalates to a [function body](/docs/framework/concepts/functions).

## Aggregates

`reduce`, `map`, and `filter` are pure operators over an array `target`. Their `value` is a per-item expression evaluated once per element, with the same `$map/` context that [mapped lists](/docs/framework/concepts/lists) use:

| Reference                   | Bound during aggregation        |
| --------------------------- | ------------------------------- |
| `{ "$ref": "$map/item" }`   | The current array element       |
| `{ "$ref": "$map/index" }`  | The current zero-based index    |
| `{ "$ref": "$reduce/acc" }` | The accumulator (`reduce` only) |

A cart total, `acc + item.price * item.qty`, seeded by `initial`:

```json&#x20;shiki
```

`reduce` requires `initial`; `map` and `filter` must not declare it. Aggregates compose by nesting, so a `filter` node can be the `target` of a `reduce`.

## Conditionals

`?:` selects between two results. Its fields follow the ECMAScript conditional: `target` is the test, `value` the result when true, `initial` the result when false. All three are required. Else-if chains nest another `?:` in `initial`.

```json&#x20;shiki
```

`switch` is value-keyed selection, mirroring element-level [`$switch`](/docs/framework/concepts/switching): `target` is the discriminant, `cases` maps its **string form** to results, `default` is optional.

```json&#x20;shiki
```

For fallbacks, prefer `??` (nullish coalescing) over `||` when `0`, `""`, or `false` are legitimate values, because it substitutes only for `null` and `undefined`.

## Pure method operators

Genuine `String.prototype`, `Array.prototype`, and `Number.prototype` methods are operators too, with the receiver in `target` and arguments in `value` (a bare scalar, or an array for multiple). Only **pure** methods qualify; where the original mutates, the ES2023 change-by-copy name stands in (`toSorted`, not `sort`).

```json&#x20;shiki
```

```json&#x20;shiki
```

Evaluation is null-safe: a missing receiver yields `undefined` rather than throwing. The full method table is in the [operator reference](/docs/framework/reference/operators).

## Named formulas and `call`

A pure expression entry with `parameters` is a **named formula**: a reusable computation instead of a computed value. Inside its body, parameters resolve through the `$args/` scheme:

```json&#x20;shiki
```

The `call` operator invokes it: `target` is the callee pointer, `value` the positional argument list, ordered by the declared `parameters` (omitted arguments take their `default`):

```json&#x20;shiki
```

A callee may also be a pure standard-library global through `window#/`, gated by a closed allowlist (`Math.*`, `JSON.*`, `Object.keys`/`values`/`entries`/`fromEntries`, `Number.*`, `Array.from`/`isArray`/`of`, `parseFloat`, `structuredClone`, …). Impure platform functions (`fetch`, `alert`, `Math.random`, `Date.now`) are deliberately absent; side effects belong to [Function entries](/docs/framework/concepts/functions).

```json&#x20;shiki
```

Formulas declared in `project.json``state` are available on every page. A catalog of ready-made composite formulas ships with Studio's palette. See the [formula catalog](/docs/framework/reference/formulas).

## Reading the event

Handlers receive the DOM event, and the `event#/` reference scheme reads it without escalating to code. It resolves only inside an expression used as an event handler:

```json&#x20;shiki
```

## Where expressions appear

An `$expression` is valid in three positions:

1. **As a `state` entry**, a named, reusable operation. A pure entry is a computed value; a mutating entry is a handler you bind with `"onclick": { "$ref": "#/state/toggleTheme" }`, exactly like a Function entry.
2. **Inline as an event handler value** on any element, in place of a `$ref` to a function.
3. **As an element's `tagName`**, described in [Choosing an element's tag](#choosing-an-elements-tag) below.

Prefer the named form when reused; the inline form for single-use handlers.

## Choosing an element's tag

Sometimes one element should be a link when it has somewhere to go and a plain box when it doesn't, wrapping the same content either way. Write the choice in `tagName`:

```json&#x20;shiki
```

Use `switch` when there are more than two, and give it a `default`, because an element with no tag can't exist:

```json&#x20;shiki
```

Two rules make this different from every other formula:

- **Every branch is a tag name, not a formula.** You choose *between* tags; you don't compute one. That's what lets Studio tell you at authoring time that `"A LINK"` isn't a tag, instead of the page breaking in a browser.
- **The tag is decided once, when the element is created**, and isn't re-read afterwards. Changing it later would mean throwing the element away and building a new one, taking your content's focus, typed-in values and scroll position with it. If a tag needs to change in response to something, that's a `$switch`, which swaps content rather than the element itself.

Note

A component's own&#x20;
`tagName`
, the name at the top of the file, is always a plain name, as is a&#x20;
`$head`
&#x20;entry's. Those become a custom element's registered name and a tag in the page head, which can't vary per instance.

## How it works

An expression lowers to the same target a `body` string would, but the function is constructed from the node tree and never parsed from a string, so no `eval` or `new Function` is involved. A mutating expression becomes a handler over the reactive `state` proxy (`(state, event) => { state.darkMode = !state.darkMode; }`); a pure expression becomes a `computed()`, recomputing whenever the state it reads changes. See [Reactivity](/docs/framework/concepts/reactivity).

References inside a node resolve in a fixed order:

```text
1. $map/       — iteration context
2. $reduce/acc — fold accumulator (reduce only)
3. $args/      — named-formula parameters
4. event#/     — handler event context
5. #/state/    — current component scope
6. parent#/    — explicitly passed props
7. window#/    — global window properties
8. document#/  — global document properties
```

In production, `?:` and `switch` evaluate only the taken branch. In Studio's editor the interpreter runs with a trace that evaluates every branch, which is how each chip carries a live value badge.

## Rules

- The operator set is **closed**. An unknown operator is a compile-time error; escalate to a Function `body` instead.
- A mutating node may only appear at the handler boundary, never nested as an operand.
- Nested nodes take no `$expression` wrapper; it appears only at the entry or handler boundary.
- State operands are explicit `$ref` pointers, never raw `state.x` strings.
- `reduce` requires `initial`; `map` and `filter` must not declare it. `?:` requires `target`, `value`, and `initial`.
- `switch` matches on the discriminant's string form, because JSON keys are strings.
- `event#/` resolves only in handler position; referencing it from a non-handler entry is a compile-time error.
- `call` targets a named formula or a blessed global; call depth is capped at 64, and statically detectable call cycles are rejected.

## Related

- [Operator reference](/docs/framework/reference/operators): every blessed token
- [Formula catalog](/docs/framework/reference/formulas): composite formulas in Studio's palette
- [Statements](/docs/framework/concepts/statements): multi-step bodies built from expression nodes
- [Functions and sidecars](/docs/framework/concepts/functions): the escape hatch to real JavaScript
- [Reactivity](/docs/framework/concepts/reactivity): how computed values track their inputs
- [Formulas and expressions in Studio](/docs/studio/logic/formulas): the visual editor for all of this

✕

Start here[Overview](/docs/start/)Get started[Install Jx Studio](/docs/start/install/)[Your first project](/docs/start/first-project/)[A tour of Jx Studio](/docs/start/studio-tour/)Tutorials[Tutorial: interactive component](/docs/start/first-component/)[Tutorial: blog with collections](/docs/start/first-collection/)[Video tutorials](/docs/start/videos/)Coming from another tool[Coming from WordPress](/docs/start/coming-from-wordpress/)[Coming from Webflow or Framer](/docs/start/coming-from-webflow/)[Coming from Wix or Squarespace](/docs/start/coming-from-wix/)[Coming from Lovable or Builder.io](/docs/start/coming-from-ai-builders/)Studio[Overview](/docs/studio/)[The desktop app](/docs/studio/desktop/)The workspace[Overview](/docs/studio/interface/)[Welcome screen](/docs/studio/interface/welcome-screen/)[Editors and views](/docs/studio/interface/modes/)[The canvas](/docs/studio/interface/canvas/)[Documents and panes](/docs/studio/interface/tabs/)[Quick Access](/docs/studio/interface/quick-access/)[Keyboard shortcuts](/docs/studio/interface/shortcuts/)[Preferences](/docs/studio/interface/preferences/)[Languages](/docs/studio/interface/languages/)[Problems and progress](/docs/studio/interface/problems-and-progress/)[Commands](/docs/studio/interface/commands/)Projects[Overview](/docs/studio/projects/)[Create a project](/docs/studio/projects/create/)[Pages, layouts, components](/docs/studio/projects/pages-layouts-components/)[The Content workspace](/docs/studio/projects/browse/)[Starter templates](/docs/studio/projects/starters/)[Media](/docs/studio/projects/media/)[Content types](/docs/studio/projects/content-types/)[Project settings](/docs/studio/projects/settings/)[Dependencies and imports](/docs/studio/projects/dependencies/)Edit mode[Overview](/docs/studio/editing/)[Writing and formatting](/docs/studio/editing/writing/)[Slash commands](/docs/studio/editing/slash-commands/)[Frontmatter and metadata](/docs/studio/editing/frontmatter/)[Grid mode](/docs/studio/editing/grid/)Design mode[Overview](/docs/studio/design/)[Outline](/docs/studio/design/layers/)[Insert](/docs/studio/design/elements/)[Content tab](/docs/studio/design/properties/)[Style inspector](/docs/studio/design/style-inspector/)[Breakpoints](/docs/studio/design/breakpoints/)[States and selectors](/docs/studio/design/states-and-selectors/)[Design tokens](/docs/studio/design/tokens/)[Project Styles](/docs/studio/design/stylebook/)[Working with components](/docs/studio/design/components/)[Repeaters](/docs/studio/design/repeaters/)Logic[Overview](/docs/studio/logic/)[Formulas and expressions](/docs/studio/logic/formulas/)[Formula workspace](/docs/studio/logic/formula-workspace/)[Statements](/docs/studio/logic/statements/)[Logic tab](/docs/studio/logic/events/)[Data](/docs/studio/logic/data/)[Data sources](/docs/studio/logic/data-sources/)[Code editing](/docs/studio/logic/code/)Databases[Overview](/docs/studio/data/)[Connections](/docs/studio/data/connections/)[Data tables](/docs/studio/data/tables/)[Data grid](/docs/studio/data/grid/)[Auth and secrets](/docs/studio/data/auth-and-secrets/)AI assistant[Overview](/docs/studio/ai/)[The AI assistant](/docs/studio/ai/chat/)[Document assistant](/docs/studio/ai/document-assistant/)Publish[Overview](/docs/studio/publish/)[Source control](/docs/studio/publish/source-control/)[GitHub](/docs/studio/publish/github/)[Cloudflare Pages](/docs/studio/publish/cloudflare/)[Other hosts](/docs/studio/publish/other-hosts/)[Redirects](/docs/studio/publish/redirects/)[Real-time collaboration](/docs/studio/publish/collaboration/)Framework[Overview](/docs/framework/)Concepts[Documents](/docs/framework/concepts/documents/)[Elements](/docs/framework/concepts/elements/)[Components](/docs/framework/concepts/components/)[Props and scope](/docs/framework/concepts/props-and-scope/)[State](/docs/framework/concepts/state/)[Reactivity](/docs/framework/concepts/reactivity/)[References](/docs/framework/concepts/references/)[Expressions](/docs/framework/concepts/expressions/)[Statements](/docs/framework/concepts/statements/)[Functions and sidecars](/docs/framework/concepts/functions/)[Styling](/docs/framework/concepts/styling/)[Color schemes](/docs/framework/concepts/color-schemes/)[Popovers and overlays](/docs/framework/concepts/overlays/)[Accessibility](/docs/framework/concepts/accessibility/)[Lists and iteration](/docs/framework/concepts/lists/)[Data prototypes](/docs/framework/concepts/data-prototypes/)[Timing](/docs/framework/concepts/timing/)[Dynamic switching](/docs/framework/concepts/switching/)[Security](/docs/framework/concepts/security/)Site architecture[Overview](/docs/framework/site/)[project.json](/docs/framework/site/project-json/)[Routing](/docs/framework/site/routing/)[Layouts](/docs/framework/site/layouts/)[Content collections](/docs/framework/site/content-collections/)[Jx Markdown](/docs/framework/site/jx-markdown/)[Obsidian vault as content](/docs/framework/site/obsidian-vault/)[Relationships](/docs/framework/site/relationships/)[SEO and metadata](/docs/framework/site/seo/)[Locales and languages](/docs/framework/site/i18n/)[Images](/docs/framework/site/images/)[Redirects](/docs/framework/site/redirects/)[Feeds](/docs/framework/site/feeds/)[Site search](/docs/framework/site/search/)[Build output and adapters](/docs/framework/site/deployment/)How compilation works[Overview](/docs/framework/build/)[The dev server](/docs/framework/build/dev-server/)[CLI commands](/docs/framework/build/cli/)Working with agents[Overview](/docs/framework/agents/)[Authoring rules for agents](/docs/framework/agents/authoring-rules/)[Machine-readable docs](/docs/framework/agents/machine-readable/)Reference[Overview](/docs/framework/reference/)[Formula catalog](/docs/framework/reference/formulas/)[Operator reference](/docs/framework/reference/operators/)Extending[Overview](/docs/extending/)Extensions[Extension anatomy](/docs/extending/extensions/anatomy/)[Schema composition](/docs/extending/extensions/schema-composition/)[Custom classes](/docs/extending/extensions/classes/)[Custom formats](/docs/extending/extensions/formats/)[Capability methods](/docs/extending/extensions/capabilities/)[Project sections](/docs/extending/extensions/project-sections/)[Server mounts](/docs/extending/extensions/server/)[Connectors](/docs/extending/extensions/connectors/)[Search indexes](/docs/extending/extensions/search/)[Security and secrets](/docs/extending/extensions/security/)[Tutorial: a TOML format](/docs/extending/extensions/tutorial-toml-format/)[Tutorial: a guestbook](/docs/extending/extensions/tutorial-guestbook/)[First-party extensions](/docs/extending/extensions/first-party/)Embedding[Overview](/docs/extending/embedding/)[Hosting the Studio assets](/docs/extending/embedding/hosting/)[Writing a platform adapter](/docs/extending/embedding/platform-adapter/)[The backend protocol](/docs/extending/embedding/backend-protocol/)[Dev server internals](/docs/extending/embedding/dev-server/)[Embedding the runtime in your app](/docs/extending/embedding/runtime-host/)[Writing assistant tools](/docs/extending/embedding/assistant-harness/)UI kit[The Jx UI kit](/docs/extending/ui-kit/)Reference[Protocol routes](/docs/extending/reference/studio-routes/)[Implementation status](/docs/extending/reference/implementation-status/)[Spec changelog](/docs/extending/reference/spec-changelog/)[Standards alignment](/docs/extending/reference/standards/)Contributing[Working in the monorepo](/docs/extending/contributing/monorepo/)[Contributing to these docs](/docs/extending/contributing/docs/)[AI assistant evals](/docs/extending/contributing/ai-evals/)

[![Jx Suite](/favicon.svg)
Suite](/)The visual IDE for the web. Build any website, save it as plain files, own it forever. MIT licensed.

Product

[Studio](/studio)[Download](/download)[Templates](/templates)[Features](/features)[Compare](/compare)[Jx Cloud (soon)](/cloud)

Developers

[Docs](/docs/start/first-project)[Framework](/framework)[Get Studio](/docs/start/install)[Spec](/docs/framework)[GitHub](https://github.com/jxsuite/jx)

Project

[MIT License](https://github.com/jxsuite/jx/blob/main/LICENSE)[Releases](https://github.com/jxsuite/jx/releases/latest)[Privacy](/privacy)[Terms](/terms)[Support](/support)

Built with Jx Suite. © 2026 Avunu LLC. Open source under the MIT License.
