Zod

Zod is a TypeScript-first schema validation library with a fluent API.

Installation

npm install zod

Basic Schema

nuxt.config.ts
import { z } from 'zod'

const runtimeConfigSchema = z.object({
  public: z.object({
    apiBase: z.string(),
    appName: z.string().optional(),
  }),
  databaseUrl: z.string(),
  secretKey: z.string(),
  port: z.number().optional(),
})

export default defineNuxtConfig({
  modules: ['nuxt-safe-runtime-config'],

  runtimeConfig: {
    databaseUrl: process.env.DATABASE_URL || '',
    secretKey: process.env.SECRET_KEY || '',
    port: Number.parseInt(process.env.PORT || '3000'),
    public: {
      apiBase: process.env.NUXT_PUBLIC_API_BASE || 'https://api.example.com',
      appName: 'My App',
    },
  },

  safeRuntimeConfig: {
    $schema: runtimeConfigSchema,
  },
})

Common Patterns

Required vs Optional

z.object({
  required: z.string(),                    // must exist
  optional: z.string().optional(),         // can be undefined
  withDefault: z.number().default(3000),   // default if undefined
  nullable: z.string().nullable(),         // can be null
})

String Validations

z.object({
  email: z.string().email(),
  apiUrl: z.string().url(),
  token: z.string().min(32),
  slug: z.string().regex(/^[a-z-]+$/),
  trimmed: z.string().trim(),
})

Number Validations

z.object({
  port: z.number().int().min(1).max(65535),
  timeout: z.number().nonnegative(),
  ratio: z.number().positive(),
})

Enums

z.object({
  environment: z.enum(['development', 'staging', 'production']),
  logLevel: z.enum(['debug', 'info', 'warn', 'error']),
})

Nested Objects

z.object({
  public: z.object({
    api: z.object({
      baseUrl: z.string(),
      version: z.string(),
    }),
  }),
  redis: z.object({
    host: z.string(),
    port: z.number(),
  }),
})

Transforms

Zod supports transforms, but they're only used for type inference, not runtime transformation:

z.object({
  // Type will be inferred as string
  apiKey: z.string().transform(s => s.trim()),
})

Full Example

nuxt.config.ts
import { z } from 'zod'

const runtimeConfigSchema = z.object({
  public: z.object({
    apiBase: z.string().url(),
    appName: z.string(),
    environment: z.enum(['development', 'staging', 'production']),
  }),
  database: z.object({
    url: z.string(),
    poolSize: z.number().optional(),
  }),
  auth: z.object({
    jwtSecret: z.string().min(32),
    sessionTtl: z.number().positive(),
  }),
  email: z.object({
    host: z.string(),
    port: z.number().int().positive(),
    from: z.string().email(),
  }).optional(),
})

export default defineNuxtConfig({
  modules: ['nuxt-safe-runtime-config'],
  safeRuntimeConfig: { $schema: runtimeConfigSchema },
})