Skip to content
nooh
Esc
↑↓navigate↵open⌘Jpreview
On this page

Schemas & Standard Schema

Using Standard Schema compliant libraries like Zod, Valibot, and ArkType in Nooh.

Nooh adopts the Standard Schema specification (~standard). This means you are not locked into any single validation library — any schema library implementing Standard Schema works out of the box with zero glue code.

Supported Libraries

Zod

The standard in TypeScript schema validation with rich ecosystem support.

Valibot

Modular, tree-shakeable schema library with a tiny bundle footprint.

ArkType

Blazing fast, 1 TypeScript syntax string-based validator.

Defining Schemas

Here is how you define schemas using popular libraries:

import { z } from "zod";

export const CreateUserSchema = z.object({
  name: z.string().min(2).max(50),
  email: z.string().email(),
  role: z.enum(["admin", "member"]).default("member"),
});

export type CreateUserInput = z.infer<typeof CreateUserSchema>;
import * as v from "valibot";

export const CreateUserSchema = v.object({
  name: v.pipe(v.string(), v.minLength(2), v.maxLength(50)),
  email: v.pipe(v.string(), v.email()),
  role: v.optional(v.picklist(["admin", "member"]), "member"),
});

export type CreateUserInput = v.InferOutput<typeof CreateUserSchema>;
import { type } from "arktype";

export const CreateUserSchema = type({
  name: "2 <= string <= 50",
  email: "email",
  "role?": "'admin' | 'member'",
});

export type CreateUserInput = typeof CreateUserSchema.infer;

Standard Schema Contract

Under the hood, Nooh inspects the ~standard property on provided schema objects:

export interface NoohStandardSchema {
  readonly "~standard": {
    readonly validate: (value: never, ...args: never[]) => unknown;
    readonly types?: {
      readonly input?: unknown;
      readonly output?: unknown;
    };
  };
}

This guarantees full compile-time type inference for your handler inputs (c.req.valid(...)) and outputs without runtime adapter overhead.

Was this page helpful?