CLI
The nextjs-cms command-line tool. Set up the database, sync tables with your sections, and manage the Master admin.
The CLI ships with the nextjs-cms package. Run it from the project root through your package manager:
pnpm nextjs-cms [global options] <command> [options]Global options
| Option | Description |
|---|---|
-d, --dev | Load .env.development and run in development mode. Without it, the CLI loads .env and runs in production mode. Must come before the command: nextjs-cms -d update-sections. |
-v, --version | Print the installed version. |
-h, --help | Show help. |
Before any command runs, the CLI checks that it's inside a nextjs-cms project (a cms.config.* exists and nextjs-cms is a dependency with a matching version). If a command refuses to start, check those first.
Commands
| Command | What it does |
|---|---|
setup | First-time setup: database config, system tables, Master admin. |
update-sections | Sync MySQL tables with your section files. Run after every section change. |
db-config | Set or change the database connection. |
set-master-admin | Set or reset the Master admin's password. |
fix-master-admin | Grant the Master admin every section and plugin again. |
setup
pnpm nextjs-cms -d setup
pnpm nextjs-cms -d setup --continueRuns, in order:
db-config: asks for the connection and writes it to the env file.- System tables: creates the CMS's internal tables (admins, privileges, tokens, logs, editor photos, bookkeeping) with
drizzle-kit push. set-master-admin: creates theMasteraccount.
| Option | Description |
|---|---|
--continue | Skip step 1 when the database is already configured. |
If system tables already exist, setup lists them and asks before dropping and recreating them, which deletes all admins and privileges. Your section tables are not touched.
create-nextjs-cms runs nextjs-cms --dev setup for you. After it, run update-sections to create your sections' tables.
update-sections
pnpm nextjs-cms -d update-sectionsThe command you'll run most. It:
- Loads every section from
sections.pathand validates it. Configuration conflicts (a reserved name, adbselect pointing at a section's table...) abort the run with an explanation. - Builds the tables the sections need: section tables,
{table}_localestranslation tables, gallery tables,destinationDbjoin tables, anddblookup tables. - Compares them with the database and resolves each difference. Missing tables are created right away; anything that could lose data (renames, drops, type changes on existing tables) is asked about first.
- Creates missing unique constraints, indexes, and full-text indexes.
- Writes the Drizzle schema (if
schemaGeneration.drizzle.enabled). - Grants the
Masteradmin access to every section (fix-master-admin).
Prompts you'll see
| Situation | Prompt | Choices |
|---|---|---|
| A section's table doesn't exist, and an unused table does | "Is table 'articles' for section 'posts' a new table?" | New table / rename an existing one (data kept) |
| A new field | "Is field 'headline' of table 'posts' a new field?" | New column / rename an existing column (data kept) |
| A column is no longer in your config | "Field 'subtitle' exists in table 'posts' but is not in your config. What do you want to do?" | Drop field / Keep field / Ask me later |
| A table is no longer used by any section | "You are about to remove table 'old_news'. Proceed?" | Yes, drop it / No, keep it / Ask me later |
| An existing table isn't managed yet | Existing-table prompt | Configure table (recommended) / Ask later |
"Keep" and "ask later" leave the column or table untouched. Answering rename instead of new is how you rename a field or table without losing data.
Changing a column's type (for example a textField to a numberField, or shrinking a maxLength) is applied with ALTER TABLE. MySQL converts or rejects existing values. Back up production data before running update-sections there.
In CI and deployments
update-sections is interactive when it needs a decision. Run it yourself against production after reviewing the changes, rather than blindly in a deploy script.
db-config
pnpm nextjs-cms -d db-configPrompts for host, port, username, password, and database name, tests the connection, then writes DB_HOST, DB_PORT, DB_NAME, DB_USER, and DB_PASSWORD to .env.development (with -d) or .env.production (without), replacing existing values.
set-master-admin
pnpm nextjs-cms -d set-master-adminAsks for a new password (twice) for the Master account, creating it if needed, and grants it every privilege. If the account exists, it asks for confirmation before resetting the password. The username is always Master.
fix-master-admin
pnpm nextjs-cms -d fix-master-adminRebuilds the Master admin's privileges so it has full (CUD) access to every current section, plugin, and built-in page. update-sections already does this at the end; run it alone after restoring a database or when sections were added some other way.
Environment files
| Command run with | Loads | db-config writes to |
|---|---|---|
-d / --dev | .env.development | .env.development |
| no flag | .env | .env.production |
Without -d, the CLI reads the database credentials from .env (or from variables already set in the shell), not from .env.production. On a production server, either export the DB_* variables in the shell before running the CLI, or keep them in .env.