[{"data":1,"prerenderedAt":1078},["ShallowReactive",2],{"content-\u002Fdocs\u002Fschemas\u002Fcontract":3},{"id":4,"title":5,"body":6,"description":1058,"extension":1059,"meta":1060,"metaRows":1061,"navigation":87,"path":1073,"seo":1074,"source":1075,"stem":1076,"__hash__":1077},"docs\u002Fdocs\u002Fschemas\u002Fcontract.md","The schema contract",{"type":7,"value":8,"toc":1042},"minimark",[9,13,20,23,26,31,34,53,159,162,166,169,174,213,349,370,374,377,415,422,426,429,517,529,533,544,634,652,656,663,751,754,758,768,829,836,840,849,865,872,876,892,896,899,978,981,984,988,991,1005,1011,1015,1038],[10,11,5],"h1",{"id":12},"the-schema-contract",[14,15,16],"blockquote",{},[17,18,19],"p",{},"A schema declares a value's shape, types, constraints, and transformations. One declaration drives validation, type inference, defaults, and metadata, all from the same source.",[21,22],"docs-meta-table",{},[17,24,25],{},"This page is the mental model for what a schema is and what it lets you do. The rest of the Schemas cluster takes each capability one at a time with side-by-side schema-and-result demos.",[27,28,30],"h2",{"id":29},"what-a-schema-is","What a schema is",[17,32,33],{},"A schema is a declarative description of data. It states what keys exist, what types they hold, how they nest, which values are valid, and which transformations apply on the way in or out. A single declaration carries the answer to every question about the data's shape.",[17,35,36,37,45,46,52],{},"Different schema libraries take different approaches: parser-combinators, classes, descriptor objects, type-only signatures. Attaform is schema-agnostic at its core, consuming any object that implements the ",[38,39,41],"a",{"href":40},"#schema-agnostic-core",[42,43,44],"code",{},"AbstractSchema"," contract. Out of the box, ",[38,47,51],{"href":48,"rel":49},"https:\u002F\u002Fzod.dev",[50],"nofollow","Zod"," is the canonical adapter. Zod v4 is the default; Zod v3 is one import away.",[54,55,60],"pre",{"className":56,"code":57,"language":58,"meta":59,"style":59},"language-ts shiki shiki-themes github-light github-dark","import { z } from 'zod'\n\nconst schema = z.object({\n  email: z.email(),\n  age: z.number().int().min(13),\n})\n","ts","",[42,61,62,82,89,112,124,153],{"__ignoreMap":59},[63,64,67,71,75,78],"span",{"class":65,"line":66},"line",1,[63,68,70],{"class":69},"szBVR","import",[63,72,74],{"class":73},"sVt8B"," { z } ",[63,76,77],{"class":69},"from",[63,79,81],{"class":80},"sZZnC"," 'zod'\n",[63,83,85],{"class":65,"line":84},2,[63,86,88],{"emptyLinePlaceholder":87},true,"\n",[63,90,92,95,99,102,105,109],{"class":65,"line":91},3,[63,93,94],{"class":69},"const",[63,96,98],{"class":97},"sj4cs"," schema",[63,100,101],{"class":69}," =",[63,103,104],{"class":73}," z.",[63,106,108],{"class":107},"sScJk","object",[63,110,111],{"class":73},"({\n",[63,113,115,118,121],{"class":65,"line":114},4,[63,116,117],{"class":73},"  email: z.",[63,119,120],{"class":107},"email",[63,122,123],{"class":73},"(),\n",[63,125,127,130,133,136,139,141,144,147,150],{"class":65,"line":126},5,[63,128,129],{"class":73},"  age: z.",[63,131,132],{"class":107},"number",[63,134,135],{"class":73},"().",[63,137,138],{"class":107},"int",[63,140,135],{"class":73},[63,142,143],{"class":107},"min",[63,145,146],{"class":73},"(",[63,148,149],{"class":97},"13",[63,151,152],{"class":73},"),\n",[63,154,156],{"class":65,"line":155},6,[63,157,158],{"class":73},"})\n",[17,160,161],{},"That schema is the artifact every dimension below describes. Attaform reads it once and derives validation, defaults, types, and reactive surfaces from it.",[27,163,165],{"id":164},"what-a-schema-declares","What a schema declares",[17,167,168],{},"A schema covers six dimensions. Each one stands on its own; the rest of the Schemas cluster takes each in depth.",[170,171,173],"h3",{"id":172},"shape","Shape",[17,175,176,177,180,181,180,184,180,187,180,190,180,193,196,197,180,200,180,203,180,206,180,209,212],{},"The structural skeleton: which keys exist, what types they hold, how they nest. Zod composes shape through ",[42,178,179],{},"z.object",", ",[42,182,183],{},"z.array",[42,185,186],{},"z.tuple",[42,188,189],{},"z.record",[42,191,192],{},"z.discriminatedUnion",[42,194,195],{},"z.enum",", and the primitives (",[42,198,199],{},"z.string",[42,201,202],{},"z.number",[42,204,205],{},"z.boolean",[42,207,208],{},"z.date",[42,210,211],{},"z.bigint",").",[54,214,216],{"className":56,"code":215,"language":58,"meta":59,"style":59},"const schema = z.object({\n  profile: z.object({\n    name: z.string(),\n    interests: z.array(z.string()),\n  }),\n  notify: z.discriminatedUnion('channel', [\n    z.object({ channel: z.literal('email'), address: z.email() }),\n    z.object({ channel: z.literal('sms'), phone: z.string() }),\n  ]),\n})\n",[42,217,218,232,241,251,267,272,288,315,338,344],{"__ignoreMap":59},[63,219,220,222,224,226,228,230],{"class":65,"line":66},[63,221,94],{"class":69},[63,223,98],{"class":97},[63,225,101],{"class":69},[63,227,104],{"class":73},[63,229,108],{"class":107},[63,231,111],{"class":73},[63,233,234,237,239],{"class":65,"line":84},[63,235,236],{"class":73},"  profile: z.",[63,238,108],{"class":107},[63,240,111],{"class":73},[63,242,243,246,249],{"class":65,"line":91},[63,244,245],{"class":73},"    name: z.",[63,247,248],{"class":107},"string",[63,250,123],{"class":73},[63,252,253,256,259,262,264],{"class":65,"line":114},[63,254,255],{"class":73},"    interests: z.",[63,257,258],{"class":107},"array",[63,260,261],{"class":73},"(z.",[63,263,248],{"class":107},[63,265,266],{"class":73},"()),\n",[63,268,269],{"class":65,"line":126},[63,270,271],{"class":73},"  }),\n",[63,273,274,277,280,282,285],{"class":65,"line":155},[63,275,276],{"class":73},"  notify: z.",[63,278,279],{"class":107},"discriminatedUnion",[63,281,146],{"class":73},[63,283,284],{"class":80},"'channel'",[63,286,287],{"class":73},", [\n",[63,289,291,294,296,299,302,304,307,310,312],{"class":65,"line":290},7,[63,292,293],{"class":73},"    z.",[63,295,108],{"class":107},[63,297,298],{"class":73},"({ channel: z.",[63,300,301],{"class":107},"literal",[63,303,146],{"class":73},[63,305,306],{"class":80},"'email'",[63,308,309],{"class":73},"), address: z.",[63,311,120],{"class":107},[63,313,314],{"class":73},"() }),\n",[63,316,318,320,322,324,326,328,331,334,336],{"class":65,"line":317},8,[63,319,293],{"class":73},[63,321,108],{"class":107},[63,323,298],{"class":73},[63,325,301],{"class":107},[63,327,146],{"class":73},[63,329,330],{"class":80},"'sms'",[63,332,333],{"class":73},"), phone: z.",[63,335,248],{"class":107},[63,337,314],{"class":73},[63,339,341],{"class":65,"line":340},9,[63,342,343],{"class":73},"  ]),\n",[63,345,347],{"class":65,"line":346},10,[63,348,158],{"class":73},[17,350,351,352,180,356,180,360,364,365,369],{},"Shape is the substrate every other dimension builds on. The per-construct deep dives live at ",[38,353,355],{"href":354},"\u002Fdocs\u002Fschemas\u002Fnested-objects","Nested objects",[38,357,359],{"href":358},"\u002Fdocs\u002Fschemas\u002Farrays-and-tuples","Arrays & tuples",[38,361,363],{"href":362},"\u002Fdocs\u002Fschemas\u002Frecords","Records & maps",", and ",[38,366,368],{"href":367},"\u002Fdocs\u002Fschemas\u002Fdiscriminated-unions","Discriminated unions",".",[170,371,373],{"id":372},"type-safety","Type safety",[17,375,376],{},"Every key, every leaf, every nested path carries a TypeScript type derived from the declaration. The schema is the single thing the type system reads; inference flows outward from there.",[54,378,380],{"className":56,"code":379,"language":58,"meta":59,"style":59},"type Account = z.infer\u003Ctypeof schema>\n\u002F\u002F { profile: { name: string; interests: string[] }, notify: ... }\n",[42,381,382,409],{"__ignoreMap":59},[63,383,384,387,390,392,395,397,400,403,406],{"class":65,"line":66},[63,385,386],{"class":69},"type",[63,388,389],{"class":107}," Account",[63,391,101],{"class":69},[63,393,394],{"class":107}," z",[63,396,369],{"class":73},[63,398,399],{"class":107},"infer",[63,401,402],{"class":73},"\u003C",[63,404,405],{"class":69},"typeof",[63,407,408],{"class":73}," schema>\n",[63,410,411],{"class":65,"line":84},[63,412,414],{"class":413},"sJ8bj","\u002F\u002F { profile: { name: string; interests: string[] }, notify: ... }\n",[17,416,417,418,421],{},"No manual generics, no ",[42,419,420],{},"any",", no reaching for plumbing whenever a field is added or renamed.",[170,423,425],{"id":424},"validation","Validation",[17,427,428],{},"Refinements declare which values are valid. A predicate runs against a parsed value and either passes or attaches an error.",[54,430,432],{"className":56,"code":431,"language":58,"meta":59,"style":59},"const password = z\n  .string()\n  .min(8, 'At least 8 characters')\n  .refine((s) => \u002F[A-Z]\u002F.test(s), 'Needs an uppercase letter')\n",[42,433,434,446,456,475],{"__ignoreMap":59},[63,435,436,438,441,443],{"class":65,"line":66},[63,437,94],{"class":69},[63,439,440],{"class":97}," password",[63,442,101],{"class":69},[63,444,445],{"class":73}," z\n",[63,447,448,451,453],{"class":65,"line":84},[63,449,450],{"class":73},"  .",[63,452,248],{"class":107},[63,454,455],{"class":73},"()\n",[63,457,458,460,462,464,467,469,472],{"class":65,"line":91},[63,459,450],{"class":73},[63,461,143],{"class":107},[63,463,146],{"class":73},[63,465,466],{"class":97},"8",[63,468,180],{"class":73},[63,470,471],{"class":80},"'At least 8 characters'",[63,473,474],{"class":73},")\n",[63,476,477,479,482,485,489,492,495,498,501,504,506,509,512,515],{"class":65,"line":114},[63,478,450],{"class":73},[63,480,481],{"class":107},"refine",[63,483,484],{"class":73},"((",[63,486,488],{"class":487},"s4XuR","s",[63,490,491],{"class":73},") ",[63,493,494],{"class":69},"=>",[63,496,497],{"class":80}," \u002F",[63,499,500],{"class":97},"[A-Z]",[63,502,503],{"class":80},"\u002F",[63,505,369],{"class":73},[63,507,508],{"class":107},"test",[63,510,511],{"class":73},"(s), ",[63,513,514],{"class":80},"'Needs an uppercase letter'",[63,516,474],{"class":73},[17,518,519,520,523,524,528],{},"Refinements can be asynchronous. ",[42,521,522],{},"z.string().refine(async (v) => await api.isAvailable(v))"," awaits the predicate before parsing settles. Synchronous predicates run eagerly; asynchronous ones await before submit dispatches. ",[38,525,527],{"href":526},"\u002Fdocs\u002Fvalidation\u002Fwhen-validation-runs","When validation runs"," covers the timing model.",[170,530,532],{"id":531},"transformation","Transformation",[17,534,535,536,539,540,543],{},"Two stages within parse can transform a value. ",[42,537,538],{},"z.preprocess(fn, T)"," normalizes the input before the inner schema sees it. ",[42,541,542],{},".transform(fn)"," converts the validated value to the wire format.",[54,545,547],{"className":56,"code":546,"language":58,"meta":59,"style":59},"z.preprocess((v) => (typeof v === 'string' ? v.trim() : v), z.string())\n\nz.string().transform((s) => s.toLowerCase())\n",[42,548,549,603,607],{"__ignoreMap":59},[63,550,551,554,557,559,562,564,566,569,571,574,577,580,583,586,589,592,595,598,600],{"class":65,"line":66},[63,552,553],{"class":73},"z.",[63,555,556],{"class":107},"preprocess",[63,558,484],{"class":73},[63,560,561],{"class":487},"v",[63,563,491],{"class":73},[63,565,494],{"class":69},[63,567,568],{"class":73}," (",[63,570,405],{"class":69},[63,572,573],{"class":73}," v ",[63,575,576],{"class":69},"===",[63,578,579],{"class":80}," 'string'",[63,581,582],{"class":69}," ?",[63,584,585],{"class":73}," v.",[63,587,588],{"class":107},"trim",[63,590,591],{"class":73},"() ",[63,593,594],{"class":69},":",[63,596,597],{"class":73}," v), z.",[63,599,248],{"class":107},[63,601,602],{"class":73},"())\n",[63,604,605],{"class":65,"line":84},[63,606,88],{"emptyLinePlaceholder":87},[63,608,609,611,613,615,618,620,622,624,626,629,632],{"class":65,"line":91},[63,610,553],{"class":73},[63,612,248],{"class":107},[63,614,135],{"class":73},[63,616,617],{"class":107},"transform",[63,619,484],{"class":73},[63,621,488],{"class":487},[63,623,491],{"class":73},[63,625,494],{"class":69},[63,627,628],{"class":73}," s.",[63,630,631],{"class":107},"toLowerCase",[63,633,602],{"class":73},[17,635,636,637,180,640,180,643,646,647,651],{},"Both fire at parse time (",[42,638,639],{},"handleSubmit",[42,641,642],{},"validate",[42,644,645],{},"validateAsync","); storage holds the consumer's raw input verbatim. ",[38,648,650],{"href":649},"\u002Fdocs\u002Fschemas\u002Fstorage-shape","How values are stored"," walks the implications.",[170,653,655],{"id":654},"metadata","Metadata",[17,657,658,659,662],{},"Labels, descriptions, placeholders, and free-form annotations live on the schema itself. ",[42,660,661],{},"withMeta"," attaches them at any node.",[54,664,666],{"className":56,"code":665,"language":58,"meta":59,"style":59},"import { withMeta } from 'attaform\u002Fzod'\n\nconst schema = z.object({\n  email: withMeta(z.email(), {\n    label: 'Email address',\n    description: \"We'll only use it for receipts.\",\n    placeholder: 'you@example.com',\n  }),\n})\n",[42,667,668,680,684,698,712,723,733,743,747],{"__ignoreMap":59},[63,669,670,672,675,677],{"class":65,"line":66},[63,671,70],{"class":69},[63,673,674],{"class":73}," { withMeta } ",[63,676,77],{"class":69},[63,678,679],{"class":80}," 'attaform\u002Fzod'\n",[63,681,682],{"class":65,"line":84},[63,683,88],{"emptyLinePlaceholder":87},[63,685,686,688,690,692,694,696],{"class":65,"line":91},[63,687,94],{"class":69},[63,689,98],{"class":97},[63,691,101],{"class":69},[63,693,104],{"class":73},[63,695,108],{"class":107},[63,697,111],{"class":73},[63,699,700,703,705,707,709],{"class":65,"line":114},[63,701,702],{"class":73},"  email: ",[63,704,661],{"class":107},[63,706,261],{"class":73},[63,708,120],{"class":107},[63,710,711],{"class":73},"(), {\n",[63,713,714,717,720],{"class":65,"line":126},[63,715,716],{"class":73},"    label: ",[63,718,719],{"class":80},"'Email address'",[63,721,722],{"class":73},",\n",[63,724,725,728,731],{"class":65,"line":155},[63,726,727],{"class":73},"    description: ",[63,729,730],{"class":80},"\"We'll only use it for receipts.\"",[63,732,722],{"class":73},[63,734,735,738,741],{"class":65,"line":290},[63,736,737],{"class":73},"    placeholder: ",[63,739,740],{"class":80},"'you@example.com'",[63,742,722],{"class":73},[63,744,745],{"class":65,"line":317},[63,746,271],{"class":73},[63,748,749],{"class":65,"line":340},[63,750,158],{"class":73},[17,752,753],{},"Metadata travels with the schema; UI that consumes it reads from the declaration directly.",[170,755,757],{"id":756},"defaults","Defaults",[17,759,760,763,764,767],{},[42,761,762],{},".default(x)"," declares the value a field takes when no input is supplied. ",[42,765,766],{},".catch(x)"," declares a fallback for parse failures.",[54,769,771],{"className":56,"code":770,"language":58,"meta":59,"style":59},"const schema = z.object({\n  priority: z.string().default('normal'),\n  remember: z.boolean().default(true),\n})\n",[42,772,773,787,806,825],{"__ignoreMap":59},[63,774,775,777,779,781,783,785],{"class":65,"line":66},[63,776,94],{"class":69},[63,778,98],{"class":97},[63,780,101],{"class":69},[63,782,104],{"class":73},[63,784,108],{"class":107},[63,786,111],{"class":73},[63,788,789,792,794,796,799,801,804],{"class":65,"line":84},[63,790,791],{"class":73},"  priority: z.",[63,793,248],{"class":107},[63,795,135],{"class":73},[63,797,798],{"class":107},"default",[63,800,146],{"class":73},[63,802,803],{"class":80},"'normal'",[63,805,152],{"class":73},[63,807,808,811,814,816,818,820,823],{"class":65,"line":91},[63,809,810],{"class":73},"  remember: z.",[63,812,813],{"class":107},"boolean",[63,815,135],{"class":73},[63,817,798],{"class":107},[63,819,146],{"class":73},[63,821,822],{"class":97},"true",[63,824,152],{"class":73},[63,826,827],{"class":65,"line":114},[63,828,158],{"class":73},[17,830,831,835],{},[38,832,834],{"href":833},"\u002Fdocs\u002Fschemas\u002Fdefaults","Defaults from the schema"," covers how declared defaults seed initial values and which operations re-apply them.",[27,837,839],{"id":838},"zod-adapters","Zod adapters",[17,841,842,845,846,848],{},[42,843,844],{},"attaform\u002Fzod"," wraps Zod v4 and is the canonical import for new projects. It walks the schema once at construction, caches structural metadata, and implements ",[42,847,44],{}," against Zod's runtime.",[54,850,852],{"className":56,"code":851,"language":58,"meta":59,"style":59},"import { useForm } from 'attaform\u002Fzod'\n",[42,853,854],{"__ignoreMap":59},[63,855,856,858,861,863],{"class":65,"line":66},[63,857,70],{"class":69},[63,859,860],{"class":73}," { useForm } ",[63,862,77],{"class":69},[63,864,679],{"class":80},[17,866,867,868,871],{},"For projects still on Zod v3, swap the import: ",[42,869,870],{},"attaform\u002Fzod-v3",". The consumer-facing surface is identical; the parsing engine and metadata walker differ to match v3's internals.",[27,873,875],{"id":874},"schema-agnostic-core","Schema-agnostic core",[17,877,878,879,882,883,885,886,891],{},"The core package (",[42,880,881],{},"attaform",") doesn't import Zod. It consumes any object that implements ",[42,884,44],{},", a small contract covering identity, defaults, shape introspection, and validation. The Zod adapters cover the bulk of real-world schemas; reach for ",[38,887,889],{"href":888},"\u002Fdocs\u002Fschemas\u002Fabstract-schema",[42,890,44],{}," directly when you're wiring Valibot, ArkType, Effect Schema, or a hand-rolled validator.",[27,893,895],{"id":894},"refinements-vs-transforms","Refinements vs. transforms",[17,897,898],{},"Refinements and transforms look adjacent but answer different questions.",[54,900,902],{"className":56,"code":901,"language":58,"meta":59,"style":59},"\u002F\u002F Refinement: runs at validate, doesn't change the value\nz.string().refine((s) => \u002F[a-z]\u002F.test(s), 'Needs a lowercase letter')\n\n\u002F\u002F Transform: runs at parse, changes the value\nz.string().transform((s) => s.toLowerCase())\n",[42,903,904,909,945,949,954],{"__ignoreMap":59},[63,905,906],{"class":65,"line":66},[63,907,908],{"class":413},"\u002F\u002F Refinement: runs at validate, doesn't change the value\n",[63,910,911,913,915,917,919,921,923,925,927,929,932,934,936,938,940,943],{"class":65,"line":84},[63,912,553],{"class":73},[63,914,248],{"class":107},[63,916,135],{"class":73},[63,918,481],{"class":107},[63,920,484],{"class":73},[63,922,488],{"class":487},[63,924,491],{"class":73},[63,926,494],{"class":69},[63,928,497],{"class":80},[63,930,931],{"class":97},"[a-z]",[63,933,503],{"class":80},[63,935,369],{"class":73},[63,937,508],{"class":107},[63,939,511],{"class":73},[63,941,942],{"class":80},"'Needs a lowercase letter'",[63,944,474],{"class":73},[63,946,947],{"class":65,"line":91},[63,948,88],{"emptyLinePlaceholder":87},[63,950,951],{"class":65,"line":114},[63,952,953],{"class":413},"\u002F\u002F Transform: runs at parse, changes the value\n",[63,955,956,958,960,962,964,966,968,970,972,974,976],{"class":65,"line":126},[63,957,553],{"class":73},[63,959,248],{"class":107},[63,961,135],{"class":73},[63,963,617],{"class":107},[63,965,484],{"class":73},[63,967,488],{"class":487},[63,969,491],{"class":73},[63,971,494],{"class":69},[63,973,628],{"class":73},[63,975,631],{"class":107},[63,977,602],{"class":73},[17,979,980],{},"Refinements ask \"is this value acceptable?\" Transforms ask \"given this value, what should the next stage see?\" Schemas stack both in any order; the order matters at validate \u002F parse time.",[17,982,983],{},"The split is intentional. Refinements drive live feedback as users type; transforms shape the wire format on the way out.",[27,985,987],{"id":986},"fingerprinting","Fingerprinting",[17,989,990],{},"Every schema carries a structural fingerprint: a short string that changes when the shape changes (adding or removing a field, changing a leaf type, restructuring nesting) but stays stable under refinement, transform, or metadata tweaks. The fingerprint surfaces in two places:",[992,993,994,998],"ul",{},[995,996,997],"li",{},"Persistence keys (a schema change auto-invalidates stale drafts).",[995,999,1000,1001,1004],{},"Shared-key form mismatches in dev (two ",[42,1002,1003],{},"useForm({ key: 'x' })"," calls with different schemas warn).",[17,1006,1007,1010],{},[42,1008,1009],{},"schema.fingerprint()"," lives on the adapter; the runtime calls it when needed.",[27,1012,1014],{"id":1013},"where-to-next","Where to next",[992,1016,1017,1026,1031],{},[995,1018,1019,1021,1022,1025],{},[38,1020,834],{"href":833},": how ",[42,1023,1024],{},".default()"," declarations flow into initial values.",[995,1027,1028,1030],{},[38,1029,650],{"href":649},": the per-wrapper read-shape policy.",[995,1032,1033,1037],{},[38,1034,1036],{"href":1035},"\u002Fdocs\u002Fschemas\u002Foptional-nullable","Optional, nullable, defaulted",": three modifiers, three different meanings.",[1039,1040,1041],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":59,"searchDepth":84,"depth":84,"links":1043},[1044,1045,1053,1054,1055,1056,1057],{"id":29,"depth":84,"text":30},{"id":164,"depth":84,"text":165,"children":1046},[1047,1048,1049,1050,1051,1052],{"id":172,"depth":91,"text":173},{"id":372,"depth":91,"text":373},{"id":424,"depth":91,"text":425},{"id":531,"depth":91,"text":532},{"id":654,"depth":91,"text":655},{"id":756,"depth":91,"text":757},{"id":838,"depth":84,"text":839},{"id":874,"depth":84,"text":875},{"id":894,"depth":84,"text":895},{"id":986,"depth":84,"text":987},{"id":1013,"depth":84,"text":1014},"A schema declares the shape, constraints, and transformations of a value. Attaform is schema-agnostic at the core and ships first-class Zod adapters.","md",{},[1062,1065,1068,1070],{"label":1063,"value":1064},"Category","Conceptual",{"label":1066,"value":1067,"kind":42},"Default adapter","attaform\u002Fzod (Zod v4)",{"label":1069,"value":870,"kind":42},"Also shipped",{"label":1071,"value":1072,"kind":42},"Custom","AbstractSchema contract","\u002Fdocs\u002Fschemas\u002Fcontract",{"title":5,"description":1058},null,"docs\u002Fschemas\u002Fcontract","yLVoPO2dxgXukOtMtlJwCXssI2L8pGgRjhZyBGmOVuo",1780949757017]