Skip to main content
Chapinismos uses Zod for runtime validation of all word entries. This ensures data integrity and provides helpful error messages during development.

Schema Definition

The complete schema is defined in src/content/config.ts:3:
import { defineCollection, z } from "astro:content";

const wordsSchema = z.object({
  word: z.string(),
  meaning: z.string(),
  examples: z.array(z.string()),
  category: z.enum([
    "sustantivo",
    "verbo",
    "adjetivo",
    "adverbio",
    "expresión",
    "interjección",
    "modismo",
    "noun",
    "verb",
    "adjective",
    "adverb",
    "expression",
    "interjection",
    "idiom",
  ]),
  region: z.string().optional(),
  synonyms: z.array(z.string()).optional(),
  relatedWords: z.array(z.string()).optional(),
  featured: z.boolean().optional(),
});
This schema is used by both collections:
  • words-es - Spanish words
  • words-en - English words

Field Reference

Required Fields

word
string
required
The word or phrase being defined.Validation:
  • Must be a string
  • Cannot be empty
  • Can include accents and special characters
Valid examples:
word: "Patojo"
word: "Púchica"
word: "¡Aguas!"
Invalid examples:
word: 123           # Must be string
word: ""            # Cannot be empty
meaning
string
required
Complete definition of the word.Validation:
  • Must be a string
  • Cannot be empty
  • Should be a clear, concise explanation
Valid example:
meaning: "Niño o joven; persona de corta edad, usado comúnmente en Guatemala."
Invalid examples:
meaning: ["definition"]  # Must be string, not array
meaning: ""              # Cannot be empty
examples
array<string>
required
Array of usage examples showing the word in context.Validation:
  • Must be an array
  • Must contain at least one string
  • Each item must be a string
Valid examples:
examples:
  - "El patojo de la tienda siempre me ayuda."
  - "Cuando era patojo jugaba en la calle."
Invalid examples:
examples: "Just one example"    # Must be array
examples: []                     # Cannot be empty
examples:
  - "Example one"
  - 123                           # All items must be strings
category
enum
required
Grammatical category of the word. Must be one of the predefined values.Spanish values:
  • "sustantivo" - Noun
  • "verbo" - Verb
  • "adjetivo" - Adjective
  • "adverbio" - Adverb
  • "expresión" - Expression
  • "interjección" - Interjection
  • "modismo" - Idiom
English values:
  • "noun"
  • "verb"
  • "adjective"
  • "adverb"
  • "expression"
  • "interjection"
  • "idiom"
Valid examples:
category: "sustantivo"    # For Spanish collection
category: "noun"          # For English collection
category: "expresión"
Invalid examples:
category: "nombre"        # Not in enum
category: "Sustantivo"    # Case sensitive
category: sustantivo      # Must be quoted string

Optional Fields

region
string
Geographic region where the word is commonly used.Validation:
  • Optional field
  • Must be a string if provided
  • Defaults to “Guatemala” if omitted
Valid examples:
region: "Guatemala"
region: "Central America"
# Or omit entirely
Invalid examples:
region: ["Guatemala", "Honduras"]  # Must be string, not array
synonyms
array<string>
List of synonyms or similar words.Validation:
  • Optional field
  • Must be an array of strings if provided
  • Can be empty array
Valid examples:
synonyms: ["cuidado", "ojo"]
synonyms: ["cipote", "güiro"]
synonyms: []              # Empty is valid
# Or omit entirely
Invalid examples:
synonyms: "word1, word2"  # Must be array
synonyms:
  - "word1"
  - 123                    # All items must be strings
List of related words that might interest the reader.Validation:
  • Optional field
  • Must be an array of strings if provided
  • Can be empty array
Valid examples:
relatedWords: ["trucha", "pilas"]
relatedWords: ["güiro"]
# Or omit entirely
Invalid examples:
relatedWords: trucha      # Must be array
Whether to feature this word on the homepage.Validation:
  • Optional field
  • Must be a boolean if provided
  • Defaults to false if omitted
