jx
JSON-based Web App Platform
Install / Use
npx skills add jxsuite/jxInstalls into whichever agent you are using.
Claude Commands
Claude Code slash commands
Quality Score
Category
Content & MediaSupported Platforms
Skill content
View source on GitHubAuthor a Jx project component, page, layout, or project configuration based on the user's request: $ARGUMENTS
You are authoring files for the Jx platform — a declarative, JSON-based web framework. All UI is described as JSON documents that map directly to DOM structure. Reactivity is powered by @vue/reactivity.
Three Schemas
Every Jx file validates against one of three JSON Schema 2020-12 documents:
- Component/Page/Layout (
$schema: "https://jxsuite.com/schema/v1") — UI documents - Project config (
$schema: "https://jxsuite.com/schema/project/v1") —project.json - Class definition (
$schema: "https://jxsuite.com/schema/class/v1") —.class.json
Read the generated schemas at packages/schema/schema.json, packages/schema/project-schema.json, and packages/schema/class-schema.json for the authoritative field reference.
Project Structure
my-site/
project.json # Required. Site config, global styles, collections, build settings
pages/ # File-based routing. Each .json = a route. [slug].json = dynamic
layouts/ # Shared page shells. Use { "tagName": "slot" } for content insertion
components/ # Reusable custom elements
content/ # Markdown/JSON content collections
public/ # Static assets copied to dist/
Files prefixed with _ in pages/ are excluded from routing.
Component Document (the core building block)
A Jx document is a JSON object describing a reactive web component:
{
"$schema": "https://jxsuite.com/schema/v1",
"$id": "TaskList",
"tagName": "task-list",
"$defs": { ... },
"state": { ... },
"style": { ... },
"children": [ ... ]
}
State — 5 shapes (detected by structure)
Shape 1 — Naked value (scalar, array, or plain object with no reserved keys):
"count": 0,
"items": [],
"user": { "name": "", "email": "" }
Shape 2 — Typed value (has default, optionally type):
"status": { "type": { "type": "string", "enum": ["idle", "loading"] }, "default": "idle" }
Shape 3 — Computed (string containing ${}):
"fullName": "${state.firstName} ${state.lastName}",
"itemCount": "${state.items.length} items"
Shape 4 — Function ($prototype: "Function"):
"increment": { "$prototype": "Function", "body": "state.count++" },
"handleInput": { "$prototype": "Function", "arguments": ["event"], "body": "state.value = event.target.value" },
"validate": { "$prototype": "Function", "$src": "./validators.js", "$export": "validateEmail" }
Shape 5 — Data source ($prototype: <ClassName>):
"userData": { "$prototype": "Request", "url": "/api/users", "method": "GET" },
"posts": { "$prototype": "ContentCollection", "contentType": "blog", "sort": { "field": "pubDate", "order": "desc" } }
$ref bindings
| Pattern | Example | Meaning |
| --------- | -------------------------------- | ------------------------------- |
| State | { "$ref": "#/state/count" } | Reactive binding to state |
| $defs | { "$ref": "#/$defs/TodoItem" } | Type definition reference |
| Parent | { "$ref": "parent#/theme" } | Prop from parent via $props |
| Map item | { "$ref": "$map/item" } | Current item in Array iteration |
| Map index | { "$ref": "$map/index" } | Current index |
| External | { "$ref": "./card.json" } | Another Jx component |
| Window | { "$ref": "window#/config" } | Window global |
Use ${} templates for inline one-off bindings. Use $ref objects for named/reused signals.
Children
Static: array of element objects or text strings:
"children": [
{ "tagName": "h1", "textContent": "Hello" },
{ "tagName": "p", "children": ["Welcome to ", { "tagName": "strong", "textContent": "Jx" }] }
]
Dynamic mapped list ($prototype: "Array"):
"children": {
"$prototype": "Array",
"items": { "$ref": "#/state/todos" },
"map": {
"tagName": "li",
"className": "${$map.item.done ? 'completed' : ''}",
"textContent": { "$ref": "$map/item/text" }
}
}
$switch / cases (dynamic component switching)
{
"$switch": { "$ref": "#/state/currentView" },
"cases": {
"home": { "$ref": "./views/home.json" },
"settings": { "$ref": "./views/settings.json" }
}
}
Style
camelCase CSS properties. Nested selectors via :, ., &, [ prefixes. Media breakpoints via @--name or @(query):
"style": {
"display": "flex",
"gap": "1rem",
"padding": "clamp(1rem, 3vw, 2rem)",
":hover": { "backgroundColor": "#f0f0f0" },
"&.active": { "borderColor": "blue" },
"@--md": { "flexDirection": "row" },
"@(prefers-reduced-motion: reduce)": { "transition": "none" }
}
Attributes
Non-IDL HTML attributes go in attributes:
{
"tagName": "a",
"href": "/about",
"attributes": { "aria-label": "About page", "data-section": "nav" }
}
Note: IDL properties like href, src, textContent, className, hidden, disabled, value, checked go directly on the element object, not inside attributes.
Event handlers
Reference a function from state:
{ "tagName": "button", "textContent": "Add", "onclick": { "$ref": "#/state/handleAdd" } }
$elements (custom element dependencies)
"$elements": [
{ "$ref": "./components/task-item.json" },
"@shoelace-style/shoelace/components/button/button.js"
]
Passing data to child components
Register the component in $elements (path relative to the current file), then use it by tag
name with props.* attributes — there is no $ref-in-children transclusion:
{
"$elements": [{ "$ref": "./components/user-card.json" }],
"children": [{ "tagName": "user-card", "attributes": { "props.name": "Ada" } }]
}
Page Documents
Pages are component documents with additional properties:
{
"title": "About Us",
"$layout": "./layouts/base.json",
"$head": [
{ "tagName": "meta", "attributes": { "name": "description", "content": "About our team" } }
],
"tagName": "main",
"children": [ ... ]
}
$layout— path to layout file, orfalsefor no layout. Omit to use project default.$head— merges with layout and project$head(page wins on conflicts).$paths— dynamic route generation from content collections.tagNameis optional on pages that use a layout.
Dynamic routes ([param].json)
{
"$paths": { "contentType": "blog", "param": "slug" },
"state": {
"post": {
"$prototype": "ContentEntry",
"contentType": "blog",
"id": { "$ref": "#/$params/slug" }
}
}
}
Layout Documents
Layouts wrap page content. Use { "tagName": "slot" } for the page content insertion point:
{
"tagName": "div",
"children": [
{ "tagName": "header", "children": [ ... ] },
{ "tagName": "main", "children": [{ "tagName": "slot" }] },
{ "tagName": "footer", "children": [ ... ] }
]
}
project.json
{
"name": "My Site",
"url": "https://example.com",
"defaults": { "layout": "./layouts/base.json", "lang": "en" },
"$head": [
{ "tagName": "link", "attributes": { "rel": "icon", "href": "/favicon.svg" } }
],
"$elements": [ ... ],
"imports": { "MarkdownCollection": "@jxsuite/parser/MarkdownCollection.class.json" },
"$media": { "--sm": "(min-width: 640px)", "--md": "(min-width: 768px)" },
"style": { "fontFamily": "system-ui, sans-serif", "margin": "0" },
"contentTypes": {
"blog": {
"source": "./content/blog/",
"schema": { "type": "object", "properties": { "title": { "type": "string" } }, "required": ["title"] }
}
},
"build": { "outDir": "./dist", "trailingSlash": "always" }
}
.class.json (Class Definitions)
{
"$prototype": "Class",
"title": "MyParser",
"$implementation": "./my-parser.js",
"$defs": {
"parameters": {
"src": { "identifier": "src", "type": { "type": "string" } }
},
"constructor": {
"role": "constructor",
"$prototype": "Function",
"parameters": [{ "$ref": "#/$defs/parameters/src" }]
},
"methods": {
"resolve": { "role": "method", "identifier": "resolve", "returnType": { "type": "object" } }
}
}
}
Authoring Rules
- Style is always an object of camelCase properties, never a CSS string.
- Text content: use
"textContent": "..."for leaf elements, or"children": ["text"]for mixed content. - IDL properties (
href,src,value,checked,disabled,hidden,className,textContent) go directly on the element. Non-IDL attributes (aria-*,data-*,role,slot) go in"attributes": {}. - Responsive sizing: prefer CSS
clamp()over media queries for simple responsive values. - Custom element names (component
tagName) must contain a hyphen per Web Components spec. $defscontains only JSON Schema type definitions — no functions, no runtime artifacts.- Template strings (
${}) are pure expressions — no statements, no assignments. - Function bodies are raw JS strings where
stateis the first implicit parameter. $headentries are{ tagName, attributes }objects, not HTML strings.- Layouts use
{ "tagName": "slot" }for content injection — not$slotor$content. - All state entries are reactive by default — no
signal: trueflag exists. - The
timingproperty ("compiler","server","client") controls when data sources resolve.
Related Skills
caveman
107.1k🪨 why use many token when few token do trick. Viral skill + proxy for coding agents that cuts 65% of tokens by talking like a caveman.
claude-mem
94.4kPersistent Context Across Sessions for Every Agent – Captures everything your agent does during sessions, compresses it with AI, and injects relevant context back into future sessions. Works with Claude Code, OpenClaw, Codex, Gemini, Hermes, Copilot, OpenCode + More
Agent-Reach
84.2kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
Understand-Anything
83.5kGraphs that teach > graphs that impress. Turn any code into an interactive knowledge graph you can explore, search, and ask questions about. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, and more.
Security Score
Audited on Sep 16, 2026
