[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/)

# Tutorial: your first interactive component

In this tutorial you build a `counter-card` component: a button and a line of text that counts the clicks, live. Small as it is, it walks the whole loop every interactive piece of a Jx site is made from, without writing any code: elements on the canvas, a state value, a binding, and an event.

![The finished counter card on the canvas with Preview on, showing a count of 3](/content/docs/images/counter-finished.png)

**About 15 minutes.** Before you start:

- Have Jx Studio running. **[Install Jx Studio](/docs/start/install)** covers it.
- If Studio is completely new to you, skim **[Your first project](/docs/start/first-project)** first. This tutorial starts where it ends, with a project open.

## 1. Open a project

Any project works. If you already have one from [Your first project](/docs/start/first-project), open it with **Open Project**. Otherwise choose **New Project…**, scroll to the **Start from scratch** card at the end of the starter gallery, click **Next**, name the project (say, "Counter Demo"), and click **Create Project**. Every step of the wizard is explained in **[Create a project](/docs/studio/projects/create)**.

![The New Project dialog with the starter gallery and the Start from scratch card](/content/docs/images/new-project-modal.png)

You should now see your project open on the canvas.

## 2. Create the component

1. Press ⌘N to open **Add new** (in a browser, ⌘⌥N), or click the **+** at the top of the Site panel.
2. Choose **Component**.
3. Type `counter-card` and click **Create component**.

Studio writes `components/counter-card.json` and opens it in a new tab, an empty canvas ready to fill. (When to reach for a component versus a page or layout is covered in **[Pages, layouts, and components](/docs/studio/projects/pages-layouts-components)**.)

## 3. Switch to Design

Component files open in **Edit**. In the **View** control on the pane's context bar, click **Design**.

![Jx Studio design canvas showing one component across four responsive breakpoints with a style inspector](/content/docs/images/mode-design.png)

The canvas now shows your component once per breakpoint, empty for the moment, and the Inspector on the right offers the **Content**, **Style**, **Logic**, and **Assistant** tabs. Views are lenses on the same file; see **[Editors and views](/docs/studio/interface/modes)**.

## 4. Add a button and a text line

1. Press ⌘K and run **Show Insert** to open the palette.
2. With nothing selected, click the `<button>` card. The button is added to the empty component.
3. Click the `<p>` card to add a paragraph. A card inserts into whatever is selected, as its last child; with nothing selected that's the component's root, so the paragraph lands after the button rather than inside it.
4. Select the button, open the Inspector's **Content** tab, and type `Add one` into **Text Content**.

![The design canvas with a button labeled Add one and an empty paragraph below it](/content/docs/images/counter-elements.png)

You should now see a button labeled **Add one** with an empty paragraph after it, at every breakpoint. The other ways to insert, dragging cards and the **+** affordance between elements, are covered in **[The canvas](/docs/studio/interface/canvas)** and the **[Insert palette](/docs/studio/design/elements)**.

## 5. Declare the count

The component needs somewhere to keep its number. That's a state entry:

1. Click **Data** in the **Document** group of the Navigator rail to open the **Data** panel.
2. Click the **+ Add…** picker at the bottom of the panel and choose **Value**. The new entry appears with a placeholder name and its editor open.
3. Rename it first: type `count` into the **Name** field and press Enter.
4. Set **Type** to `integer`, then type `0` into **Default**. A new entry starts with an empty default, and an empty string is not something you can add one to.

