Skip to main content


Frourio uses zod for validation; see the documentation at the link above for a definition of the zod schema.

Two Types of Validators

Frourio provides two types of validators: Controller-level Validators and Directory-level Validators. The elements that can be validated in each are different.

  • Controller-level Validators: called at the current endpoints. params cannot be validated.
    • query
    • headers
    • body
  • Directory-level Validators: called at the current and subordinate endpoints. Only params can be validated.
    • params


See the Routing page for a reference on defineController().

[(target key)]?: z.object({ ... })

The validators is an object whose keys are the same as RequestParams (query, headers or body) and whose values are zod object schemas (z.object()).

Each schemas are checked for consistency with the API type definition using z.ZodType.

server/api/[email protected]/index.ts
import { DefineMethods } from 'aspida';
import { Fuga, Res } from '$/types';

export type Methods = DefineMethods<{
get: {
resBody: string;
post: {
reqBody: {
hogeString: string;
fugaObject: Fuga;
piyoBoolean?: boolean;
query: {
length?: number;
resBody: Res;
server/api/[email protected]/controller.ts
import { defineController } from './$relay';
import { z } from 'zod';

export default defineController(() => ({
get: () => ({ status: 200, body: 'Hello' }),
post: {
validators: {
query: z.object({
length: z.number().optional(),
body: z.object({
hogeString: z.string(),
fugaObject: z.object({ ... }),
piyoBoolean: z.boolean().optional(),
handler: async ({ params: { id }, body, query: { length } }) => {
const res = await createBaz(id, body, length);
if (!res) return { status: 400 };
return { status: 201, body: res };


To define directory-level validators, create validators.ts at the top of the target directory, and use the function defineValidators exported by ./$relay.ts .

If there are multiple directory-level validators affecting to the endpoint, they are converted to an intersection type using .and.


Frourio automatically creates validators.ts when a directory with a path parameter in its name is created.

server/api/[email protected]/validators.ts
import { defineValidators } from './$relay';
import { z } from 'zod';

export default defineValidators(() => ({
params: z.object({ id: z.string() }),

Function defineValidators

Argument Type

  • function (fastify: FastifyInstance) => { params: (zod object schema) }

The actual type definition of (zod object schema) is z.ZodType<{ (params type) }>, but there is no need to be aware of this. This ensures consistency with the API type definitions.

{ (params type) }

The type definition of the URL parameter that the directory has. It does not include that of the upper-level directory. If unspecified, it will be string, but as noted on Automatic Validation page, it is recommended that it be specified.