nextjs-cms

Introduction

nextjs-cms is a CMS framework for Next.js. You describe your content in TypeScript section files, and it gives you an admin panel, MySQL tables, and a typed API.

Welcome to the nextjs-cms documentation. These pages are for developers building a CMS with nextjs-cms. If you want to work on nextjs-cms itself, head to the Contributing docs.

What is nextjs-cms?

nextjs-cms is a Next.js application plus a library. You install it as a project (the admin app), then describe your content in *.section.ts files:

sections/posts.section.ts
import { hasItemsSection } from 'nextjs-cms/core/sections'
import { richTextField, textField } from 'nextjs-cms/core/fields'

const title = textField({ name: 'title', required: true })

export default hasItemsSection({
    name: 'posts',
    order: 1,
    title: { section: 'Blog', singular: 'Post', plural: 'Posts' },
    headingField: title,
    db: { table: 'posts' },
    fields: [title, richTextField({ name: 'body' })],
})

From that one file you get:

  • An admin UI: sidebar entry, list page with search and pagination, create and edit forms, validation, and delete.
  • A database table: running nextjs-cms update-sections creates posts with id, title, body, created_at, updated_at, created_by, and updated_by columns.
  • Permissions: admins can be granted create, update, and delete rights on posts, per admin.
  • An optional Drizzle schema for the table, so your public website can query the content with full types.

How it fits together

┌──────────────────────┐    update-sections     ┌──────────────┐
│  sections/*.section  │ ─────────────────────▶ │    MySQL     │
│  cms.config.ts       │                        │   tables     │
└──────────┬───────────┘                        └──────▲───────┘
           │ loaded at runtime                         │ reads/writes
           ▼                                           │
┌──────────────────────┐        tRPC           ┌───────┴──────┐
│  Admin UI (Next.js)  │ ◀──────────────────▶  │  nextjs-cms  │
│  forms, lists, auth  │                       │  core + API  │
└──────────────────────┘                       └──────────────┘
                                                       ▲
                               your public website ────┘ (reads the same tables)
  1. You write section files and a cms.config.ts.
  2. The CLI (nextjs-cms update-sections) reads your sections and syncs MySQL tables to match.
  3. The admin app loads the same sections at runtime to render forms, validate submissions, and write rows.
  4. Your website reads the tables directly, optionally through the generated Drizzle schema.

Core concepts

ConceptWhat it is
SectionA piece of content with its own table and admin pages. There are three types: simple (one row, e.g. settings), has-items (a collection, e.g. posts), and category (a tree, e.g. nested categories).
FieldOne input in a section's form and one column in its table (with a few exceptions, like dateRangeField, which writes two columns). Created with helpers such as textField() or photoField().
Field groupA titled group of fields, rendered as a card in the form. Purely visual.
HooksFunctions that run before or after a create, update, or delete. Use them to validate, sync, or notify.
PluginAn npm package that adds pages (and API routes) to the admin panel.

Where to go next