---
name: jarvis-create-content
description: Create new Jarvis topics and content (text explanations, exercises, lessons) from markdown. Use when asked to create a new topic, write a text explanation, create an exercise, create a lesson, or build out a content topic with educational material.
argument-hint: <topic name or description of content to create>
---

# Jarvis Create Content

Use this skill to create new topics and content in the Jarvis CMS on **staging**.

For full markdown format reference, see `domains/jarvis/docs/MARKDOWN_IMPORT_AND_VALIDATION_API.md`.

## Scope

Use this skill when the user wants to:

- Create a new subject, topic, subtopic, or content topic in the topic hierarchy
- Write a text explanation (the main article for a content topic)
- Create an exercise with questions and answers
- Create a lesson with interactive steps

Do not use this skill for:

- Searching existing content (use `jarvis-search-content` instead)
- Linking content to topics or publishing (use `jarvis-publish-content` instead)

## Topic Hierarchy

```
subject (e.g. "Informatik")
  └── topic (e.g. "Softwareentwicklung")
        └── subtopic (e.g. "Moderne Architekturen")
              └── content topic (e.g. "MCP Server")
                    ├── textExplanation
                    ├── exercise(s)
                    └── lesson(s)
```

## Workflow

### 1. Create topic hierarchy (if needed)

Use `jarvis_create_topic` to create each level. You must create parent topics before children.

**Create a topic (under a subject):**
```
jarvis_create_topic({
  type: "topic",
  name: "Softwareentwicklung",
  subject: "content/internal/topics/<subject-id>",
  parent: "content/internal/topics/<subject-id>",
  description: "Grundlagen der Softwareentwicklung",
  alternativeNames: ["Software Engineering", "Programmierung"]
})
```

**Create a subtopic (under a topic):**
```
jarvis_create_topic({
  type: "subtopic",
  name: "Moderne Architekturen",
  subject: "content/internal/topics/<subject-id>",
  parent: "content/internal/topics/<topic-id>",
  description: "Moderne Softwarearchitekturen und Entwurfsmuster"
})
```

**Create a content topic (under a subtopic):**
```
jarvis_create_topic({
  type: "content",
  name: "MCP Server",
  subject: "content/internal/topics/<subject-id>",
  parent: "content/internal/topics/<subtopic-id>",
  description: "Was MCP Server sind und wann man sie einsetzt",
  alternativeNames: ["Model Context Protocol", "MCP"]
})
```

Key rules:
- `subject` must always reference the root subject identifier
- `parent` is the direct parent in the hierarchy
- `type` must match the hierarchy level: subject → topic → subtopic → content
- `name` is the display name (German for German content)
- `alternativeNames` help with search discoverability
- The response returns the new topic's full identifier (e.g. `content/internal/topics/<new-id>`)

**IMPORTANT: Parent topics must have a text explanation (presentation) before you can create subtopics or content topics under them.** If you try to create a child topic under a parent that has no presentation, you will get the error: `No default presentation found for parent topic`. The fix is to create a text explanation for the parent first using `jarvis_create_content_from_markdown`, then retry creating the child topic.

### 2. Create a text explanation

Text explanations are the main article content for a content topic. They use **plain markdown** — no HTML comment metadata required.

```
jarvis_create_content_from_markdown({
  contentType: "textExplanation",
  topicIdentifier: "content/internal/topics/<content-topic-id>",
  content: "<markdown content>"
})
```

#### Text explanation markdown format

Text explanations accept standard GitHub-Flavored Markdown: headings, paragraphs, lists, blockquotes, tables, code fences, inline code, TeX formulas (`$...$`), images, and horizontal rules.

Follow this structure (based on real simpleclub content):

```markdown
**Hook paragraph** — 2-3 sentences posing a question or setting up the topic. Use **bold** for key terms. End with "**simpleclub** erklärt dir..."

# <Topic Name> einfach erklärt

Overview section with key concepts. Use **bold** for important terms.

<!-- theme: info -->
> **Definition** or key concept in a callout block.

---

# <Topic Name> Erklärung

## Subsection 1

Detailed explanation with **bold key terms**.

## Subsection 2

More detail, examples, numbered lists for processes.

---

# <Topic Name> Beispiele

## Example 1

Concrete, practical example.

## Example 2

Another example.

# <Topic Name> Zusammenfassung

* Key point 1
* Key point 2
* Key point 3
```

