DEV Community

Alex Spinov
Alex Spinov

Posted on

Velite Has a Free Content Layer for Static Sites — Here's How to Use It

Contentlayer is abandoned. MDX is setup-heavy. Velite turns your Markdown, YAML, and JSON files into type-safe, validated collections — with zero runtime overhead.

What Is Velite?

Velite is a content build tool that transforms local files (Markdown, MDX, YAML, JSON) into type-safe data collections. Think of it as a "content compiler" for your static site.

Quick Start

npm install velite
Enter fullscreen mode Exit fullscreen mode
// velite.config.ts
import { defineConfig, s } from 'velite';

export default defineConfig({
  collections: {
    posts: {
      name: 'Post',
      pattern: 'posts/**/*.md',
      schema: s.object({
        title: s.string().max(120),
        slug: s.slug('posts'),
        date: s.isodate(),
        description: s.string().max(300),
        tags: s.array(s.string()),
        draft: s.boolean().default(false),
        body: s.markdown(),
      }),
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Usage

// Access typed content in your app
import { posts } from '#content';

// posts is fully typed as Post[]
const publishedPosts = posts
  .filter(post => !post.draft)
  .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());

// TypeScript knows the exact shape
publishedPosts.forEach(post => {
  console.log(post.title);       // string
  console.log(post.slug);        // string
  console.log(post.date);        // string (ISO date)
  console.log(post.tags);        // string[]
  console.log(post.body);        // string (rendered HTML)
});
Enter fullscreen mode Exit fullscreen mode

Schema Validation

Velite validates your content at build time:

const schema = s.object({
  title: s.string().min(10).max(120),
  date: s.isodate(),
  cover: s.image(),                    // Validates image exists, returns dimensions
  category: s.enum(['tech', 'life']),  // Only allowed values
  author: s.object({
    name: s.string(),
    avatar: s.image(),
  }),
  related: s.array(s.slug('posts')),   // Validates references exist
});
Enter fullscreen mode Exit fullscreen mode

If your frontmatter doesn't match the schema, the build fails with a clear error.

Supported Content Types

// Markdown → HTML
body: s.markdown(),

// MDX → Component code
body: s.mdx(),

// Rich text excerpt
excerpt: s.excerpt(),

// Computed fields
readingTime: s.string().transform((_, { meta }) => 
  `${Math.ceil(meta.content.split(' ').length / 200)} min read`
),

// Image processing
cover: s.image(),  // Returns { src, width, height, blurDataURL }
Enter fullscreen mode Exit fullscreen mode

Framework Integration

Works with any framework:

  • Next.js — import from #content
  • Astro — import from #content
  • Remix — import at build time
  • SvelteKit — import from #content

Why Velite

Feature Velite Contentlayer Gray-matter
Status Active Abandoned Active
Type safety Full Full None
Validation Built-in (Zod-like) Contentlayer schema None
MDX support Yes Yes No
Image processing Built-in No No
Framework Any Next.js focused Any

Get Started


Processing content from the web? My Apify scrapers extract structured content from any site. Custom solutions: spinov001@gmail.com

Top comments (0)