Skip to content
KismetKismetDevelopers
llms.txt

Recipes, contracts, and implementation tests

View .md

Recipes let a custom site keep its own routes, components, JSX, and CSS while proving that the finished experience still works. The declaration belongs on the component subtree that implements the behavior. It is not inferred from a page filename, so a recipe may live in a page, a shared component, a modal, or a layout.

Term Meaning Example
Contract One replaceable, observable capability A property card identifies and opens one rental.
Recipe A complete user outcome composed from contracts, API operations, and flows A curated group row contains only that group’s property cards.
Implementation Your stable name for the component subtree that provides the behavior website/curated-group-row

Kismet Elements will implement the same SDK contracts automatically. If you build custom UI, declare the recipe and its contracts directly. Both paths are graded against the same outcomes.

This example declares curated-groups in a reusable row component. It also binds the visible group description and each property card to exact SDK data.

// Documentation example for thoughts/ledgers/LEDGER-kismet-recipe-conformance.md.
import { Kismet } from '@kismet-tech/sdk/react';
import type {
BookableProductGroup,
VacationRentalSummary,
} from '@kismet-tech/sdk/contracts';
export function PropertyGroupRow({
group,
rentals,
}: {
group: BookableProductGroup;
rentals: readonly VacationRentalSummary[];
}) {
return (
<Kismet.Recipe
as="section"
recipe="curated-groups"
implementation="website/curated-group-row"
subject={group}
>
<Kismet.Contract
contract="property-group"
implementation="website/curated-group-row"
subject={group}
>
<Kismet.Field
as="h2"
entity={group}
field="name"
implementation="website/curated-group-row/name"
/>
<Kismet.Field
as="p"
entity={group}
field="description"
implementation="website/curated-group-row/description"
transform={Kismet.transforms.trim}
/>
<Kismet.Field
as="p"
entity={group}
field="memberCount"
implementation="website/curated-group-row/member-count"
render={(memberCount) => `${memberCount} stays`}
/>
<ul>
{rentals.map((rental) => (
<Kismet.Contract
as="li"
key={rental.id}
contract="property-card"
implementation="website/property-card"
subject={rental}
>
<Kismet.Field
as="h3"
entity={rental}
field="name"
implementation="website/property-card/name"
/>
<Kismet.Field
entity={rental}
field="media.hero.url"
implementation="website/property-card/lead-image"
render={(leadImageUrl) =>
leadImageUrl ? (
<img src={leadImageUrl} alt={rental.name} />
) : null
}
/>
<Kismet.Field
entity={rental}
field="slug"
implementation="website/property-card/link"
render={(rentalSlug) => (
<a href={`/properties/${rentalSlug}`}>View stay</a>
)}
/>
</Kismet.Contract>
))}
</ul>
</Kismet.Contract>
</Kismet.Recipe>
);
}

Kismet.Field records the entity type, stable entity ID, exact property path, source kind, implementation ID, and named transforms in rendered metadata. A browser extension or coding agent can therefore distinguish “edit this group description” from “change this component’s typography.” A transform such as Kismet.transforms.trim changes presentation without hiding that the source is still bookableProductGroup.description.

Use Kismet.Derived when visible output combines multiple source fields. Do not claim a direct field binding for calculated or locally authored text.

Customize without weakening the base contract

Section titled “Customize without weakening the base contract”

Styling and component composition are unrestricted. To add requirements for a reusable custom implementation, extend a base contract through the recipes entry point:

import {
extendKismetContract,
getKismetContract,
} from '@kismet-tech/sdk/recipes';
const propertyCardContract = getKismetContract('property-card');
if (!propertyCardContract) throw new Error('Missing property-card contract.');
export const premiumPropertyCardContract = extendKismetContract(
propertyCardContract,
{
id: 'website/premium-property-card',
version: '1.0.0',
title: 'Premium property card',
additionalProhibited: ['Do not hide the canonical property link.'],
}
);

Extensions may add fields, dependencies, acceptance criteria, and prohibitions. They cannot remove or weaken the base requirements. Define a new independent contract if the behavior is genuinely different.

Terminal window
npx kismet recipes explain
npx kismet recipes explain --recipe curated-groups

The explanation prints, in plain language, the expected outcome, evidence used to prove it, and the negative control the grader must reject. The shipped catalog currently contains 37 recipes (23 runner-tested) and 76 executable criteria, including configured checkout handoffs and privacy-safe property sharing.

For the configured-checkout recipe, follow Integrate Kismet Checkout. It tests selected-stay handoff and re-quoting, not payment or reservation confirmation. Keep the checkout product, its payment rail, and any reviewed partner-engine integration separate from this URL-level contract.

Install the browser once:

Terminal window
npx playwright install chromium

Run the app with deterministic fixture data and test every declared recipe:

Terminal window
npx kismet recipes test --data fixtures

Run one recipe, keep testing after source changes, or inspect the browser:

Terminal window
npx kismet recipes test --recipe curated-groups --output .kismet/artifacts
npx kismet recipes dev --recipe curated-groups
npx kismet recipes test --recipe curated-groups --headed

Pass --url http://127.0.0.1:3000 to test an app server you already started. Without --url, the runner starts the local Next.js app and the deterministic test-data server. --data test (the default) serves local test data; --data live talks to the hosted API with either a TEST or a LIVE key; --data fixtures is a deprecated alias of --data test. The flag never changes the pass condition to a fixed portfolio size.

The runner discovers internal routes, finds declarations anywhere in the rendered component tree, observes SDK operations, checks browser and HTTP errors, evaluates the recipe scenarios, and can save screenshots plus a Playwright trace. Exit 0 means the implementation passed, 1 means the app failed a criterion, and 2 means the test infrastructure failed.

npx kismet init writes agent guidance and a kismet-check.yml workflow. The workflow installs Chromium and runs npx kismet verify --env production — one scorecard that aggregates the site check (kismet check) and the recipe suite (kismet recipes test), so a site failing site/llms-txt cannot ship with green recipes. Keep that deterministic fixture gate required on pull requests; use a bounded TEST-key smoke check separately for hosted image and schema compatibility.

The deterministic checks should own facts code can prove: data membership, links, exact field provenance, API operations, structured data, Markdown twins, llms.txt, browser errors, and flow state. Use a model judge only for a criterion whose correct outcome is genuinely qualitative, and keep its plain-language rubric and evidence visible beside the deterministic criteria.