Style guidelines:
- Write in German (unless specified otherwise)
- Use **bold** liberally for key terms and concepts
- Use `<!-- theme: info -->` blockquotes for definitions
- Use `---` horizontal rules to separate major sections
- Structure: Hook → Simple explanation → Detailed explanation → Examples → Summary
- Address the reader directly with "du/dir"
- Keep paragraphs short and scannable

### 3. Create an exercise

Exercises use **HTML comment metadata** to define tasks, questions, and solutions. This is critical — do NOT use heading-based structure like `## Task 1`.

```
jarvis_create_content_from_markdown({
  contentType: "exercise",
  topicIdentifier: "content/internal/topics/<content-topic-id>",
  name: "Exercise Name",
  content: "<exercise markdown with HTML comment metadata>"
})
```

#### Exercise markdown structure

Every exercise is divided into **tasks**. Each task starts with a task comment and contains a question section and an optional (but recommended) solution section:

```html
<!-- { "contentType": "task", "points": 1 } -->

<!-- { "collectionType": "question" } -->

Question content here

<!-- { "collectionType": "solution" } -->

Solution/explanation content here
```

**Critical rules:**
- All metadata must be valid JSON inside HTML comments with **double quotes**
- Invalid JSON in comments is silently ignored, causing follow-up validation errors
- `points` can be on the task comment or the question comment (task takes precedence)
- Points default to `1` when omitted during import
- Content limit: 40,000 characters

#### Exercise question types

Exercises support three question types:

**1. Multiple choice (checkbox MCQ):**

```html
<!-- { "contentType": "task", "points": 1 } -->

<!-- { "collectionType": "question" } -->

### Welches Protokoll nutzt MCP?

- [ ] GraphQL
- [x] JSON-RPC
- [ ] gRPC
- [ ] SOAP

<!-- { "collectionType": "solution" } -->

MCP verwendet **JSON-RPC** für die Kommunikation zwischen Client und Server.
```

Checkbox rules for exercises (intentionally tolerant):
- `[x]` marks correct answers, `[ ]` marks incorrect
- Missing correct answers produce a warning (not error)
- Fewer than 2 options produce a warning (not error)

**2. Free-text task:**

```html
<!-- { "contentType": "task", "points": 1 } -->

<!-- { "collectionType": "question", "questionType": "freeTextTask", "freeTextTaskType": "explain", "freeTextTaskExpectation": "The student should explain that MCP provides a standardized interface for AI to access external systems." } -->

### Erkläre den Hauptvorteil von MCP-Servern

Warum ist das Model Context Protocol ein Vorteil gegenüber proprietären Schnittstellen?

<!-- { "collectionType": "solution" } -->

MCP bietet eine **standardisierte Schnittstelle**, die von verschiedenen KI-Clients genutzt werden kann. Ohne MCP müsste jede KI-Anwendung eigene Integrationen für jedes externe System bauen.
```

Required metadata for free-text:
- `questionType`: must be `"freeTextTask"`
- `freeTextTaskType`: required, one of: `describe`, `name`, `compare`, `explain`, `coding_sql`, `coding_python`, `coding_java`, `coding_math`, `calculate`
- `freeTextTaskExpectation`: strongly recommended (describes expected answer)

**3. Dropdown/selectable:**

```html
<!-- { "contentType": "task", "points": 1 } -->

<!-- { "collectionType": "question", "questionType": "selectables" } -->

### Wähle die richtigen Begriffe

Ein ▼「MCP-Server▿✓MCP-Client✓▿MCP-Router」 sendet Anfragen an den Server. Die Kommunikation erfolgt über ▼「✓JSON-RPC✓▿REST▿GraphQL」.

<!-- { "collectionType": "solution" } -->

Der **MCP-Client** (z.B. Claude) sendet Anfragen, und die Kommunikation erfolgt über **JSON-RPC**.
```

Dropdown syntax: `▼「Option A▿✓Correct Option✓▿Option C」`
- `▼「...」` wraps the entire dropdown
- `▿` separates options
- `✓...✓` marks the single correct option
- `questionType` must be `"selectables"`
- Cannot mix with checkbox MCQ in the same question
- Each dropdown needs at least 2 options

#### Complete exercise example (multiple tasks)

