@joy-dom/spec
TypeScript types and JSON Schema for the Joy DOM document format.
@joy-dom/spec is the source of truth for what Joy DOM documents may contain. It exports a Zod schema, the inferred TypeScript types, and a published JSON Schema file. Renderers and tooling consume these.
For the behavioral spec (selectors, resolution order, breakpoints), see Specification. This page covers the programmatic surface.
Install
bun add @joy-dom/specTop-level exports
SpecSchema
A Zod schema for the full document. Use it to validate any object claiming to be a Joy DOM document.
const = .();
if (.) {
const : Spec = .;
} else {
.(.);
}Two calling forms:
SpecSchema.parse(value)- throws aZodErroron failure.SpecSchema.safeParse(value)- returns{ success, data | error }.
Spec
TypeScript type inferred from SpecSchema. Shape:
type Spec = {
version: 1;
style: Record<string, Style>;
breakpoints: Breakpoint[];
layout: Node;
};Node
A discriminated union covering the supported node types.
type Node = TextNode | ImageNode | BlockNode | CustomNode;
type TextNode = {
type: "p" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
props?: NodeProperties;
children?: PrimitiveValue[];
};
type ImageNode = {
type: "img";
props: NodeProperties & { src: string; alt?: string };
};
type BlockNode = {
type: "div";
props?: NodeProperties;
children?: (Node | PrimitiveValue)[];
};
type CustomNode<Props = unknown> = {
type: `${string}-${string}`; // kebab-case
props?: NodeProperties & Props;
children?: (Node | PrimitiveValue)[];
};
type PrimitiveValue = string | number | null;NodeProperties
The common subset of fields every node may carry:
type NodeProperties = {
id?: string;
className?: string[];
style?: Style;
};Style
A record of supported style properties. The shape matches §5 Properties; see that section for value tables and inheritance.
Breakpoint
type Breakpoint = {
conditions: MediaQuery[];
nodes: Record<string, Partial<NodeProperties>>;
style: Record<string, Style>;
};MediaQuery
A discriminated union over condition types:
type MediaQuery =
| { type: "type"; value: "print" }
| {
type: "feature";
name: "width";
value: number;
operator?: ">" | "<" | ">=" | "<=";
unit: "px";
}
| { type: "feature"; name: "orientation"; value: "landscape" | "portrait" }
| { op: "and" | "or"; conditions: MediaQuery[] }
| { op: "not"; condition: MediaQuery };See §6.2 Conditions for the human-readable description.
Helpers
isCustomElementName(value)
Returns true if value is a string matching the WHATWG custom-element-name rules (§3.6). Use this when accepting arbitrary type strings from external input.
import { } from "@joy-dom/spec";
("contact-button"); // true
("Button"); // false (not lowercase, no hyphen)
("annotation-xml"); // false (reserved)JSON Schema
The package ships a JSON Schema for the full document at dist/schema.json. Use it from non-JS tools - editors with JSON Schema support, OpenAPI pipelines, validation CLIs.
# Build the JSON Schema artifact
bun --filter @joy-dom/spec build:schemaOther Zod schemas
For when you need to validate a fragment rather than the whole document:
| Export | Validates |
|---|---|
StyleSchema | A single Style record (e.g. an inline style). |
NodeSchema | A single Node (any variant). |
ChildNodeSchema | A Node or a PrimitiveValue. |
BreakpointSchema | A single breakpoint object. |
MediaQuerySchema | A single media query. |
LengthSchema | A Length<unit> object. |
NodePropertiesSchema | Just the common node props (id, className, …). |
Why Zod?
Zod gives one definition that produces both a runtime validator and a TypeScript type. The
exported types you import from @joy-dom/spec are the validator output, so they cannot drift from
what the schema accepts.
Where next
- Specification - what each type represents semantically.
@joy-dom/react- the consumer that takes these types as input.