Getting Started with Cmssy CLI

Complete guide to installing and configuring Cmssy CLI, creating your first project, and publishing custom blocks to your workspace.

Last updated: April 24, 2026

Installation

Install Cmssy CLI globally using your preferred package manager:

npm install -g @cmssy/cli
# or
pnpm add -g @cmssy/cli

Requirement: Node.js >= 18.0.0

Verify the installation:

cmssy --version

Quick Start

Get from zero to a published block in 7 steps:

# 1. Create a new project
cmssy init my-blocks

# 2. Navigate to project
cd my-blocks

# 3. Install dependencies
pnpm install

# 4. Connect to your workspace
cmssy link

# 5. Start development server
cmssy dev

# 6. Create your first block
cmssy create block hero

# 7. Publish your block via the sandbox build pipeline
cmssy publish-block hero

Project Structure

After running cmssy init, your project looks like this:

my-blocks/
├── cmssy.config.js          # Project configuration
├── package.json              # Dependencies (React 19, Next.js, Tailwind v4)
├── tsconfig.json             # TypeScript configuration
├── postcss.config.js         # PostCSS + Tailwind
├── .env                      # API credentials (never commit!)
├── .env.example              # Template for .env
├── blocks/                   # Your custom blocks
│   └── hero/                 # Example block
│       ├── config.ts         # Block schema definition
│       ├── package.json      # Block metadata & version
│       ├── preview.json      # Dev server preview data
│       └── src/
│           ├── Block.tsx     # React component
│           ├── index.tsx     # Export wrapper + CSS import
│           ├── index.css     # Block styles
│           └── block.d.ts    # Auto-generated TypeScript types
├── templates/                # Page templates
├── components/               # Shared components
├── styles/
│   └── main.css             # Tailwind v4 global styles
├── public/                   # Build output
└── .cmssy/                   # CLI internal cache

Configuration

Project Config (cmssy.config.js)

export default {
  framework: "react",
  projectName: "my-blocks",
  author: {
    name: "Your Name",
    email: "you@example.com"
  },
  build: {
    outDir: "public",
    minify: true,
    sourcemap: true
  }
}

API Credentials (.env)

Run cmssy link to set up interactively, or create .env manually:

CMSSY_API_URL=https://api.cmssy.io/graphql
CMSSY_API_TOKEN=cs_your_api_token_here
CMSSY_WORKSPACE_ID=your_workspace_id
  • API Token: Generate in Workspace Settings → API Tokens. Format: cs_xxxxx
  • Workspace ID: Found in Workspace Settings → General → Workspace Information

Block Structure

Every block follows a consistent pattern:

blocks/my-block/
├── config.ts         # Schema + metadata (defineBlock)
├── package.json      # Name, version, description
├── preview.json      # Preview data for dev server
└── src/
    ├── Block.tsx     # Your React component
    ├── index.tsx     # Exports component + imports CSS
    ├── index.css     # Styles (@import main.css + custom)
    └── block.d.ts    # Auto-generated types from schema

config.ts — Block Definition

import { defineBlock } from "@cmssy/cli/config";

export default defineBlock({
  name: "Hero Section",
  description: "Main hero with heading, CTA, and media",
  category: "marketing",
  tags: ["hero", "landing", "cta"],

  schema: {
    heading: {
      type: "singleLine",
      label: "Heading",
      required: true,
      defaultValue: "Welcome to our site"
    },
    description: {
      type: "multiLine",
      label: "Description",
      defaultValue: "A short description"
    },
    buttonText: {
      type: "singleLine",
      label: "Button Text",
      defaultValue: "Get Started"
    },
    buttonUrl: {
      type: "link",
      label: "Button URL",
      defaultValue: "#"
    },
    image: {
      type: "media",
      label: "Hero Image"
    }
  }
});

Block.tsx — React Component

import type { PlatformContext } from "@cmssy/cli/config";
import type { BlockContent } from "./block";

export default function Hero({
  content,
  context
}: {
  content: BlockContent;
  context?: PlatformContext;
}) {
  const {
    heading = "Welcome",
    description = "",
    buttonText = "Get Started",
    buttonUrl = "#",
    image
  } = content;

  return (
    <section className="py-20 text-center">
      <h1 className="text-5xl font-bold">{heading}</h1>
      <p className="mt-4 text-lg text-muted-foreground">{description}</p>
      <a href={buttonUrl} className="mt-8 inline-block px-6 py-3 bg-primary text-white rounded-lg">
        {buttonText}
      </a>
      {image && <img src={image} alt="" className="mt-12 mx-auto rounded-xl" />}
    </section>
  );
}

index.tsx — Export Wrapper

export { default } from "./Hero";
import "./index.css";

Development Workflow

Dev Server

cmssy dev

Opens at http://localhost:3000 with:

  • Live preview of all blocks
  • Hot reload on file changes
  • Preview data from preview.json

Building

cmssy build

Compiles all blocks with esbuild, processes Tailwind CSS, and outputs to public/.

Publishing

cmssy publish-block hero -w <workspace-id>

Uploads the block via the sandbox build pipeline (CMS-576): the CLI archives the source tree, the backend bundles it in a Vercel Sandbox, and writes artifacts back to Vercel Blob.

Options:

  • -w, --workspace <id> — override the workspace from .env
  • --entry <path> — block entry path (default: src/index.tsx)
  • --dry-run — collect files and print the plan, no upload

The legacy cmssy publish command + its --zip / --patch / --minor / --major / --overwrite-content flags were removed in CMS-606. Templates still accept --overwrite-content via cmssy publish-template.


Next Steps