---
title: CMS Pages (CLI)
description: Create and delete CMS pages from the command line.
---

When the `cms` module is installed, the Nibiru CLI gains two extra flags for managing CMS pages directly. This is the same content store powering the production e-commerce site `prod.maschinen-stockert.de`, where editors update site copy without touching code.

## Create a page

```bash
./nibiru -new-cms-page about-us
```

This:

1. Inserts a row in the `cms_pages` table with slug `about-us`.
2. Binds the page to a CMS template (the default template, unless one is configured).
3. Creates per-language placeholder rows in `cms_template_texts` so editors can fill in copy in every supported language.

Visit `/cms/about-us` (or your configured CMS prefix) and the new page is live.

## Delete a page

```bash
./nibiru -delete-cms-page about-us
```

Removes the page row and its associated `cms_template_texts` entries. The CMS template itself is not deleted — only the page binding to it.

## Why these are CLI commands and not just SQL

Two reasons:

1. **Atomicity** — creating a page requires inserts in two tables (the page and its text rows). The CLI wraps this in a transaction.
2. **Slug uniqueness** — the CLI checks for collisions before inserting and gives a friendlier error than a SQL constraint violation.

## Without the CMS module

`-new-cms-page` and `-delete-cms-page` exit non-zero with a clear error message if the `cms` module isn't installed. Add it with:

```bash
./nibiru -m cms
./nibiru -mi local
```

(See [Modules](/core/modules/) for what `./nibiru -m` does and the migration files the `cms` module ships.)

## Editing content after creation

The CLI doesn't edit text — that's deliberately left to the CMS module's web UI. From production code:

```php
// Read all text identifiers for a controller path + language
$texts = \Nibiru\Module\Cms\Cms::init('about-us')
    ->loadCmsTemplateTextsByControllerPath('about-us/page', $this->language);

foreach ($texts as $t) {
    \Nibiru\View::assign([
        $t['cms_template_texts_text_identifier']
            => $t['cms_template_texts_text_content']
    ]);
}
```

The result: every `{$identifier}` in the template is auto-populated with the current language's content. Non-developers manage text via the admin UI; developers manage layout via the template.