```html
<!-- { "contentType": "task", "points": 1 } -->

<!-- { "collectionType": "question" } -->

### Was ist ein MCP-Server?

- [x] Ein Programm, das eine standardisierte Schnittstelle für KI-Assistenten bereitstellt
- [ ] Ein Webserver für statische Dateien
- [ ] Eine Datenbank für KI-Modelle
- [ ] Ein Compiler für Programmiersprachen

<!-- { "collectionType": "solution" } -->

Ein **MCP-Server** stellt eine standardisierte Schnittstelle nach dem Model Context Protocol bereit, über die KI-Assistenten auf externe Systeme zugreifen können.

<!-- { "contentType": "task", "points": 1 } -->

<!-- { "collectionType": "question", "questionType": "freeTextTask", "freeTextTaskType": "explain", "freeTextTaskExpectation": "MCP-Server bieten atomare, wiederverwendbare Tools; Skills definieren feste Arbeitsabläufe." } -->

### Erkläre den Unterschied

Was ist der Hauptunterschied zwischen einem MCP-Server und einem Skill?

<!-- { "collectionType": "solution" } -->

Ein **MCP-Server** bietet atomare, wiederverwendbare **Tools**, die von jedem MCP-Client flexibel kombiniert werden können. Ein **Skill** ist eine vorkonfigurierte **Anleitung**, die einen festen Arbeitsablauf beschreibt.

<!-- { "contentType": "task", "points": 1 } -->

<!-- { "collectionType": "question", "questionType": "selectables" } -->

### Ergänze die Lücken

MCP definiert drei Kernkonzepte: ▼「✓Tools✓▿Endpoints▿Routes」, ▼「✓Resources✓▿Schemas▿Models」 und ▼「✓Prompts✓▿Controllers▿Handlers」.

<!-- { "collectionType": "solution" } -->

Die drei Kernkonzepte von MCP sind **Tools** (Funktionen), **Resources** (Datenquellen) und **Prompts** (Vorlagen).
```

### 4. Create a lesson

Lessons use the same HTML comment metadata as exercises but add a required `answerType` field and stricter validation rules.

```
jarvis_create_content_from_markdown({
  contentType: "lesson",
  topicIdentifier: "content/internal/topics/<content-topic-id>",
  name: "Lesson Name",
  content: "<lesson markdown with HTML comment metadata>"
})
```

#### Lesson task types

Lessons have two task types controlled by `answerType`:

**`answerType: "next"` — contextual/informational steps (no interaction):**

```html
<!-- { "contentType": "task", "answerType": "next" } -->

<!-- { "collectionType": "question" } -->

### Einleitung

In dieser Lektion lernst du, was MCP-Server sind und wie sie funktionieren. MCP steht für **Model Context Protocol** und ist ein offener Standard von Anthropic.

<!-- { "collectionType": "solution" } -->
```

Rules for `next`:
- Question content must not be empty
- Checkbox items are NOT allowed
- Dropdown placeholders are NOT allowed
- Solution section is required but may be empty
- `points` should not be present (produces warning)

**`answerType: "regular"` — interactive assessment steps:**

```html
<!-- { "contentType": "task", "answerType": "regular", "points": 1 } -->

<!-- { "collectionType": "question" } -->

### Welches Transportprotokoll nutzt MCP?

- [x] JSON-RPC
- [ ] GraphQL

<!-- { "collectionType": "solution" } -->

MCP verwendet **JSON-RPC** für die Kommunikation.
```

Rules for `regular`:
- Supports free text, checkbox MCQ, and dropdown questions
- `points` must be positive if present (defaults to `1` on import)
- Solution section is required; empty solution produces a warning
- Checkbox MCQs are validated strictly: at least 2 options required, at least one `[x]`

#### Complete lesson example

```html
<!-- { "contentType": "task", "answerType": "next" } -->

<!-- { "collectionType": "question" } -->

### Was ist MCP?

Das **Model Context Protocol (MCP)** ist ein offener Standard, der definiert, wie KI-Assistenten mit externen Systemen kommunizieren. Man kann es sich wie **USB für KI** vorstellen.

<!-- { "collectionType": "solution" } -->

<!-- { "contentType": "task", "answerType": "regular", "points": 1 } -->

<!-- { "collectionType": "question" } -->

### Wofür steht MCP?

- [ ] Multi Cloud Platform
- [x] Model Context Protocol
- [ ] Machine Communication Protocol

<!-- { "collectionType": "solution" } -->

**MCP** steht für **Model Context Protocol**.

<!-- { "contentType": "task", "answerType": "regular", "points": 1 } -->

<!-- { "collectionType": "question", "questionType": "selectables" } -->

### Ergänze

Ein MCP-Server kommuniziert über ▼「✓JSON-RPC✓▿REST▿SOAP」 und kann über ▼「✓stdio✓▿TCP▿UDP」 oder ▼「✓HTTP (SSE)✓▿WebSocket▿gRPC」 transportiert werden.

<!-- { "collectionType": "solution" } -->

MCP nutzt **JSON-RPC** über **stdio** (lokal) oder **HTTP mit Server-Sent Events** (remote).
```