![Jx Studio Data panel listing a component's state and functions](/content/docs/images/state-panel.png)

The panel now shows a **State** section with one row: an **S** badge and the name `count`. Everything else the panel can hold, from computed values to data sources to functions, is covered in **[Data panel](/docs/studio/logic/data)**.

## 6. Bind the text to the count

Now point the paragraph at the value instead of typing fixed text:

1. Select the paragraph on the canvas.
2. In the Inspector's **Content** tab, find the **Text Content** row in the **Element** section. Beside its label sits a small chip reading **Fixed value**. That is the row's *value source*, and it says the text is a literal you typed.
3. Click the chip. A short list opens naming every source this field accepts (**Fixed value**, **From data…**, **Mixed text**), each with a line saying what it does. Pick **Mixed text**. Any source is one click away; the chip never cycles you through the ones you didn't want.
4. Studio fills the field with your first state entry: ${state.count}. Keep it, or mix in words: Clicked ${state.count} times.

![The Text Content row set to Mixed text, holding $​{state.count}, with its value-source chip accent-colored](/content/docs/images/counter-text-binding.png)

The chip takes on the accent color: this value is produced from something else now, and the paragraph will always show the current count. The same four words name a value's source everywhere in Studio (**Fixed value**, **From data…**, **Mixed text**, **Formula**), and each field offers only the ones it can legally hold, which is why Text Content shows three of them. The dynamic ones are explained in **[Formulas and expressions](/docs/studio/logic/formulas)**.

## 7. Make the button count

1. Select the button and open the Inspector's **Logic** tab, either by clicking it or by pressing ⌘⇧4. Logic is where an element's behavior lives: its events, and the condition or repeating-list settings when it has them.
2. In the **Events** section, click **Add Event**. A binding appears on `onclick`, and since the file has no functions yet it starts as an inline handler.
3. The picker beside the event name chooses how the binding responds. Set it to **Expression**, the mode for one-step reactions. (**Inline code** and **Existing function** are the other two.)
4. In the formula editor, set the **Operator** to `+=`. The **Target** row becomes a signal picker, so choose `count`. In the **Value** row, leave the source on **Fixed value**, change its type from `null` to `num`, and enter `1`.

![The Logic tab with an onclick binding in expression mode incrementing count](/content/docs/images/counter-onclick.png)

A chip strip above the editor summarizes the formula as a `count` chip followed by a `+=` chip, and each chip carries a small badge with the value it evaluates to against the running page. The three ways an event can respond (**Existing function**, **Expression**, **Inline code**) are covered in **[Events](/docs/studio/logic/events)**.

## 8. Try it in Preview

Pick **Preview** in the **View** control on the context bar. The paragraph now shows `0`, the resolved value. Click **Add one** a few times.

![The canvas with Preview on, the paragraph showing the climbed count](/content/docs/images/counter-preview.png)

You should see the number climb with every click. That's the whole reactive loop: the event writes to `count`, and everything bound to `count` updates by itself.

## 9. Watch the value resolve

Click **Data** in the **Document** group of the Navigator rail, or run **Show Data** from ⌘K. It lists the same entries as the Data panel, but with what each one is worth *right now*, so your `count` row shows the current number. Stay in Preview, click **Add one**, and watch the row change; **Refresh** re-renders the canvas and reads the values again.

![The Data panel with the count entry showing its live value](/content/docs/images/counter-data-explorer.png)

When a page ever looks wrong, this panel is where you find out what it actually sees. See **[the Data panel](/docs/studio/logic/data)**.

## 10. Try a test value

Because `count` is a plain state value on a component, it's also one of the component's *props*: an option a page can set when it uses the card.

1. On the context bar, click **Defaults ⌄**. The popover headed **resolving with** holds one field per prop.
2. Type `100` into the **count** field.
3. The canvas re-renders with the count starting at 100, at every breakpoint, and the button now reads **1 set**.
4. Clear the field to return to the default of `0`.

![The resolving-with popover holding a test value, the canvas rendering with it](/content/docs/images/counter-test-prop.png)

Test values are a preview lens only, and are never saved into the component. Props and test values are covered in **[Working with components](/docs/studio/design/components)**.

## 11. Save your work

The document's tab shows a **●** dot for unsaved changes. Press ⌘S (macOS) or Ctrl+S (Windows/Linux), or click **Save** in the Command Bar, and the dot goes away.

You should see the dot disappear. When you're ready to publish, the **Publish** workspace takes it from here. See **[Source control](/docs/studio/publish/source-control)**.

## What you built

A working, reusable component, and every piece of the interactive toolkit in one pass:

- A **state entry** (`count`) is the component's memory, and automatically its prop.
- A **template binding** (${state.count}) is text that follows the value wherever it goes.
- An **event expression** (`count += 1`, assembled from an operator and two operands) is behavior without a line of code.
- **Preview**, the **Data** panel's resolved values, and **test values** are three ways to watch it run.

Note

Everything landed in one plain file,&#x20;
`components/counter-card.json`
: the entry in its&#x20;
`state`
&#x20;object, the paragraph's text as a&#x20;
`${}`
&#x20;template, and the button's&#x20;
`onclick`
&#x20;as an&#x20;
`$expression`
. The formats are documented in&#x20;
**[State](/docs/framework/concepts/state)**
&#x20;and&#x20;
**[Reactivity](/docs/framework/concepts/reactivity)**
.

## Next steps

- Drop the card onto any page from the **[Insert palette](/docs/studio/design/elements)**, where your components appear at the top.
- Style its spacing, color and hover states with the **[Style inspector](/docs/studio/design/style-inspector)**.
- When one step isn't enough, build multi-step handlers as **[statements](/docs/studio/logic/statements)**.
- Keep going: **[Tutorial: a blog with content collections](/docs/start/first-collection)**.

✕

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.