Only mark 6 words maximum as featured to avoid overwhelming the homepage.
Valid examples:
featured: true
featured: false
# Or omit entirely (defaults to false)
Invalid examples:
featured: "true"          # Must be boolean, not string
featured: 1               # Must be boolean, not number
featured: yes             # Must be true/false

Validation Errors

When validation fails, Astro provides detailed error messages to help you fix the issue.

Common Error Examples

Missing Required Field

**`word` is required**

You did not provide the required `word` field in the frontmatter.

File: src/content/words-es/example.md
Fix: Add the missing field:
---
word: "Example"
meaning: "..."
examples: [...]
category: "sustantivo"
---

Invalid Category

**Invalid enum value**

Received 'nombre', expected 'sustantivo' | 'verbo' | 'adjetivo' | ...

File: src/content/words-es/example.md
Fix: Use a valid category value:
---
category: "sustantivo"  # Not "nombre"
---

Wrong Type

**Expected array, received string**

File: src/content/words-es/example.md
Fix: Use array syntax:
# ❌ Wrong
examples: "Just one example"

# ✅ Correct
examples:
  - "Just one example"

Empty Array

**Array must contain at least 1 element(s)**

File: src/content/words-es/example.md
Fix: Add at least one example:
# ❌ Wrong
examples: []

# ✅ Correct
examples:
  - "At least one example"

Type Safety

The Zod schema provides full TypeScript type safety:
import type { CollectionEntry } from 'astro:content';

// TypeScript infers the correct types from the schema
type WordEntry = CollectionEntry<'words-es'>;

// TypeScript knows all valid properties
function displayWord(word: WordEntry) {
  const title = word.data.word;              // string
  const definition = word.data.meaning;      // string
  const examples = word.data.examples;       // string[]
  const category = word.data.category;       // enum type
  const region = word.data.region;           // string | undefined
  const featured = word.data.featured;       // boolean | undefined
  
  // TypeScript error - property doesn't exist
  // const invalid = word.data.author;
}

Validation at Build Time

Validation happens automatically during:
  1. Development mode (npm run dev)
    • Validates when you save files
    • Shows errors in the terminal
    • Hot-reloads after fixing
  2. Build time (npm run build)
    • Validates all content before building
    • Build fails if validation errors exist
    • Ensures production site has valid data
All validation happens at build time, not runtime. This means your production site is guaranteed to have valid data.

Extending the Schema

To add new fields to the schema:
  1. Edit src/content/config.ts:3
  2. Add the field to the wordsSchema object
  3. Choose appropriate Zod validator
  4. Mark as optional with .optional() if needed
Example - Adding an “etymology” field:
const wordsSchema = z.object({
  word: z.string(),
  meaning: z.string(),
  examples: z.array(z.string()),
  category: z.enum([...]),
  region: z.string().optional(),
  synonyms: z.array(z.string()).optional(),
  relatedWords: z.array(z.string()).optional(),
  featured: z.boolean().optional(),
  // New field
  etymology: z.string().optional(),
});
Then use it in frontmatter:
---
word: "Patojo"
meaning: "Niño o joven"
examples: [...]
category: "sustantivo"
etymology: "Posible origen en lenguas mayas"
---

Common Validation Patterns

Validate String Length

word: z.string().min(1).max(100),
meaning: z.string().min(10),

Validate Array Length

examples: z.array(z.string()).min(2).max(5),  // Require 2-5 examples

Add Custom Error Messages

word: z.string({
  required_error: "The 'word' field is required",
  invalid_type_error: "The 'word' must be a string",
}),

Validate URLs

reference: z.string().url().optional(),

Transform Data

word: z.string().trim().toLowerCase(),  // Auto-lowercase

Testing Validation

To test if your word file is valid:
  1. Run the development server:
    npm run dev
    
  2. Check the terminal for validation errors
  3. Or run a build:
    npm run build
    
If validation passes, you’ll see no errors and the build completes successfully.

Build docs developers (and LLMs) love