Building FieldTest: A Framework-Agnostic Content Validation Toolkit
I was building content-heavy sites (documentation, blogs, marketing sites) and kept hitting runtime errors from invalid frontmatter or missing required fields. The usual solutions were either framework-specific (Astro's Zod schemas) or required manual validation scripts. I wanted something that works across frameworks, validates at build time, and handles large content repositories efficiently.
The Problem
Most content validation solutions are:
- Framework-specific (tied to Astro OR Next.js OR Remix)
- Runtime-only (errors discovered after deployment)
- Manual (require custom validation scripts)
- Inefficient (don't scale to large content repositories)
I needed a solution that:
- Works across frameworks (Astro, Next.js, Remix, SvelteKit)
- Validates at build time, not runtime
- Follows a standard (Standard Schema v1) for interoperability
- Handles large content repositories efficiently (5000+ files)
The Solution
FieldTest - A validation toolkit built on Standard Schema v1 that validates markdown files and their frontmatter against custom schemas.
Key Features
- Framework agnostic - Works with any modern framework
- Build-time validation - Catches errors before deployment
- Standard Schema compliant - Built on Standard Schema v1 for maximum interoperability
- Performance - <50ms validation per document, handles 5000+ files efficiently
- TypeScript support - Full type safety with comprehensive error messages
- Zero config - Works out of the box, customizable when needed
Technical Architecture
The toolkit is built around a core markdown processing engine with:
- Schema Registry - Reusable validation rules across projects
- Framework Integrations - Native support for Astro Content Collections, Next.js static generation, and more
- MCP Server - AI-powered content validation workflows
- Biome Plugins - GritQL plugins for migration assistance
Example Usage
import { loadUserSchema, validateWithSchema } from '@watthem/fieldtest';
const blogSchema: StandardSchemaV1 = {
version: '1',
name: 'blog-post',
fields: {
title: { type: 'string', required: true },
author: { type: 'string', required: true },
published: { type: 'boolean', required: true },
tags: { type: 'string', array: true },
publishedAt: { type: 'date', required: false }
}
};
const schema = loadUserSchema(blogSchema);
const result = validateWithSchema(markdown, schema);
if (!result.valid) {
result.errors.forEach(error => {
console.error(`${error.field}: ${error.message}`);
});
}
Impact
- Eliminated runtime content errors - All validation happens at build time
- Improved developer experience - Clear error messages with field-level details
- Standardized content - Consistent validation across multiple projects
- AI integration - MCP server enables AI workflows for content generation and validation
Tech Stack
- TypeScript
- Standard Schema v1
- pnpm + Turborepo (monorepo)
- Biome (formatting/linting)
- Vitest (testing)
What I Learned
Building framework-agnostic tools requires careful abstraction. Standard Schema v1 provides a solid foundation for interoperability, but performance matters - optimizing for large content repositories required careful algorithm design. Developer experience is critical - clear error messages and zero-config defaults make adoption easier.
Links
- NPM: @watthem/fieldtest
- GitHub: watthem/fieldtest
- Docs: fieldtest.watthem.blog
FieldTest is actively maintained and open to feedback and contributions!