# Define collections

```bash
npm install @qentrah/cms@beta hono drizzle-orm zod
```

```ts
import { createQentrahApp, registerCollections } from '@qentrah/cms'
import type { QentrahConfig } from '@qentrah/cms'

const config: QentrahConfig = {
  name: 'My CMS',
}

registerCollections([
  {
    name: 'article',
    displayName: 'Article',
    slug: 'articles',
    kind: 'collection',
    schema: {
      type: 'object',
      properties: {
        title: { type: 'string', title: 'Title', required: true },
        body: { type: 'lexical', title: 'Body' },
      },
      required: ['title'],
    },
    managed: true,
    isActive: true,
  },
])

export default createQentrahApp(config)
```

## Schema responsibilities

`registerCollections` registers collection metadata. Give each collection a stable name and slug, define its schema and required properties, and decide whether it is managed and active. The example uses a string title and Lexical body. A schema registration does not by itself establish access permissions or complete a deployment migration.

## Read content from an app

Use the separate `@qentrah/sdk` package for a typed client. Relations and media are not populated by default in the CMS. Make population explicit in the server query contract instead of assuming related records are always embedded.