contentlayer2

A type-safe content SDK that turns Markdown, MDX, and CMS content into validated JSON you import directly into your app.

Tool
npm
v0.5.8
422stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
44/100Fair
Development Activity0
Maintenance32
Community56
Maturity48
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
69/100Good
Architecture78
Code Quality58
Innovation68
Learning Curve70

Contentlayer2 is a community-maintained fork of the original Contentlayer project, picked up after the upstream package stalled and its future became uncertain. It reads local content (Markdown, MDX, JSON, YAML) or remote sources, validates every document against a schema you define with defineDocumentType, and generates fully-typed TypeScript data plus .d.ts files so consuming code gets autocomplete and compile-time safety on frontmatter fields.

The toolchain is invoked through a CLI (contentlayer2 build/dev) that watches content directories, incrementally rebuilds on change, and writes generated documents plus a on-disk cache keyed by content hash so unchanged files are skipped on rebuild. A next-contentlayer2 package wraps this as a Next.js webpack/Turbopack integration so the generated .contentlayer/generated types and data are wired into the build automatically.

Under the hood it is built on Effect-TS (@effect-ts/core) rather than plain async/await, giving the core pipeline typed, tagged errors (NoConfigFoundError, SourceFetchDataError, etc.), OpenTelemetry tracing spans around cache and schema operations, and composable effect pipelines for config loading, schema validation, and MDX/Markdown compilation via mdx-bundler and the unified/remark/rehype ecosystem.

What You Get

  • Schema DSL - define document types with defineDocumentType and get validation plus generated TypeScript types for every field
  • CLI with watch mode - contentlayer2 dev/build incrementally rebuilds only changed content using a content-hash cache
  • Next.js integration - next-contentlayer2 wires generated types and data into the Next.js webpack/Turbopack build automatically
  • MDX pipeline built-in - ships with mdx-bundler, unified, remark, and rehype wired up so Markdown/MDX compiles out of the box
  • Pluggable content sources - source-files for local content today, with a source-remote-files extension point for CMS-backed sources
  • Typed error handling - Effect-TS-based core surfaces tagged, structured errors instead of throwing untyped exceptions

Common Use Cases

  • Next.js blogs and docs sites - author posts/pages as MDX files and import fully-typed allPosts/allDocs arrays into route components
  • Migrating off the original Contentlayer - projects on the archived contentlayer/next-contentlayer packages switch to this fork with no API changes required
  • Marketing sites with structured content - product pages, changelogs, or case studies modeled as document types with validated, typed frontmatter
  • Static site generators needing typed content - any Node build pipeline that wants compile-time-safe access to Markdown/MDX/JSON content instead of ad hoc file parsing

Under The Hood

Architecture The monorepo splits responsibilities across small @contentlayer2/* packages — source-files fetches and maps documents from disk, core owns schema validation, MDX/Markdown compilation, and the on-disk DataCache (keyed by a content hash so unchanged documents skip reprocessing), cli wires up the dev/build/postinstall commands, and client/utils provide the runtime and shared primitives consumed by generated code. The top-level contentlayer2 package re-exports these as public entry points (source-files, client, core, utils), while next-contentlayer2 layers a webpack/Turbopack integration on top so a Next.js build triggers a full contentlayer build automatically. Config loading, schema validation, and cache read/write all run as composable pipelines rather than plain function calls, so a change to any core abstraction (the DataCache shape or the SchemaDef types) ripples through every source plugin and the generated-types writer.

Tech Stack TypeScript throughout, built on @effect-ts/core for its functional-effect runtime plus OpenTelemetry (@opentelemetry/sdk-trace-node, -otel) for tracing build operations. Markdown/MDX compilation goes through unified/remark-parse/remark-rehype/rehype-stringify and mdx-bundler, with esbuild doing the actual bundling and gray-matter parsing frontmatter. The workspace is a Yarn 3 (Berry) monorepo built with tsc --build against a shared tsconfig.all.json, released via Changesets, and includes a Nix flake for reproducible dev environments.

Code Quality Tests are limited to five integration-test specs under packages/integration-tests (image fields, markdown, remark-gfm, empty content folders, MDX-with-images) run via Vitest — there is no unit-test suite for the individual @contentlayer2/* packages. Error handling is deliberately typed: core errors extend a Tagged base class (NoConfigFoundError, SourceFetchDataError, ConfigReadError) carrying a _tag discriminant and structured fields rather than throwing bare Error instances, and ESLint plus Prettier are enforced via lint:check in CI. Naming and file organization are consistent (fetchData/, schema/, errors/ per source package), but the shallow integration-only test coverage is a real gap for a fork whose value proposition is being a trustworthy maintenance successor.

What Makes It Unique What sets it apart from typical Markdown/MDX loaders is the Effect-TS foundation underneath a conventional-looking content API: config loading, schema validation, and data fetching all run as typed, tagged-error effect pipelines instrumented with OpenTelemetry spans, giving structured failure modes and build-performance tracing that plain async/await content pipelines don’t offer. Its primary differentiator versus alternatives, though, is being an actively maintained continuation of a project whose original maintainers had paused development — same API, same generated-types workflow, kept current with modern Unified v11 and TypeScript 5 toolchains.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search