# What is a contract

> One shared definition of a Kismet contract — what is in it, what is out of it, the requirement levels, the substitution rule, and the three customization levels.




A **contract** is the set of necessary behaviors a component needs to serve a
guest. How you build them is up to you.

It can also recommend behaviors (SHOULD) and rule some out (MUST NOT).

The contract is defined once, in the SDK catalog. Kismet Elements is **one
implementation** of that catalog, not the definition of it. Your own UI can be
another.

## What is in a contract

A contract holds only requirements. Each requirement carries a requirement level
from [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119). The levels are defined
by consequence, not by testability:

| Level | Consequence if ignored | Checked by |
|---|---|---|
| MUST | Something breaks, or your site ends up with a limited feature set. | The conformance suite; a failure is an error. A MUST is only real if code enforces it: every MUST names a registered check that a runner evaluator implements, and the contract lint fails on a MUST with no check or on a check nobody runs. An unenforceable rule is a SHOULD, not a MUST. |
| SHOULD | What Kismet recommends as best practice; skip it and the site still works fully. Skipping needs a documented deviation ([RFC 2119 §6](https://www.rfc-editor.org/rfc/rfc2119#section-6)). | The conformance suite where a check exists; a gap is a warning. Unchecked SHOULDs are marked **not yet checked**. |
| MUST NOT | Doing it breaks something. | The conformance suite; a violation is an error. Like a MUST, every MUST NOT names an implemented check, and lint fails otherwise. |

Everything the contract does not say is **MAY** — free space. Layout, markup,
animation, framework, and visual design are never in a contract.

Read as a designed object, a contract has three families of requirements, in the
vocabulary of [Design by Contract](https://en.wikipedia.org/wiki/Design_by_contract)
(Meyer, 1992):

- the declared props and data the implementation needs up front are the
  **precondition surface**;
- the `must.*` families state what must hold after rendering and interaction —
  **postconditions**;
- `mustNot` entries are **invariants**: they hold in every state, on every render.

The checks run on the rendered page; there is no runtime assertion machinery.

## What is out of a contract

- **The look.** Brand tokens, CSS, and theme are configuration, not requirements.
- **The packaging.** Install methods, source files, and emitted events belong to
  an Element manifest, not to the contract.
- **The data types.** DTOs and entity shapes are entities — see
  `@kismet-tech/sdk/contracts` for types and the glossary for why that entry
  point is not the contract catalog.

## The substitution rule

Any implementation that satisfies a contract's requirements is **substitutable**
for any other ([Liskov & Wing, 1994](https://www.cs.cmu.edu/~wing/publications/LiskovWing94.pdf)).
That is the swap rule in one sentence: replace a certified page with your own
component, or a component with fully custom UI, and whatever you put in its place
takes over that contract — the same requirements, the same conformance suite,
the same data.

## Per-contract documentation shape

Every contract is documented with three tables, in the shape
[WAI-ARIA §5.2](https://www.w3.org/TR/wai-aria-1.2/#host_general_conf) uses for
roles — required, supported, prohibited. For `property-card`:

**Required**

| Requirement | Level | Check |
|---|---|---|
| Show the rental name | MUST | Field bound in DOM |
| Show a lead image with alt text | MUST | `img` + `alt` |
| Activating the card opens the canonical property URL | MUST | Link `href` |

**Supported**

| Requirement | Level | Check |
|---|---|---|
| Show the indicative nightly price when present | SHOULD | Warning only |
| Use brand slots for color and type | SHOULD | Warning only |

**Prohibited**

| Requirement | Level | Check |
|---|---|---|
| Show a price as bookable without a dated quote | MUST NOT | Scenario check |
| Claim the contract without rendering its observable behavior | MUST NOT | Scenario check |

## The three customization levels

You can adopt Kismet at three depths. The contract stays constant through all
three; only the implementation changes.

1. **Drop-in page** — install a certified Kismet page and configure it. Fastest
   path; the implementation is Kismet's.
2. **Drop-in components** — install certified components (fixtures) into your own
   pages and swap them one at a time.
3. **Fully custom** — build your own UI on SDK data, marked with
   `data-kismet-contract`, graded by the same suite.

Walking 1 → 3 is the developer applying the
[strangler fig](https://martinfowler.com/bliki/StranglerFigApplication.html)
pattern to their own site: each swap happens behind the contract, which is the
seam. Because substitution holds, the guest experience requirements never move.

## Where to go next

- [The browse channel](https://developers.kismet.travel/sdk/browse-channel.md) — the `browse-channel` and
  `map-view` contracts: the results.* actions, one state owner, and the
  island-sends / receivers-react rule.
- [The search island](https://developers.kismet.travel/sdk/search-island.md) — the `search-island` contract:
  the headless `useSearchIsland` hook, stay settings that live only in the
  canonical stay URL, the collapsed summary pill, and scope-aware
  availability.
- [The canonical stay URL](https://developers.kismet.travel/sdk/stay-query.md) — the `stay-query` contract: one
  stay query format, the `StayUrlParam` enum, the helpers and hook, and the
  two gates that make compliance required.
- [Contract glossary](https://developers.kismet.travel/sdk/contracts-glossary.md) — every term named after the
  spec, book, or product it comes from.
- [Recipes, contracts, and implementation tests](https://developers.kismet.travel/sdk/recipes.md) — declare
  implementations and run the suite.
- ADR 0001 — why the contract is defined in the SDK and why a fourth requirement
  level was rejected: `docs/adr/0001-one-contract-defined-in-the-sdk.md`.
