Skip to content
AtMyApp Docs
Go to AtMyApp
Open with AI

Field types and options

Import s from @atmyapp/structure (also re-exported by @atmyapp/core). Builders take an options object; nested builders take named fields, items, values, or variants properties.

This reference describes the SDK source in this repository. An option can describe editor or storage behavior without being enforced by the local content validator. Do not treat display hints as validation guarantees.

These options are available on every field. Use them only where their semantics apply.

Option Meaning and behavior
description Human-readable purpose, constraints, or writing guidance
optional true allows the field to be absent; default is required
required Alternative requiredness flag; false makes it optional. Prefer optional and avoid conflicting flags
default Default/placeholder value of the expected shape; does not backfill all existing content
localize Localize string or MDX leaves; invalid on other field kinds
unique Uniqueness declaration; cross-entry checks need platform context
ui Advanced editor metadata record; not a set of guaranteed portable controls
storage Advanced storage metadata record
legacy Compatibility metadata for compilation; avoid in new schemas unless integrating legacy definitions

Optional means missing, not automatically nullable. To accept explicit null, use a union with s.enum({ values: [null] }).

s.string({ min: 1, max: 100, placeholder: "A clear headline" });
s.shortText({ description: "A one-line summary" });
s.longText({ max: 600 });
s.markdown({ localize: false });
s.email({ optional: true });
s.url();
Builder Defaults added to s.string()
string No format or length default
shortText format: 'short', preferredLength: 80, localize: true
longText format: 'long', preferredLength: 280, localize: true
markdown format: 'markdown', preferredLength: 1200, localize: true
email format: 'email'
url format: 'url'
Option Meaning
min, max Aliases for minimum/maximum string length
minLength, maxLength Explicit lengths; take precedence over aliases
pattern Regular-expression source string, checked by local validation
enumValues Allowed scalar values; prefer s.enum for a dedicated choice field
format short, long, markdown, email, url, slug, code, textarea, date, datetime, timestamp, or an integration-defined string
preferredLength Writing/editor hint, not a hard limit
placeholder, examples Input guidance; not stored default content

The local scalar validator checks type, length, pattern, and enumValues. A format alone does not locally validate an email, URL, or Markdown document. Use s.slug() for managed URL identifiers rather than format: 'slug'. Render Markdown with your application’s Markdown pipeline; plain strings are not trusted HTML.

s.number({ min: 0, max: 100, step: 0.5 });
s.integer({ min: 1, default: 1 });
s.number({ format: "currency", description: "Price in EUR" });

min/max map to minimum/maximum; explicit bounds win. integer: true adds an integer format and step 1 unless overridden. s.integer() defaults to integer: true, format: 'integer', and step: 1. Formats include integer, percent, and currency; specify units in the description.

step and integer formatting are hints: the local numeric validator checks type and bounds, not divisibility or integrality. enumValues restricts allowed values. Scalar options such as placeholder, examples, and preferredLength exist in the shared type but do not add numeric validation.

s.boolean({ default: false });
s.enum({ values: [null] });
s.union({ variants: [s.string(), s.enum({ values: [null] })] });

Use booleans for a real on/off choice. There is no dedicated s.null() builder; a single-value null enum accepts only null. Both support common options; extra scalar hints on boolean do not change its value type.

s.date({ optional: true });
s.datetime();
s.timestamp();

Each builder produces its corresponding scalar and format. Values are strings in the canonical validator and inferred SDK types, not JavaScript Date objects. Choose a consistent representation in your content, such as 2026-09-14 for a date and an ISO timestamp with a timezone for an instant. The local validator checks string type, not calendar validity or timezone interpretation. Bounds and formatting metadata do not implement a date-range validator.

s.enum({ values: ["draft", "published"], default: "draft" });
s.union({ variants: [s.string(), s.number()] });

enum.values accepts string, number, boolean, or null literals. union.variants is a list of field definitions; a value must match at least one variant. Keep choices understandable for editors. Both builders accept the common options.

s.object({
additionalProperties: false,
fields: { label: s.string(), href: s.url() },
});

fields defines child properties. additionalProperties: false rejects undeclared properties during local validation; leaving it unset does not reject them. Optional children use their own optional option. Localize leaves, not the object.

s.array({ items: s.string(), minItems: 1, maxItems: 5 });
Option Meaning
items Required field definition for each value
minItems, maxItems Bounds checked by local validation
identityField Stable non-localized scalar key in object items; required when objects contain localized descendants
uniqueItems Uniqueness metadata; the local validator does not enforce duplicate removal

Use localized array identities when applicable. Array order is its stored sequence; s.order() is for collection entries.

s.image({
config: { optimizeFormat: "webp", ratioHint: { x: 16, y: 9 } },
});
s.file({
accept: ["application/pdf"],
config: { contentType: "application/pdf" },
});
s.gallery({ optional: true });

image and file are single assets. gallery is a multiple-image asset. Stored canonical values are asset-reference strings, or arrays of strings for galleries; they are not binary file contents. Render through your media/storage integration. Submission uploads have separate binary handling in the Core SDK.

Option Meaning
accept Accepted media-type hints
config.optimizeFormat Image output preference: webp or none
config.optimizeLoad Image load preference: progressive or none
config.ratioHint Suggested { x, y } aspect ratio
config.maxSize Suggested { width, height } dimensions
config.contentType File content-type configuration
imageOptions Advanced image configuration record
deletePolicy detach or delete asset lifecycle metadata
orphanPolicy allow or delete orphan lifecycle metadata

These settings describe asset handling; the local string-shape validator does not resize images, inspect MIME bytes, or delete files. Confirm backend support before relying on lifecycle metadata for cleanup.

s.reference("authors");
s.reference({ target: "posts", by: "slug", multiple: true, optional: true });
Option Meaning
target Required definition name in the same schema
multiple Store multiple references instead of one
by Defaults to id; collections support id or slug
onDelete Defaults to restrict; collections require restrict
targetField Present in generic types, but unsupported for collection references

Slug references require the target to expose a field named slug built with s.slug(). Generic types also contain by: 'path' and deletion modes nullify/cascade; these are not valid collection-reference configurations. Local value validation checks strings; resolving targets and preventing broken links requires platform context. The SDK does not automatically expand references into related objects.

s.slug({ source: "title" });

A slug is a stable URL identifier of at most 96 lowercase letters, numbers, and single hyphens. Defaults are unique: true, generated: true, immutable: true, and updatePolicy: 'immutable'.

source identifies the source field used for generation. generated controls generation metadata. The generic types expose immutable and updatePolicy, but the schema validator rejects mutable slugs, unique: false, and updatePolicy: 'on_change'. Editing a title should not unexpectedly break an existing page URL.

s.order();
s.order({ groupBy: "category" });

Order fields must be top-level collection fields. groupBy, when set, must name a single-value reference field in that collection. Values are safe integer ranks. Use the platform’s ordering operations instead of inventing concurrent rank updates in a public website.

s.mdx({ config: "article" });

config names a required entry in the schema’s mdx map:

const mdx = {
article: {
description: "Article content with approved callouts.",
components: {
Callout: {
description: "A highlighted note.",
props: { tone: "string" },
},
},
},
};

Pass that map as mdx to defineSchema. MDX values are strings. The configuration describes available components; your website must provide the renderer and implementations. Local validation checks the string and configuration reference, not arbitrary code safety. Only allow the components and execution behavior your application intends to support.