MADORIMADORI

CLI

Madori source checkout includes command-line tools for scaffolding, content migration, code generation, and administration. Generated create-madori-app projects do not bundle this CLI; manage those projects through control panel instead. @madori/cli is currently source-checkout tooling rather than a published registry package.


Configuration Reference

Running CLI Commands

From Madori source checkout, run commands with:

pnpm madori <command>

Available Commands

Command Description
make:user Create a new user account interactively
make:blueprint <handle> Generate a blueprint from content, schema, or interactively
make:collection <handle> Scaffold a complete collection with blueprint and example entry
migrate:definitions Migrate legacy entity definitions from config to flat files
migrate:wordpress <export-file> Migrate content from a WordPress WXR export file
migrate:markdown <source-directory> Migrate Markdown files from a directory into a collection
export <path> Export blueprints, collections, fieldsets, and content as an archive
import <archive-path> Import resources and content from an archive
init:preset <preset-name> Initialise project with an opinionated preset structure
registry:pull <repository-url> Pull resources from a shared Git registry
registry:push <repository-url> Push local resources to a shared Git registry
git:status Show Git sync status for configured repositories
git:sync Commit and optionally push pending tracked changes
git:retry --repository <id> Retry a pending Git push for repository ID from git:status
seo:migrate Migrate legacy SEO frontmatter fields into nested seo values
seo:rollback --plan <path> Roll back an SEO migration plan
backup <path> Create a checksummed operational backup
backup:verify <archive-path> Verify backup structure and checksums
restore <archive-path> --yes Restore a verified backup and retain rollback copies
generate Generate TypeScript types, schemas, and SDK from blueprints
check Check manifest schema-version compatibility

Scaffolding Commands

Git sync commands and setup are documented in Git Content Sync.

make:blueprint

Generate a blueprint from existing content, a JSON Schema file, or interactively.

pnpm madori make:blueprint <handle> [options]
Flag Type Description
--from-content <path> string Infer blueprint from a Markdown file's frontmatter
--from-schema <path> string Generate blueprint from a JSON Schema file

When run without flags, the command runs interactively. Fields inferred with low confidence default to text and are flagged in the output.

Example — infer from content:

pnpm madori make:blueprint blog --from-content content/collections/blog/hello.md
✓ Blueprint "blog" created successfully!

  Output: resources/blueprints/collections/blog.yaml
  Fields: 6

⚠ 1 field(s) defaulted to "text" (low confidence):
    - custom_meta

Example — from JSON Schema:

pnpm madori make:blueprint products --from-schema schemas/product.json

make:collection

Scaffold a complete collection in one step — creates the collection definition, blueprint, and an example entry.

pnpm madori make:collection <handle> [options]
Flag Type Description
--fields <fields> string Comma-separated field definitions: handle:type[:required]
--route <route> string Route pattern for the collection

Example:

pnpm madori make:collection products --fields "name:text:required,price:number:required,description:tiptap,image:asset" --route "/products/{slug}"
✓ Collection "products" created successfully!

Files created:
  - resources/collections/products.yaml
  - resources/blueprints/collections/products.yaml
  - content/collections/products/example.md

init:preset

Initialise a project with an opinionated preset structure for common use cases.

pnpm madori init:preset <preset-name> [options]
Flag Description
--force Skip conflict prompts and overwrite existing resources

Available presets:

Preset Description
marketing-site Pages, sections, and team members
blog Blog posts with categories and tags
documentation Documentation pages with navigation
saas-landing SaaS marketing with features and pricing
agency-portfolio Portfolio with case studies and team

Example:

pnpm madori init:preset blog
✓ Preset "blog" applied successfully!

Files created:
  - resources/collections/posts.yaml
  - resources/blueprints/collections/posts.yaml
  - resources/taxonomies/categories.yaml
  - resources/taxonomies/tags.yaml
  - content/navigation/main.yaml

Next steps:
  Run `pnpm madori check` to check manifest schema compatibility.

Migration Commands

migrate:wordpress

Migrate content from a WordPress WXR export file into Madori entries. Converts HTML to Markdown, preserves categories and tags as taxonomy terms, and maps WordPress statuses.

pnpm madori migrate:wordpress <export-file> [options]
Flag Type Description
--collection <handle> string Target collection handle (default: posts for posts, pages for pages)

