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

# Custom formats

A format teaches Jx a new file type. Jx *is* JSON, so `.json` is the single native built-in; every other extension a project opens, saves, builds, or loads content from (`.md`, `.csv`, your `.toml`) is dispatched through a format class. A class participates in format dispatch iff its `.class.json` descriptor carries a top-level `format` object.

## The `format` block

The parser's `Markdown.class.json` declares, verbatim:

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

| Key             | Type                                 | Default | Meaning                                                                                                                                      |
| --------------- | ------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `extensions`    | `string[]` (required)                | —       | File extensions claimed, with leading dot.                                                                                                   |
| `mediaType`     | `string`                             | —       | Media type; **validated**, so a malformed value fails the registry build. Used for icons, labels and HTTP responses.                         |
| `documentKinds` | `("page"\|"component"\|"content")[]` | `[]`    | `page`/`component` admit the extension into pages/components discovery globs; `content` admits it as a content source.                       |
| `exportTarget`  | `boolean`                            | `false` | When true, site builds emit a serialized sidecar per page in this format (requires a `serialize` capability).                                |
| `remote`        | `boolean`                            | `false` | When true, the `load` capability accepts `http(s)` URLs as sources. Remote content sources **must** name a remote-capable format explicitly. |

Two classes may claim the same extension **only with disjoint capabilities**. The registry build fails on an ambiguous `(extension, capability)` pair. A registry never claims `.json`.

### mediaType is checked

Your `mediaType` reaches an HTTP header, a file-picker filter and a Studio label, so it's parsed rather than passed through. Get the grammar wrong and the build tells you:

```text
Format "Toml" declares an invalid mediaType: "applicationtoml" has no "/" — a media type is type/subtype (RFC 6838 §4.2)
```

The check is on the **syntax**, not the IANA registry: `application/x.my-format` is fine, and so is any subtype nobody has registered.

Parameters are welcome and carry meaning. `@jxsuite/parser` declares `text/markdown; variant=GFM`, which is how [RFC 7763](https://www.rfc-editor.org/rfc/rfc7763) says *which* markdown a format speaks:

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

Note

A file-picker&#x20;
`accept`
&#x20;map or an editor language id&#x20;
**keys**
&#x20;on a media type. In code like that, use the&#x20;
*essence*
&#x20;(
`text/markdown`
), not the declared string.&#x20;
`mediaTypeEssence`
&#x20;on the registry entry gives you that. Two Studio call sites broke the moment the&#x20;
`variant`
&#x20;parameter was declared, which is why the distinction exists.

### What a static file server sends

Your `format` block only reaches code that went through the registry. A `.md` file served straight off disk (by the dev server, or by `jx preview`) never touches it, and the platform's own table answers instead.

For most extensions that's fine. For two it isn't, so Jx overrides them:

| Extension       | Platform says           | Jx sends                     | Why                                                  |
| --------------- | ----------------------- | ---------------------------- | ---------------------------------------------------- |
| `.md`           | `text/markdown`         | `text/markdown; variant=GFM` | Bare `text/markdown` doesn't say *which* markdown () |
| `.yaml`, `.yml` | `text/yaml`, or nothing | `application/yaml`           | `text/yaml` is the pre-registration spelling ( §5)   |

Everything else keeps whatever the host already decided. This list corrects a lookup, it isn't a second MIME table. A test asserts that the `.md` entry and the parser's declared `mediaType` agree, because they live in files that can't import each other.

## Format capabilities

The block declares *what* the class handles; the class's [capability methods](/docs/extending/extensions/capabilities) declare *how*. Five roles belong to the `format` block:

| Role        | Signature                                                     | Consumers                                   |
| ----------- | ------------------------------------------------------------- | ------------------------------------------- |
| `parse`     | `(source, options?) → JxDocument`                             | compiler, server, Studio (open file)        |
| `serialize` | `(doc, options?) → string`                                    | Studio (save), site build (export sidecars) |
| `rewrite`   | `(source, edits) → string`                                    | the rename refactor (repair a reference)    |
| `discover`  | `(source, { baseDir }) → string[]`                            | content loading (list entry files)          |
| `load`      | `(path, { schema, directiveOptions }) → ContentLoaderEntry[]` | content loading (parse one source)          |

A format implements the subset it needs: a read-only format can ship `parse` without `serialize` (Studio then opens files in this format read-only in structural modes); a data-only format like `Csv` needs `discover`/`load` but has no reason to be a page format.

### `rewrite`: repairing a reference without round-tripping

`serialize` promises a lot: that a parsed document turns back into source your author would recognize. A data format often cannot promise it. Re-emitting a CSV means picking a quoting style, a line ending and a column order the author already picked, and the loader has no opinion about any of them.

