Skip to content

API Schema Guide

This page expands the legacy $apiSchema placeholder into a practical guidance page for the new docs site.

What $apiSchema represents

$apiSchema is the schema-oriented layer of the server-data model.

While $api and generated SDKs focus on calling backend operations, $apiSchema focuses on the API metadata itself.

That matters when frontend behavior needs to be driven by schema, not just by returned values.

Why schema access matters

In the Cabloy/Zova model, schema metadata can support higher-level frontend behavior such as:

  • validation
  • automatic form rendering
  • automatic field behavior
  • metadata-driven UI logic

This is one reason the server-data thread in Zova is more powerful than a plain request library.

The generated and runtime path

A schema-driven frontend normally follows this contract path:

text
backend entity / DTO / controller metadata
  -> Swagger / OpenAPI
  -> generated API bean + API-schema bean + static types
  -> $api / $apiSchema / $sdk
  -> ModelResource when the API belongs to a reusable resource
  -> ZForm for schema-driven form runtime
  -> page/controller for local orchestration

Each layer has a different responsibility:

LayerResponsibility
Backend entity or inferred field contractReusable field meaning, validation, titles, ordering, and shared renderer metadata
Backend DTOOperation-specific request/response projection and composition
Generated $apiExecute a typed backend operation
Generated $apiSchemaExpose a named operation's schema-oriented facade
$sdkProvide the lower-level schema/query runtime used by schema facades and dynamic consumers
ModelResourceOwn reusable resource schema, query, mutation, cache, invalidation, and permission state
ZFormConsume a resolved schema and own form binding, validation, submission, and field rendering
Page/controllerCoordinate local page lifecycle and page-specific actions without duplicating shared contract or cache state

The generated API bean, API-schema bean, and static OpenAPI types are separate frontend surfaces for the same backend operation. Runtime schema metadata such as titles, renderer names, validation, and scene information is consumed through $apiSchema/$sdk; static request and response typing is consumed through the generated TypeScript types and $api methods.

Direct schema-driven form pattern

For a page-specific form whose request-body schema is already exposed by a generated API-schema bean, expose a getter that obtains the current facade, load its SDK query, and derive the schema reactively:

ts
get apiSchemasRegister() {
  return this.$apiSchema.homeUserPassport.register({ authToken: false });
}

protected async __init__() {
  await $QueryEnsureLoaded(() => this.apiSchemasRegister.sdk);
  this.schemaRegister = this.$computed(() => {
    return this.apiSchemasRegister.requestBody;
  });
}
tsx
<ZForm
  data={this.user}
  schema={this.schemaRegister}
  onSubmitData={data => this.submitRegister(data)}
  slotFooter={$form => {
    return <button type="submit">Register</button>;
  }}
></ZForm>

When ZForm receives a schema without a default body slot, it iterates the schema properties and resolves each field from the contract metadata. slotFooter is independent of body rendering, so page-specific submit actions can remain in the form without replacing automatic field rendering. Adding default children to the form changes the body path to explicit composition and should be reserved for manual or mixed forms.

Locale-aware schema lifetime

OpenAPI schema metadata can include localized titles, descriptions, validation messages, and renderer metadata. Obtain it through the current $apiSchema/$sdk runtime rather than retaining a one-time apiSchemas facade or requestBody snapshot across a locale change. A $computed only helps when its callback rereads a live getter or owning resource; wrapping a facade created before the locale change still reads that earlier schema.

Apply page-specific schema derivation in the same reactive callback:

ts
this.schemaPasswordSet = this.$computed(() => {
  return omitSchemaProperty(this.apiSchemasPasswordSet.requestBody, 'token');
});

This keeps both the source schema and the filtered view current. The same rule applies to pick, property ordering, or any other schema transformation. staleTime: Infinity is cache behavior within the selected runtime; it does not make a schema facade locale-neutral.

For a reusable resource, prefer the owning ModelResource to supply formSchema, formData, formMeta, and mutation policy. For a low-reuse page action with no shared query, cache, mutation, or invalidation state, the page controller may call the generated $api directly. A model should not wrap an API merely to add an extra indirection.

How to think about $apiSchema

Use $apiSchema when the frontend needs to inspect what the backend contract says, not just call the backend endpoint.

That usually means the problem is shifting from “fetch data” to “use metadata to drive behavior.”

One practical metadata-driven expression example

When schema-driven form or table rendering uses JSX/CEL evaluation, the runtime can resolve helper functions against the current scope.

For example, frontend CEL expressions can now use toFixed(value, precision) to keep a numeric value at the desired precision:

text
toFixed(getValue('price'), 2)

In the shared form/table CEL environment:

  • toFixed(...) returns a string with fixed decimal precision
  • getValue(name) reads the current field value or current row value from the active runtime scope
  • getProperty(name) reads the current schema property metadata from the active runtime scope

That is useful when the backend contract already owns the field metadata and the frontend only needs a thin expression layer for schema-driven display behavior.

If your next question is not only how expressions read schema-driven scope, but how backend-owned field metadata attaches live field-side behavior through ZovaRender.onEffect(...), ZovaEvent, and command chains, continue with Schema-Driven Field Effects Guide.

Read together with

Use this page together with:

Implementation checks for schema-driven UI changes

When asked to build dynamic forms, metadata-driven UI, or schema-aware validation, consider whether the right source is $apiSchema rather than hand-authored frontend-only field definitions.

That keeps the frontend closer to backend truth and reduces duplicate configuration.

Released under the MIT License.