Example:

pnpm madori migrate:wordpress wordpress-export.xml --collection blog
Migrating WordPress content from: /path/to/wordpress-export.xml

Migration complete!

  Total processed: 142
  Entries created:  138
  Skipped:          4

Taxonomies:
  Categories: 8 terms → resources/taxonomies/categories.yaml
  Tags:       23 terms → resources/taxonomies/tags.yaml

Summary: 142 processed, 138 created, 4 skipped, 0 warnings

The migration:

  • Converts HTML content to Markdown
  • Maps publish → published, draft/private → draft
  • Preserves author, categories, and tags
  • Auto-creates taxonomy definition files

migrate:markdown

Migrate a directory of Markdown files into a Madori collection. Extra frontmatter fields are preserved, but migration sets title, slug, status, createdAt, and updatedAt; imported entries become drafts. Review generated entries before publishing.

pnpm madori migrate:markdown <source-directory> [options]
Flag Type Description
--collection <handle> string Target collection handle (prompted if not provided)

Example:

pnpm madori migrate:markdown ./old-blog-posts --collection blog
Migrating Markdown files from: /path/to/old-blog-posts
Target collection: blog

Migration complete!

  Files processed:  47
  Entries created:  47
  Skipped:          0

Summary: 47 processed, 47 created, 0 skipped, 0 warnings

migrate:definitions

Migrates taxonomies, globals, and navigations arrays from the config file into individual YAML files under resources/.

pnpm madori migrate:definitions [options]
Flag Type Default Description
--config <path> string ./madori.config.ts Path to the config file to migrate from
--resources <path> string ./resources Output directory for generated definition files

Portability Commands

export

Export project resources and content as a portable archive.

pnpm madori export <output-path> [options]
Flag Type Default Description
--format <format> string zip Archive format: zip or tar
--resources <types> string all Comma-separated resource types to include

Resource types: blueprints, collections, fieldsets, content

Example:

pnpm madori export ./backup.zip --format zip --resources "blueprints,fieldsets"
✓ Export completed successfully!

  Archive: ./backup.zip
  Size:    24.3 KB
  Files:   18

import

Import resources and content from a previously exported archive.

pnpm madori import <archive-path>

Example:

pnpm madori import ./backup.zip
✓ Import completed successfully!

  Total files: 18
  Imported:    16
  Skipped:     2
  Conflicts:   0

Existing files are skipped by default to prevent accidental overwrites.

Operational backup and restore

Back up configured content, resources, assets, users, configuration, SEO state, sessions, and the schema manifest. Restore requires an explicit --yes and keeps pre-restore rollback copies.

pnpm madori backup ./storage/madori-backup.tar.gz
pnpm madori backup:verify ./storage/madori-backup.tar.gz
pnpm madori restore ./storage/madori-backup.tar.gz --yes

Use --rollback-dir <path> with restore to choose the rollback directory.

registry:pull

Pull shared resources from a Git repository into your local project.

pnpm madori registry:pull <repository-url> [options]
Flag Type Default Description
--resources <types> string all Comma-separated resource types to pull
--branch <branch> string main Git branch to pull from

Example:

pnpm madori registry:pull https://github.com/my-agency/shared-blueprints.git --resources "blueprints,fieldsets"

registry:push

Push local resources to a shared Git registry.

pnpm madori registry:push <repository-url> [options]
Flag Type Default Description
--resources <types> string all Comma-separated resource types to push
--branch <branch> string main Git branch to push to

Code Generation

generate

Generate TypeScript types, Zod schemas, and a typed GraphQL SDK from your blueprints. Output goes to .madori/generated/ by default.

pnpm madori generate [options]
Flag Type Default Description
-o, --output <path> string .madori/generated Output directory for generated files
-w, --watch boolean false Watch blueprint files and regenerate on change

Example:

pnpm madori generate
✓ Generate complete: 3 blueprint(s) processed in 42ms

Watch mode:

pnpm madori generate --watch

Watches YAML files under resources/blueprints/**/*.yaml and regenerates with a 300ms debounce. It does not watch collection definitions or fieldsets, so run pnpm madori generate explicitly after changing those resources.