### 5. Edit existing content

There is no in-place edit API. To update existing content, use `overwriteExisting: true` which **deletes all existing content of that type** for the topic and creates new content.

```
jarvis_create_content_from_markdown({
  contentType: "textExplanation",
  topicIdentifier: "content/internal/topics/<id>",
  content: "<new markdown>",
  overwriteExisting: true
})
```

**Critical editing behaviors to understand:**

**Text explanations:**
- Without `overwriteExisting`, creating again will add a **second presentation** to the topic (duplicates). Always use `overwriteExisting: true` when editing.
- **Published text explanations cannot be overwritten.** You will get: `Cannot delete presentations for a published topic`. You must unpublish the text explanation first, then overwrite, then republish:
  1. `jarvis_publish_content({ contentType: "textExplanation", action: "unpublish", topicIdentifier: "..." })`
  2. `jarvis_create_content_from_markdown({ ..., overwriteExisting: true })`
  3. `jarvis_publish_content({ contentType: "textExplanation", action: "publish", topicIdentifier: "..." })`

**Exercises and lessons:**
- `overwriteExisting: true` creates content with a **new identifier** — the old identifier is deleted.
- **Old story links are NOT cleaned up.** The old exercise/lesson remains linked to the topic story even though its content is gone. You must manually link the new exercise/lesson to the topic after overwriting.
- Recommended edit workflow for exercises:
  1. `jarvis_create_content_from_markdown({ contentType: "exercise", ..., overwriteExisting: true })` → note the new identifier
  2. `jarvis_link_content_to_topic({ contentType: "exercise", exerciseIdentifier: "<new-id>", topicIdentifier: "..." })`
  3. The old exercise link will remain as a stale entry in the topic story

## Common Errors

### Structural errors
- `Task 1: Must start with <!-- { "contentType": "task" } -->` — first task missing task comment
- `Missing question section with <!-- { "collectionType": "question", ... } -->` — task has no question
- `Missing solution section` — lesson task missing solution comment
- `No tasks found in exercise/lesson markdown` — no task comments found at all

### Metadata errors
- `answerType: Required` — lesson task missing required answerType
- `freeTextTaskType is required when questionType is "freeTextTask"` — missing freeTextTaskType

### Dropdown errors
- `Dropdown placeholders require questionType "selectables"` — forgot to set questionType
- `Dropdown selectable syntax cannot be mixed with checkbox MCQ syntax` — mixed dropdowns and checkboxes
- `Dropdown 1 must mark exactly 1 correct option inline using ✓...✓` — missing or multiple correct markers

## Reporting

Always report:
- Each topic created with its identifier and position in the hierarchy
- Content created with its type, identifier, and a brief summary
- Any warnings returned by the API

## Tips

- Always search first (`jarvis-search-content`) to avoid duplicating existing topics
- Create the full topic hierarchy top-down before creating content
- **Critical order**: For each level, create the topic THEN immediately create its text explanation BEFORE creating any child topics under it. The API requires a presentation to exist on a parent before children can be added.
- Save returned identifiers — you'll need them for linking and publishing
- Text explanations don't need a `name` parameter (it comes from the topic)
- Exercises and lessons require a `name` parameter
- Exercise validation is intentionally tolerant (warnings not errors for missing answers). Lesson validation is strict.
- Prefer mixing question types in exercises for variety (MCQ + free-text + dropdown)

## Content Type Summary

| Content type | HTML metadata required | Solution required | `answerType` required | Dropdowns supported |
| --- | --- | --- | --- | --- |
| Text explanation | No | No | No | No |
| Exercise | Yes | Recommended | No | Yes |
| Lesson | Yes | Yes | Yes (`next` or `regular`) | Yes, only for `regular` |