But a rename does not need a document back. It needs one cell's text changed. That is what `rewrite` is:

```ts&#x20;shiki
```

You are handed the file's own text and a list of authored values to replace, and you return the text with exactly those values replaced and every other byte preserved. Two rules make it safe:

- **Match whole values, never substrings.**`hero.jpg` must not rewrite the middle of `my-hero.jpg`.
- **Change nothing else.** Padding, quoting and line endings are the author's.

Declare it and the rename refactor repairs references living in your format instead of reporting them as something the author has to fix by hand. Declare both and the refactor prefers `serialize`, because a full round trip can express a change a list of value edits cannot, such as renaming a custom-element tag.

Note

`rewrite`
&#x20;is not a weaker&#x20;
`serialize`
, and the two are not ranked. Declare either, both, or neither. Only&#x20;
`serialize`
&#x20;makes your format creatable and convertible in Studio;&#x20;
`rewrite`
&#x20;earns nothing but the refactor, which is exactly what a load-only format wants.

The `Markdown` class implements all four, plus the standard instance `resolve()`, so `{ "$prototype": "Markdown", "src": "./about.md" }` works as runtime state, satisfying the same [external class contract](/docs/extending/extensions/classes) as every other class.

## How the pipeline dispatches

Hosts never hard-code file types. Each one builds a format registry from the enabled extensions' manifests and routes by extension:

- **Pages and components discovery**: the site build and dev server glob for `.json` plus every extension whose format declares the matching `documentKind`, then call `parse` on non-JSON matches. This is why adding a Markdown page is just dropping `pages/about.md` in a parser-enabled project.
- **Content loading**: a `content` section entry names a format (or derives it from the source's file extension); the loader calls `discover` to list entry files, then `load` per file, validating each entry against the content type's schema. See [Content collections](/docs/framework/site/content-collections).
- **Studio editing**: opening a claimed file calls `parse` to get the Jx tree the canvas edits; saving calls `serialize`. When a capability's `timing` excludes the browser, Studio round-trips through the dev server's `POST /__studio/format` endpoint instead of importing the implementation ([Studio routes](/docs/extending/reference/studio-routes)).
- **Export sidecars**: with `exportTarget: true`, the build serializes each page into the format next to its HTML output, and links to it from the page's `<head>` with `rel="alternate"` and the format's `mediaType`, so a reader of the HTML can find it. A format with no `mediaType` is exported but not advertised.

## Studio hints

Format classes describe their Studio control surface declaratively in a top-level `$studio` block. Studio interprets this data generically and never hard-codes per-format element sets. From `Markdown.class.json`, abbreviated:

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

- `icon`: file icon in the Files panel.
- `modes`: which canvas modes the format supports.
- `documentMode`: whether files open as prose content or as components, with an optional frontmatter-based override (here: a hyphenated `tagName` means "this .md file defines a custom element").
- `newFileTemplate`: the seed content for **New File** in this format.
- `elements`: the allowlist and nesting constraints gating structural editing, covering which tags the element picker offers, what may nest where, and which are void or text-only.

### What declaring both capabilities buys you

Studio derives two of its surfaces from `parse` and `serialize` rather than from any list of format names, so a format extension reaches both by declaring them:

- **The New File format picker** offers your extension when some installed class declares BOTH `parse` and `serialize` for it. Both are needed: without `parse` the file cannot be opened after it is created, and without `serialize` its first save falls through to another format and writes that format's bytes into it. (This is why the parser extension's `Csv`, which parses rows and has no serializer, is not offered; a `.csv` is still creatable through the picker's **Other…** row. `Csv` declares `rewrite` instead, which buys it the refactor and not this picker.)
- **Convert Format…** offers your format as a conversion endpoint when it declares both capabilities **and**`page` or `component` in `documentKinds`. That membership is what says `parse` returns a Jx document rather than content entries, and the compiler already relies on it to build its page and component globs, so there is no separate declaration to make.

`.json` is the endpoint both surfaces share, because no registry ever claims it.

One more generic hint applies to any class, not just formats: `$studio.stateDefaults`, an object merged into state entries Studio creates for the prototype. The connector's `TableQuery` sets `{ "timing": "client" }` so Studio-created queries default to browser resolution.

## Related

- [Tutorial: a TOML format extension](/docs/extending/extensions/tutorial-toml-format): build a working format end to end
- [Capability methods](/docs/extending/extensions/capabilities): timing and the options contract
- [Content collections](/docs/framework/site/content-collections): the consumer of `discover`/`load`
- [Jx Markdown](/docs/framework/site/jx-markdown): what the reference format's dialect looks like

✕

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.