The generator reads resources/blueprints/**/*.yaml from the project root and does not derive this input directory from a custom resourcesPath. The generated output includes:

  • TypeScript interfaces for each collection's entries
  • Zod schemas for runtime validation
  • A typed GraphQL SDK with operations for each collection
  • A barrel index.ts for convenient imports
  • A tsconfig.paths.json for path alias configuration

Generated consumers import @madori/sdk, which is currently a source workspace package. Build and link the SDK before using those imports; see SDK and content access for setup. Path aliases alone do not install the package.


Administration Commands

make:user

Create a new user account interactively.

pnpm madori make:user
Prompt Type Validation
Email address string Must be valid email, must not already exist
Display name string Required, non-empty
Password string Required, minimum 8 characters
Roles string[] Comma-separated list of role handles

Output: Creates a YAML file at users/{id}.yaml with a scrypt password hash.

check

Check whether the manifest's schema version matches the version expected by the running code. This command does not validate all blueprints, content, or application configuration.

pnpm madori check

Use --manifest <path> to override the default .madori/manifest.json location.


Usage Examples

Creating a User

pnpm madori make:user

Interactive prompts:

? Email address: [email protected]
? Display name: Jane Editor
? Password: ********
? Roles (comma-separated): editor

✓ User created: users/<generated-id>.yaml

Full Agency Workflow

Set up a new client project from a preset, then customise:

# Start from a preset
pnpm madori init:preset marketing-site

# Add a blog collection
pnpm madori make:collection blog --fields "title:text:required,slug:slug:required,body:tiptap,image:asset"

# Validate everything
pnpm madori check

# Generate typed SDK
pnpm madori generate

Migrating from WordPress

# Export from WordPress (WXR format)
# Then import into Madori:
pnpm madori migrate:wordpress wordpress-export.xml

# Generate blueprint from migrated content
pnpm madori make:blueprint posts --from-content content/collections/posts/first-post.md

Sharing Resources Between Projects

# Push blueprints and fieldsets to a shared registry
pnpm madori registry:push https://github.com/my-agency/shared-resources.git --resources "blueprints,fieldsets"

# Pull into another project
pnpm madori registry:pull https://github.com/my-agency/shared-resources.git

Resource Portability

# Export supported resources and content
pnpm madori export ./project-backup.zip

# Import on another machine; existing files are skipped
pnpm madori import ./project-backup.zip

This portable export is not an operational backup of users, sessions, assets, or all configured storage roots. Use backup, backup:verify, and restore for disaster recovery.


Common Patterns

Scripting User Creation

For CI/CD or staging setup, prefer make:user or your configured auth provider. If you write provider files directly, use the provider's documented hash format; Madori's built-in file provider uses scrypt:<salt>:<hash> values.

# users/staging-admin.yaml
id: staging-admin
email: [email protected]
name: Staging Admin
password_hash: scrypt:<salt hex>:<hash hex>
roles:
  - admin
created_at: 2026-01-01T00:00:00.000Z

Code Generation in CI

Add generation to your build pipeline to ensure types stay fresh:

{
  "scripts": {
    "prebuild": "pnpm madori generate",
    "build": "next build"
  }
}

SEO Frontmatter Migration

Move legacy meta_title, meta_description, and og_image fields into a nested seo object. The command is idempotent, preserves unknown fields, writes per-file backups, and refuses rollback if a target changed after migration. Records do not carry the standalone SEO document's version wrapper.

# Preview changes
pnpm madori seo:migrate --root ./content --dry-run

# Apply migration
pnpm madori seo:migrate --root ./content

For a reversible apply, write a private rollback plan and keep it out of Git:

pnpm madori seo:migrate --root ./content --plan ./storage/seo-migration-plan.json
pnpm madori seo:rollback --plan ./storage/seo-migration-plan.json

Review the JSON output and rollbackPlan before committing. Commit migrated content and SEO defaults through the repository that owns those paths; operational SEO state under storage/seo is not part of this migration and should remain outside content Git.

Legacy Definitions Migration

When upgrading from an older Madori version that stored definitions inline:

  1. Run pnpm madori migrate:definitions to extract definitions to files
  2. Review the generated files in resources/
  3. Remove the migrated arrays from madori.config.ts
  4. Commit the new files and updated config

The migration is non-destructive — existing files are never overwritten.