---
name: create-content-category
description: Use when adding or implementing new CMS content category list styles, preview styles, or category layout structures across models, controllers, templates, playground, and themes.
---

# Create Content Category Style

Use this skill when adding or extending CMS category presentation modes (`list_style` or `preview_style`).

## Architectural Layers

Every category style touches these layers:

| Layer | File | Purpose |
|---|---|---|
| Model | `src/model/base/content.model.php` | Define style constant, options array, and whitelist validation |
| Controller | `src/pages/admin/content-management/content-management.controller.php` | Validate submitted style against `ContentModel::LIST_STYLE_OPTIONS` |
| Admin View | `src/pages/admin/content-management/content-editor.view.php` | Expose style in `FormComponents::showSelect('list_style', ...)` |
| Core Module | `src/core/modules/Content/Content.php` | Dispatch and render category items (`renderContentCategoryOutput` + renderer function) |
| Core Template | `src/core/modules/Content/templates/news-category-{style}.php` | Standalone template file for inclusion / theme override |
| Global CSS | `src/assets/css/global.css` | Baseline styles for fallback / standard themes |
| Theme Styles | `src/templates/{theme}/assets/css/theme.css` | Theme-specific styling (grid, responsive columns, cards) |
| Playground View | `src/pages/public/playground/playground.view.php` | Playground component registered under `content` category |
| Playground Ref | `Docs/skills/create-full-template/playground-html-ref.html` | Plain HTML reference for theme designers |
| Playground Doc | `Docs/api/playground.md` | Playground documentation reference table |
| CMS Doc | `Docs/knowledge/05-content-management.md` | Data model documentation of available list styles |

---

## Workflow

### 1. Data Model & Options

In `src/model/base/content.model.php`:

```php
public const STYLE_{STYLE} = '{style}';

public const LIST_STYLE_OPTIONS = [
  self::STYLE_NEWS => 'News',
  self::STYLE_DROPDOWN => 'Dropdown / FAQ',
  self::STYLE_{STYLE} => '{Label}',
];
```

Ensure `create()` and `update()` validate against `array_keys(self::LIST_STYLE_OPTIONS)`.

### 2. Admin Validation & UI

- In `src/pages/admin/content-management/content-management.controller.php`:
  Validate category style with `in_array($listStyle, array_keys(ContentModel::LIST_STYLE_OPTIONS), true)`.
- In `src/pages/admin/content-management/content-editor.view.php`:
  Use `ContentModel::LIST_STYLE_OPTIONS` in `FormComponents::showSelect('list_style', ...)`.

### 3. Rendering Logic

In `src/core/modules/Content/Content.php`:

1. In `renderContentCategoryOutput($node, $showTitleAndBlocks)`:
   ```php
   if (ContentModel::STYLE_{STYLE} === $node['list_style']) {
     renderContentCategory{Style}($children);
     if ($showTitleAndBlocks) {
       ComponentsTemplate::EndBlock();
     }
     return;
   }
   ```
2. Implement `renderContentCategory{Style}($children)`:
   - Construct wrapper element with semantic class (e.g. `.news-list.content-category-{style}`).
   - Render each item with required DOM hierarchy and classes:
     - Item container: `article.news-card`
     - Date element: `.news-date` (e.g. `24 AUG 2026`)
     - Clickable title: `h3 > a` pointing to `contentNodeUrl($child)`
     - Excerpt paragraph: `p.text-muted`
   - Strip HTML tags and limit excerpt length when displaying raw body text.
3. Create `src/core/modules/Content/templates/news-category-{style}.php` for direct template rendering:
   ```php
   <?php
   $childrenLanguage = $node['translation']['language'] ?? LANGUAGE;
   $children = ContentModel::getPublishedChildren($node['id'], $childrenLanguage);
   renderContentCategory{Style}($children);
   ```

### 4. Clickable Elements Contract

- Item titles or cards **must be clickable** navigating to `contentNodeUrl($child)`.
- Format: `<?php echo htmlspecialchars(contentNodeUrl($child), ENT_QUOTES, 'UTF-8'); ?>`.
- Category dates: `strtoupper(date('d M Y', strtotime($child['publish_at'])))`.

### 5. CSS & Responsiveness

- Provide basic responsive grid styles in `src/assets/css/global.css` (e.g. `display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px;`).
- In theme stylesheets (e.g. `theme.css`), collapse grid to single column on mobile viewports (`@media (max-width: 900px)` or `@media (max-width: 768px)`).

### 6. Playground & Documentation Maintenance

1. Add component key to `$playgroundComponentsByCategory['content']['components']` in `src/pages/public/playground/playground.view.php`.
2. Add `playgroundComponentStart('content', 'category-{style}', ...)` block in `playground.view.php`.
3. Add the plain HTML fixture to `Docs/skills/create-full-template/playground-html-ref.html`.
4. Update `Docs/api/playground.md` table.
5. Update `Docs/knowledge/05-content-management.md` `list_style` list.

---

## Validation

- `php -l` on all touched PHP files.
- Verify admin category editor displays the new style and saves without error.
- Verify public rendering with both `$showTitleAndBlocks = true` (category page) and `false` (embedded on home/custom page).
- Verify playground filter selects and displays the new component.
