---
name: contentrain-content
description: "Create and manage content entries for existing Contentrain models. Use when adding entries to collections, populating singletons, writing documents, or managing dictionary keys."
metadata:
  author: Contentrain
  version: "1.0.0"
---

# Skill: Create Content for Existing Models

> Generate and save content entries for models already defined in the project.

---

## When to Use

The user wants to create new content, add entries to a collection, populate a singleton, or says something like "add a blog post", "create content", "fill in the hero section".

---

## MUST Rules

- MUST call `contentrain_describe` before writing content (know the schema)
- MUST provide ALL required fields in entries
- MUST create entries for ALL supported locales when model has `i18n: true`
- MUST NOT set system fields (id, slug, createdAt, updatedAt, status, source)
- MUST run `npx contentrain generate` after adding new models or changing fields

---

## Steps

### 1. Check Project State

Call `contentrain_status` to get the full project context:

- Confirm the project is initialized.
- List available models, their kinds, domains, and field counts.
- Note supported locales and the source locale.
- Check for any pending changes or validation errors.

If `.contentrain/` does not exist, stop and suggest running `/contentrain-init` first.

### 2. Identify the Target Model

If the user specified a model, use it. Otherwise:

- Present the list of available models from status.
- Ask the user which model to create content for.
- If the user describes content without naming a model (e.g., "write a blog post about X"), infer the model from context.

### 3. Read the Model Definition

Call `contentrain_describe(model: "<model-id>", include_sample: true)` to get:

- All field definitions (name, type, required, constraints).
- A sample entry if one exists (use it as a structural reference).
- Relation fields and their target models.

If the user's request does not match an existing model, offer to create one first with `contentrain_model_save`.

### 4. Read Vocabulary and Context

- Check `.contentrain/vocabulary.json` for canonical terms. All content must use these terms consistently across locales. Do not use alternative spellings or synonyms for vocabulary-defined terms.
- Check `.contentrain/context.json` for tone conventions (professional, casual, technical).
- **For dictionaries:** Before creating any new key, call `contentrain_content_list` on the target model and scan existing values. If the value you intend to write already exists under a different key, REUSE the existing key instead of creating a new one. MCP will also warn you via `advisories` in the save response if duplicates are detected. Replacing an existing key's value is allowed — the response reports what was replaced, so read the advisories rather than assuming a save was purely additive.

### 5. Generate Content

Create content following the rules in `content-quality.md`:

- **Required fields:** Every required field must have a real, non-placeholder value.
- **Field constraints:** Respect `min`, `max`, `pattern`, and `options` constraints.
- **Unique fields:** Verify `unique` field values do not collide with existing entries.
- **Tone:** Match the tone defined in `.contentrain/context.json` → `conventions.tone`.
- **Vocabulary:** Use terms from `.contentrain/vocabulary.json` if it exists.
- **Content patterns:** Follow the appropriate content type pattern (blog post, landing page, documentation, etc.) from `content-quality.md` Section 3.
- **Consistency:** If existing entries exist, read 2-3 via `contentrain_content_list` to match the established style and structure.

**Relation integrity:** For `relation` and `relations` fields, verify referenced entries exist by calling `contentrain_content_list` on the target model.

### 6. Apply SEO Rules

For fields that affect SEO (from `seo-rules.md`):

- **Title:** 50-60 characters optimal, max 70. Primary keyword in the first 30 characters.
- **Slug:** Lowercase, hyphen-separated, 3-5 words, no stop words.
- **Description/excerpt:** 120-160 characters, complete sentence, summarizes value.
- **Alt text:** Descriptive, includes context, under 125 characters.
- **Heading hierarchy:** In markdown/richtext content: h1 → h2 → h3 (no skips).

### 7. Present Draft for Approval

Show the user the content draft before writing. Include:

- The model name and kind.
- The content for each locale (if i18n).
- Any relations being set.
- A summary of which quality rules were applied.

Wait for user confirmation before proceeding.

### 8. Save Content

Call `contentrain_content_save` with the approved content. The tool takes `model` and an `entries` array:

```json
contentrain_content_save({
  "model": "<model-id>",
  "entries": [
    { "locale": "en", "data": { "field": "value" } }
  ]
})
```

**Kind-specific entry format:**

- **singleton:** `{ "locale": "en", "data": { "title": "My Site", "cta": "Get Started" } }` -- no `id` or `slug`.
- **collection:** `{ "id": "optional-id", "locale": "en", "data": { "name": "John", "role": "CEO" } }` -- omit `id` to auto-generate, provide `id` to update.
- **document:** `{ "slug": "getting-started", "locale": "en", "data": { "title": "Getting Started", "body": "# Welcome\n..." } }` -- `slug` is required, use `"body"` key for markdown content.
- **dictionary:** `{ "locale": "en", "data": { "auth.login": "Log In", "auth.logout": "Log Out" } }` -- flat key-value pairs, no `id` or `slug`.

**Critical rules:**
- NEVER include system fields (`status`, `source`, `updated_by`, `approved_by`) in `data`. These are managed in meta files, not content. Temporal data (created/updated timestamps) comes from git history.
- Prefer batch mode -- send multiple entries in a single call when possible.
- Locale defaults to the project's default locale if omitted, but explicit locale is recommended.

### 9. Review Save Advisories

After `contentrain_content_save`, check the response for an `advisories` field. If present:

- Review each advisory for duplicate value warnings.
- If a duplicate is flagged, consider whether to:
  - Remove the new key and reuse the existing one instead.
  - Keep both keys if they serve semantically different purposes (document the reason).
- Report any advisories to the user for their decision.

### 10. Handle i18n Completeness

If the project has multiple supported locales and the model has `i18n: true`:

- Ask the user if they want translations created now.
- If yes, generate translations following `i18n-quality.md` rules:
  - Translate meaning, not words.
  - Respect string expansion ratios.
  - Preserve tone across locales.
  - Check `vocabulary.json` for approved term translations.
- Call `contentrain_content_save` for each target locale.

If the user defers translations, note incomplete locales in the final summary.

### 11. Validate

Call `contentrain_validate` to check all changes:

- Schema compliance (all required fields, correct types).
- Referential integrity (relations point to existing entries).
- i18n completeness (all locales have matching keys).
- Content policy compliance.

Fix any errors reported. Acknowledge any warnings.

For large content operations (10+ entries), also recommend running `contentrain doctor --usage` to detect unused keys and duplicate values across the project.

### 12. Submit

Call `contentrain_submit` to push branches to remote:

- Write operations already create branches and commit changes automatically.
- `contentrain_submit` pushes unmerged `contentrain/*` branches to the remote.
- In `auto-merge` mode, branches are already merged to the base branch during the write operation.
- In `review` mode, branches are pushed for team review.

Report the Studio URL if provided in the tool response -- the user can review and approve content there.

### After Save: SDK Regeneration

When new models are created or fields change, regenerate the SDK client:

```bash
npx contentrain generate
```

This updates TypeScript types for the new content. See: **contentrain-generate** skill.

### 13. Final Summary

Report to the user:

- How many entries were created/updated.
- Which locales were covered.
- The validation result.
- The submission status (auto-merged or pending review).
- Studio link for visual review (if available).
- Next steps: run `/contentrain-generate` to update SDK types if models changed.

## Related Skills

- **contentrain-serve** — Browser-based review for content branches
- **contentrain-generate** — SDK client regeneration after content changes
- **contentrain-quality** — Content quality, SEO, and accessibility rules
- **contentrain** — Core architecture and MCP tool catalog
