# kompot

> The server describes a screen as a tree of components, the client renders it, and a new screen ships without a client release. Open hierarchies, KSP registration, forms, theming, and two conformance kits.

Page: https://kotlin.website/kompot

## Why it exists

Backend-driven UI usually arrives as a sealed hierarchy of every widget the product happens to
have: a client that must be released whenever the server learns a new component, and a
serialiser that turns an unfamiliar type into a crash. kompot inverts that. The core knows
about a tree, actions, modifiers and design tokens — nothing about what a "product card" is —
and everything concrete is a plug-in module. An unknown type degrades to a placeholder rather
than taking the screen down, and the degradation is reported to a sink the deployment owns.

## What you get

- **Open contracts** — `KompotComponent`, `KompotAction`, `FieldValue` and `ValidationRule`
  are interfaces; the application assembles the concrete set.
- **One annotation** — `@KompotComponentMarker`, and KSP writes the polymorphic registration
  and the renderer entry.
- **Forms** — validation, visibility and cross-field rules run client-side; a server-relevant
  change asks for a targeted patch, and a server-computed value lands in a bound read-only
  field rather than an editable one.
- **Server-driven theming** over open string tokens, down to text colour.
- **Per-user live updates** — a screen names its own channel.
- **Wizards as pure functions** — `(session, transition, draft) -> session`.
- **Compose renderers** for the standard, form, wizard and image components, plus a Material3
  design system with surface roles a brand overrides.
- **A screen editor** — `kompot-studio` opens a body beside the renderers that will draw it,
  in the consumer's own brand frame, with findings from the schema, the rules, the vocabulary
  and the render itself; see [the write-up](https://kotlin.website/blog/a-screen-editor-for-backend-driven-ui).

## Install

```kotlin
repositories { maven("https://reposilite.kotlin.website/snapshots") }

val kompotVersion = "0.33.1.88"

dependencies {
    implementation(platform("io.github.youndie:kompot-bom:$kompotVersion"))
    implementation("io.github.youndie:kompot-core")
    implementation("io.github.youndie:kompot-standard")
    implementation("io.github.youndie:kompot-ktor")
}
```

A version carries the CI run number, so any two publishes differ; the BOM makes a mixed pair
of versions impossible to write down.

## The wire is a specification

The JSON Schema of every protocol module is generated from the very `SerialDescriptor`s the
responses are encoded with, and both the schemas and the written specification travel inside
the published artefact — the numbered rules resolve from the jar, by id. Two conformance kits
hold the two sides: `kompot-tck` walks a running server over HTTP with twelve checks, and
`kompot-client-tck` is a corpus of eighteen cases any client answers through a seven-operation
adapter, with a coverage report naming the rules nothing holds yet. Every release is read back
from the repository by [proba](https://github.com/youndie/proba), and the verdict badge is
written by the run that published it.

## Limitations

- Your own components need your own renderers; the SwiftUI side is yours entirely.
- The live-update transport (SSE or WebSocket) is the application's.
- Business validation belongs to the server; the client highlights the field a refusal names.
- The Compose half pairs Compose Multiplatform 1.11.1 with material3 `1.11.0-alpha07`; mixing
  Compose lines fails at runtime, not at resolution.
- `iosX64` is unreachable for the Compose renderers — `compose.runtime` stopped publishing it.
  Device and Apple-silicon simulator targets are covered; the protocol modules carry all three
  iOS targets.
