Catch CMS bugs before deploy.

cms-lab checks your CMS content against your Next.js routes so broken pages, missing fields, SEO gaps, and image alt text issues are caught before customers see them.

Free open-source CLI. Runs locally, uses your CMS credentials, and does not send content to a hosted cms-lab service.

$npx @cms-lab/cli scanRead docs

Run it before deploy.

cms-lab scan
$ npx @cms-lab/cli scan

cms-lab
checked your Next.js routes and CMS content

warnings
 Missing meta description on About
  Image alt text is empty on Blog / Launch notes

summary
 errors 0
 warnings 2

scan completed
report written to .cms-lab/report.html

The content failures cms-lab catches.

Reachability

Published entries that lead to a dead page

cms-lab turns each mapped CMS document into the URL your app should serve, probes that URL, and flags 404s, 500s, fetch errors, and invalid responses before deploy.

Expected URL, HTTP status, source document.
Required data

Fields your templates assume are present

If a page needs fields like title, author.name, heroImage, or launchDate, the scan checks the configured paths and reports the exact missing value.

Field path, content type, affected document.
Share previews

Pages that look unfinished in search and chat

Missing titles and descriptions create vague search snippets and weak link previews. cms-lab catches empty metadata before those pages are indexed or shared.

Document, missing metadata fields.
Image content

Image fields with empty or placeholder alt text

Hero images, galleries, nested slices, and repeatable groups are walked recursively so empty strings and placeholder alt text do not ship.

Exact image field path.
Route mapping

CMS types that never become pages

Content types without a configured route, or entries missing the UID your route pattern needs, are reported instead of silently disappearing from the site.

Type, UID state, route pattern.
URL builders

Route functions that throw or point outside the site

When a getPath function throws, returns an invalid path, or resolves outside the configured site origin, cms-lab reports it as a configuration problem.

Route type, sanitized error, safe path.

Config-first, so your route rules stay explicit.

import { defineConfig } from "@cms-lab/core";

export default defineConfig({
  site: { url: "http://localhost:3000" },
  framework: { type: "next", router: "app" },
  cms: {
    provider: "prismic",
    repositoryName: "my-repo",
    accessToken: process.env.PRISMIC_ACCESS_TOKEN,
  },
  routes: [
    { type: "page", pattern: "/:uid", getPath: (doc) => "/" + doc.uid },
    { type: "article", pattern: "/articles/:uid", getPath: (doc) => "/articles/" + doc.uid },
  ],
});

Adapters

Connect the CMS you already use, map content types to routes, and scan the same way across providers.

Prismic
Strapi
Directus
WordPress

Private by default

cms-lab runs where your app runs. It does not require a dashboard account, and the hosted cms-lab service does not exist.

JSON output redacts raw CMS payloads unless you explicitly ask for sensitive output.