Plugin Contract Guide

Plugin Contract Guide

Plugin Contract Guide

Plugin DeveloperPlugin Developer Agent Kit — documentation written for AI agents, readable by humans.

For the full contract syntax, decision tree, and examples, see the shared Contract Authoring Guide.

This file covers plugin-specific contract concerns. Contracts (.jay-contract files) are the source of truth for a component's data shape. Define the contract before implementing the component.

Basic Structure

name: ProductCard
description: Displays a single product with price and add-to-cart. Use for product grids and featured sections.
props:
  - name: productId
    type: string
    required: true
    description: The product to display
params:
  slug: string
tags:
  - tag: name
    type: data
    dataType: string
    phase: slow

Tag Types

data — Read-only values

- tag: productName
  type: data
  dataType: string # string (default), html-string, number, boolean, date
  required: true # optional, defaults to false
  phase: slow # slow, fast, or fast+interactive
  description: Display name

variant — Enum/boolean for conditionals

- tag: status
  type: variant
  dataType: enum (AVAILABLE | OUT_OF_STOCK | PREORDER)
  phase: fast+interactive

interactive — Element refs for user interaction

- tag: addToCart
  type: interactive
  elementType: HTMLButtonElement # HTMLAnchorElement, HTMLInputElement, HTMLSelectElement, etc.

Interactive tags are always fast+interactive — do not specify a phase.

A tag can be both data and interactive:

- tag: quantityInput
  type: [data, interactive]
  dataType: number
  elementType: HTMLInputElement

sub-contract — Nested objects

Inline:

- tag: pricing
  type: sub-contract
  tags:
    - tag: amount
      type: data
      dataType: number
    - tag: currency
      type: data
      dataType: string

Linked (reference another contract file):

- tag: author
  type: sub-contract
  link: ./author.jay-contract # relative path (same package)

For dynamic/materialized contracts linking to static contracts in a plugin package, use the package path:

- tag: gallery
  type: sub-contract
  link: '@my-org/my-plugin/media-gallery' # package path (cross-directory)

sub-contract with repeated: true — Arrays

- tag: items
  type: sub-contract
  repeated: true
  trackBy: id # Required: identifies each item
  phase: fast
  tags:
    - tag: id
      type: data
      dataType: string
    - tag: name
      type: data
      dataType: string

trackBy must reference a data tag with string or number type within the same sub-contract.

Async Data

Wrap any tag in Promise<T> with async: true:

- tag: reviews
  type: data
  async: true
  dataType: string # Compiles to Promise<string>

- tag: relatedProducts
  type: sub-contract
  repeated: true
  trackBy: id
  async: true # Compiles to Promise<Array<...>>
  tags:
    - tag: id
      type: data
      dataType: string

Rendering Phases

Each tag has a phase that determines when its data is available:

Phase When Use For
slow Build time (SSG) Static content, SEO data, product names
fast Request time (SSR) Per-request data, live pricing, stock
fast+interactive Request + client Data that also updates on the client

How to choose:

  • Can the data be known at build time? Use slow
  • Does it change per request (user, time, session)? Use fast
  • Does it also update on the client after interaction? Use fast+interactive
  • Interactive tags (refs) are always fast+interactive

Phase rules for arrays: Child phases must be >= parent phase. If the array is fast, all children must be fast or later.

Props vs Params

Props — Component configuration

Props are passed by the parent component or jay-html template. Use for component inputs like IDs, configuration flags, display options.

props:
  - name: productId
    type: string
    required: true
    description: The product to display
  - name: showPricing
    type: boolean
    default: 'true'

Params — URL route segments

Params come from dynamic route segments ([slug], [[lang]], [...path]). Use for page-level routing data.

params:
  slug: string # required — from [slug]
  lang: string? # optional — from [[lang]]
  path: string[] # catch-all — from [...path]

Description Field

Always include a description at the contract level explaining when to use this contract:

name: product-search
description: Product listing with filters, sorting, and pagination. Use for search results and category pages.

Tag Metadata

Tags can carry a meta field — a free-form key-value map for plugin validators. The framework ignores meta; only validators read it.

- tag: heroImage
  type: data
  dataType: string
  meta:
    vendor: wix-image
    defaultTransform: w_800,h_400,q_80

Use meta to attach semantic meaning that goes beyond the data type — e.g., marking a string tag as a URL that requires specific formatting. See validation.md for writing validators that consume meta.

Validation Rules

  • Tag names must be unique at each level
  • repeated: true requires trackBy
  • trackBy must reference a data tag with string or number type
  • Interactive tags cannot have an explicit phase
  • Sub-contracts must have either tags (inline) or link (external), not both
  • Array children must have phase >= parent phase
  • Prop names must be unique

About this document

This page is part of the Jay Stack Agent Kit — documentation generated from the framework source and written primarily for AI agents. The language and structure are optimized for machine consumption — expect precise, specification-style prose rather than narrative documentation. Learn more about the Agent Kit →