generate-lesson — for Claude Code generate-lesson, Japanese_Learning_Website, community, for Claude Code, ide skills, thumbnail_url, Vocabulary.image_url, docker compose ps db, docker compose up db -d, ADMIN_EMAIL

v1.0.0

关于此技能

适用场景: Ideal for AI agents that need generate-lesson — anfänger-lektionen für japanese-learning.ch. 本地化技能摘要: # generate-lesson — Anfänger-Lektionen für japanese-learning.ch Auftrag Erstelle eine komplette, sofort nutzbare Lektion für Mayuko und andere deutschsprachige Anfänger. This AI agent skill supports Claude Code, Cursor, and Windsurf workflows.

功能特性

generate-lesson — Anfänger-Lektionen für japanese-learning.ch
Einzige Ausnahme: Bilder. Für thumbnail url und Vocabulary.image url kannst du DALL-E per Script
Start-Check (immer zuerst)
Bevor du überhaupt Content schreibst:
Lies learnings.md. Dort steht, was in vorherigen Runs geklappt hat und was nicht. Wende diese

# 核心主题

ClaudioLutz ClaudioLutz
[0]
[0]
更新于: 4/24/2026

Killer-Skills Review

Decision support comes first. Repository text comes second.

Reference-Only Page Review Score: 10/11

This page remains useful for teams, but Killer-Skills treats it as reference material instead of a primary organic landing page.

Original recommendation layer Concrete use-case guidance Explicit limitations and caution Quality floor passed for review
Review Score
10/11
Quality Score
52
Canonical Locale
de
Detected Body Locale
de

适用场景: Ideal for AI agents that need generate-lesson — anfänger-lektionen für japanese-learning.ch. 本地化技能摘要: # generate-lesson — Anfänger-Lektionen für japanese-learning.ch Auftrag Erstelle eine komplette, sofort nutzbare Lektion für Mayuko und andere deutschsprachige Anfänger. This AI agent skill supports Claude Code, Cursor, and Windsurf workflows.

核心价值

推荐说明: generate-lesson helps agents generate-lesson — anfänger-lektionen für japanese-learning.ch. generate-lesson — Anfänger-Lektionen für japanese-learning.ch Auftrag Erstelle eine komplette, sofort nutzbare Lektion

适用 Agent 类型

适用场景: Ideal for AI agents that need generate-lesson — anfänger-lektionen für japanese-learning.ch.

赋予的主要能力 · generate-lesson

适用任务: Applying generate-lesson — Anfänger-Lektionen für japanese-learning.ch
适用任务: Applying Einzige Ausnahme: Bilder. Für thumbnail url und Vocabulary.image url kannst du DALL-E per Script
适用任务: Applying Start-Check (immer zuerst)

! 使用限制与门槛

  • 限制说明: Requires repository-specific context from the skill documentation
  • 限制说明: Works best when the underlying tools and dependencies are already configured

Why this page is reference-only

  • - Current locale does not satisfy the locale-governance contract.

Source Boundary

The section below is imported from the upstream repository and should be treated as secondary evidence. Use the Killer-Skills review above as the primary layer for fit, risk, and installation decisions.

评审后的下一步

先决定动作,再继续看上游仓库材料

Killer-Skills 的主价值不应该停在“帮你打开仓库说明”,而是先帮你判断这项技能是否值得安装、是否应该回到可信集合复核,以及是否已经进入工作流落地阶段。

实验室 Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

常见问题与安装步骤

以下问题与步骤与页面结构化数据保持一致,便于搜索引擎理解页面内容。

? FAQ

generate-lesson 是什么?

适用场景: Ideal for AI agents that need generate-lesson — anfänger-lektionen für japanese-learning.ch. 本地化技能摘要: # generate-lesson — Anfänger-Lektionen für japanese-learning.ch Auftrag Erstelle eine komplette, sofort nutzbare Lektion für Mayuko und andere deutschsprachige Anfänger. This AI agent skill supports Claude Code, Cursor, and Windsurf workflows.

如何安装 generate-lesson?

运行命令:npx killer-skills add ClaudioLutz/Japanese_Learning_Website/generate-lesson。支持 Cursor、Windsurf、VS Code、Claude Code 等 19+ IDE/Agent。

generate-lesson 适用于哪些场景?

典型场景包括:适用任务: Applying generate-lesson — Anfänger-Lektionen für japanese-learning.ch、适用任务: Applying Einzige Ausnahme: Bilder. Für thumbnail url und Vocabulary.image url kannst du DALL-E per Script、适用任务: Applying Start-Check (immer zuerst)。

generate-lesson 支持哪些 IDE 或 Agent?

该技能兼容 Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer。可使用 Killer-Skills CLI 一条命令通用安装。

generate-lesson 有哪些限制?

限制说明: Requires repository-specific context from the skill documentation;限制说明: Works best when the underlying tools and dependencies are already configured。

安装步骤

  1. 1. 打开终端

    在你的项目目录中打开终端或命令行。

  2. 2. 执行安装命令

    运行:npx killer-skills add ClaudioLutz/Japanese_Learning_Website/generate-lesson。CLI 会自动识别 IDE 或 AI Agent 并完成配置。

  3. 3. 开始使用技能

    generate-lesson 已启用,可立即在当前项目中调用。

! 参考页模式

此页面仍可作为安装与查阅参考,但 Killer-Skills 不再把它视为主要可索引落地页。请优先阅读上方评审结论,再决定是否继续查看上游仓库说明。

Upstream Repository Material

The section below is imported from the upstream repository and should be treated as secondary evidence. Use the Killer-Skills review above as the primary layer for fit, risk, and installation decisions.

Upstream Source

generate-lesson

安装 generate-lesson,这是一款面向AI agent workflows and automation的 AI Agent Skill。查看评审结论、使用场景与安装路径。

SKILL.md
Readonly
Upstream Repository Material
The section below is imported from the upstream repository and should be treated as secondary evidence. Use the Killer-Skills review above as the primary layer for fit, risk, and installation decisions.
Supporting Evidence

generate-lesson — Anfänger-Lektionen für japanese-learning.ch

Auftrag

Erstelle eine komplette, sofort nutzbare Lektion für Mayuko und andere deutschsprachige Anfänger. Du schreibst den gesamten Text-Content selbst (keine OpenAI/Gemini-Calls). Der Skill ist der Orchestrator: Er gibt dir Schema, Guardrails und die Persistierungs-/Verifikations-/Git-Schritte vor; du produzierst den japanischen Content als strukturiertes JSON.

Einzige Ausnahme: Bilder. Für thumbnail_url und Vocabulary.image_url kannst du DALL-E per Script aufrufen (siehe §7).


1. Start-Check (immer zuerst)

Bevor du überhaupt Content schreibst:

  1. Lies learnings.md. Dort steht, was in vorherigen Runs geklappt hat und was nicht. Wende diese Regeln strikt an.
  2. Lies improve-jpl/SKILL.md. Die Produkt-Vision (Mayuko-Lackmustest, Nicht-Ziele) gilt uneingeschränkt.
  3. Docker-Stack muss laufen — zweistufiger Check:
    • a) Docker-Desktop-Prozess: docker compose ps db schlägt mit "cannot find the file specified" / "docker daemon not running" fehl, wenn Docker Desktop nicht läuft. In dem Fall: Start-Process "C:\Program Files\Docker\Docker\Docker Desktop.exe" (PowerShell) — Start dauert 30–60 s.
    • b) DB-Container: Danach docker compose up db -d und mit docker exec postgres_db pg_isready -U app_user -d japanese_learning warten, bis "accepting connections" erscheint.
  4. DB-Status prüfen: Führe python .claude/skills/generate-lesson/pipeline.py status aus. Das zeigt, welche Themen/JLPT-Level wenig approved Content haben — Grundlage für Vorschlag bei Aufruf ohne Argumente.
  5. Admin-Credentials aus .env: Für alle verifikationsbezogenen Logins gilt ADMIN_EMAIL und ADMIN_PASSWORD aus der lokalen .env. NIEMALS hardcoden. Login-Form-Feld heisst email (nicht username), Post-Login-Redirect ist /admin (nicht /dashboard).

2. Input-Modi

AufrufVerhalten
/generate-lesson (ohne Args)DB-Gap-Analyse → 3 Themen-Vorschläge mit Begründung → User wählt
/generate-lesson N5 FamilieDirektes Thema, JLPT-Level N5. Wenn thematisch passendes MNN-Kapitel existiert, orientiere dich daran (siehe §2a).
/generate-lesson --from-mnn 3Quelle: Minna no Nihongo Kapitel 3 (lies scripts/mnn_data/beginner1_lesson03.json). Siehe §2a.
/generate-lesson --from-jlpt N5Zufälliges noch nicht abgedecktes N5-Thema

2a. Minna-no-Nihongo-Quellen (WICHTIG)

Rohdaten liegen vor: scripts/mnn_data/beginner1_lesson01.jsonbeginner2_lesson50.json (50 Lektionen). Jede Datei enthält vocabulary[], vocabulary_countries[], grammar[], conversation{title, lines[]} und teils additional_conversations[]. Die bestehenden 10 Lektionen in der DB (IDs 131–141, Titel MNN L1…L5 EN+DE) wurden per scripts/import_mnn.py direkt importiert, ohne AI, als wörtliche Übernahme.

Wie Claude MNN nutzt:

  1. MNN ist Vorlage, nicht Copy-Paste. Die bestehenden 10 Lektionen sind Wort-für-Wort-Import. Deine Aufgabe: auf derselben thematischen/grammatikalischen/vokabulären Linie eine neue Lektion schreiben, mit:
    • Anderen Namen/Personen. MNN nutzt Mike Miller, Satou Keiko, Guputa-san, Yamada. Du nutzt andere Namen (z.B. Tanaka Haruto, Lisa Weber, Ueno Sensei). Keine MNN-Originalfiguren wiederverwenden.
    • Leicht anderen Beispielsätzen — gleiche Grammatik, gleiche Vokabelsätze, aber neu formuliert. Kein Satz wird 1:1 aus der MNN-JSON übernommen.
    • Gleichem Grammatik-Kern — wenn MNN-Kapitel 3 Demonstrativpronomen lehrt, lehrst auch du Demonstrativpronomen, mit denselben Strukturen (これ/それ/あれ + は + N + です).
  2. Vokabeln übernehmen: Die Vokabel-Liste aus MNN-JSON darfst du weitgehend übernehmen (Vocabulary-Tabelle ist eh dedupliziert — Wörter wie わたし sind schon da). Füge Romaji hinzu, wenn fehlt.
  3. Konversation ist Pflicht — siehe §4 Page-Struktur "Dialog/Anwendung". Nutze dieselbe speaker / japanese / romaji / english-Struktur wie in der MNN-JSON, aber mit deinen neuen Namen und leicht anderem Verlauf.
  4. Zusätzlicher DB-Gap-Check: Bevor du eine neue Lektion zu MNN-Kapitel N schreibst, prüfe ob MNN L{N}: bereits existiert (Lesson.title LIKE MNN L{N}:%). Wenn ja, wähle einen Titel ohne MNN L{N}:-Präfix, damit es keine Kollision mit dem Original-Import gibt (z.B. N5 Selbstvorstellung — Tanaka trifft Lisa).

Konversations-Plaintext-Format (entspricht _format_conversation in scripts/import_mnn.py:170):

Tanaka: こんにちは。わたしは たなかです。
  (Konnichiwa. Watashi wa Tanaka desu.)
  → Guten Tag. Ich bin Tanaka.

Lisa: はじめまして。リサです。ドイツから きました。
  (Hajimemashite. Risa desu. Doitsu kara kimashita.)
  → Freut mich. Ich bin Lisa. Ich komme aus Deutschland.

Leerzeile zwischen Sprechern, Einrückung der Romaji-Zeile mit zwei Leerzeichen, für die deutsche Übersetzung.

3. Harte Constraints (Nicht-Verhandelbar)

Verletzung ⇒ sofortiger Abbruch, keine Insertion:

  • Quiz-Typen NUR: multiple_choice, true_false, matching. KEIN fill_blank (siehe CLAUDE.md §"Quiz-System").
  • JLPT-Level NUR: N5 oder N4. Kein N3/N2/N1 (siehe improve-jpl §"Nicht-Ziele").
  • Keine Umlaut-Fallbacks in allen deutschen Texten (Einleitung, Grammar-Explanation, Quiz-Frage/Hint/Explanation/Feedback, Dialog-Übersetzung, Zusammenfassung, Lesson.description/title, LessonPage.title): immer Ü/Ö/Ä/ß (oder ss), niemals UE/OE/AE/SS. "Schüler" statt "Schueler", "höflich" statt "hoeflich", "Grüße" statt "Gruesse", "für" statt "fuer". UTF-8 durchgängig. Gilt auch in content_text, hint, explanation, feedback, option_text — überall, wo deutscher Fliesstext steht.
  • Rōmaji NEBEN JEDEM japanischen Zeichen, das der Lerner nicht automatisch lesen kann — überall, ausnahmslos. Jedes Auftreten von Kanji/Hiragana/Katakana in einem Text-Feld bekommt in derselben Zeile Rōmaji in Klammern (romaji). Folgende Felder sind alle betroffen:
    • LessonContent.content_text (Einleitung, Grammatik-Erklärung, Dialog, Zusammenfassung): jedes JP-Wort/Phrase mit Rōmaji in Klammern. Beispiel: Dort begrüßt dich das Personal mit 「いらっしゃいませ」 (irasshaimase, 'Willkommen'). In jedem Satz neu, nicht nur beim ersten Vorkommen.
    • Grammar.title: wenn der Titel JP-Zeichen enthält (〜をください (höfliche Bitte)), muss Rōmaji dabei sein → 〜をください (~ wo kudasai — höfliche Bitte).
    • Grammar.structure: wenn die Struktur JP-Zeichen enthält ([Nomen] + を + ください), muss direkt danach die Rōmaji-Variante stehen. Da das structure-Feld nur einzelne Zeile ist: Rōmaji in derselben Zeile in Klammern, z.B. [Nomen] + を + ください ([noun] + wo + kudasai). Zusätzlich bleibt das Grammar.romaji-Feld (wird separat gerendert). Beide redundant zu haben ist OK — das Template zeigt mal das eine, mal das andere, Mayuko sieht es so oder so.
    • Grammar.explanation (DE-Erklärung): jeder JP-Ausdruck in Klammern mit Rōmaji. 「を」 (wo, ausgesprochen 'o') statt nur 「を」.
    • Grammar.example_sentences: jeder JP-Satz JP-Zeile → Rōmaji-Zeile → DE-Zeile (dreizeilig).
    • QuizQuestion.question_text, .hint, .explanation: wenn JP-Zeichen darin stehen, Rōmaji in Klammern. Was bedeutet 「水」 (mizu)? statt Was bedeutet 「水」?.
    • QuizOption.option_text, .feedback: wenn JP darin steht, Rōmaji in Klammern. In Matching-Optionen 肉 (niku) | Fleisch statt 肉 | Fleisch.
    • Vocabulary.romaji (Datenbankfeld, eigene Spalte): Hepburn-Rōmaji des Wortes.
    • Vocabulary.example_sentence_english beginnt mit Rōmaji-Satz, Format "Romaji — English" (bereits in §5 beschrieben).
    • Vocabulary.example_sentence_japanese bleibt rein JP — dort ist Rōmaji redundant, weil reading + romaji in derselben Vokabel-Karte stehen.
    • Ziel: Mayuko kann jeden Satz überall in der Lektion westlich aussprechen, selbst wenn sie ein Kanji nicht kennt.
  • Instruction-Language: default 'german' (Mayuko ist primäre Zielgruppe). Englisch nur auf explizite User-Anweisung.
  • Beispielsätze dürfen NUR Kanji/Vokabeln des eigenen oder eines niedrigeren JLPT-Levels enthalten. N5-Lektion darf keine N3-Kanji im Beispielsatz haben. Wenn unvermeidbar: schreibe den Satz in Hiragana.
  • created_by_ai = True für alle generierten Kana/Kanji/Vocabulary/Grammar-Einträge. LessonContent.generated_by_ai = True ebenfalls.
  • status = 'approved' direkt (User-Entscheidung 2026-04-20).
  • Duplicate-Check: Vor jedem INSERT in Kana/Kanji/Vocabulary/Grammar prüfen ob character/word/title schon existiert → bestehende ID wiederverwenden, NICHT neue Zeile erzeugen.
  • KEIN HTML in content_text (content_type text). Das Template lesson_view.html:683 rendert mit | nl2br, nicht | safe — alle Tags erscheinen als Text. Nutze Plaintext mit \n\n für Absätze, keine <p>, <b>, <ul> usw. Für Hervorhebung: Anführungszeichen 「…」 (japanisch) oder kursiv via Markdown-Konvention im Plaintext.
  • Rōmaji ist PFLICHT — an drei Stellen:
    1. Vocabulary.romaji (neue Spalte seit Migration a3f5c2d1b8e9): Hepburn-Transkription des Wortes, z.B. word="家族", reading="かぞく", romaji="kazoku".
    2. Grammar.romaji (bestand schon): Struktur in Rōmaji, z.B. "[noun] + wo + kudasai".
    3. example_sentence_english: muss mit Rōmaji-Version des Satzes beginnen, Format "Romaji — English meaning", z.B. "Watashi no kazoku wa yo-nin desu. — My family has four people.". So sieht Mayuko in JEDER Darstellung die westliche Lesung.
  • Bilder sind PFLICHTthumbnail_url muss vor Insert gesetzt sein. Pipeline-Schritt images (DALL-E) läuft vor insert, NICHT optional. Zusätzlich: jede Vokabel muss image_url haben (MNN-DE-Standard, siehe §4-Budget).
  • Vocabulary.image_url muss relativ zu UPLOAD_FOLDER sein (= app/static/uploads/), NICHT absolut. Das Template lesson_view.html:859 ruft url_for('routes.uploaded_file', filename=content_data.image_url) auf — die Route routes.py:3973 /uploads/<path:filename> dient aus UPLOAD_FOLDER. Richtige Werte: vocab_generated/vocab_abc.png, vocabulary/images/vocab_124.png. Falsch: /static/uploads/vocab_generated/…, http://…, static/uploads/….
  • Audio für die Konversation ist PFLICHT — jede Dialog-Page bekommt ein eigenes LessonContent(content_type='audio') vor dem Dialog-Text (order_index=1, Text auf order_index=2). Der Pipeline-Schritt audio {lesson_id} rendert via Google Cloud TTS (Neural2-B, langsam=0.85) eine einzige MP3 mit allen japanischen Sprecher-Zeilen, 700ms-Pausen dazwischen. Speicherort: app/static/uploads/lessons/audio/lesson_{id}/conversation.mp3. Felder im LessonContent: file_path="lessons/audio/lesson_{id}/conversation.mp3" (relativ zu UPLOAD_FOLDER!), file_type="audio/mpeg", title="Konversation (Audio)". Das Template (lesson_view.html:674) nutzt content.get_file_url() — der GCS-aware Resolver im Model models.py:463. Benötigt GOOGLE_API_KEY oder GOOGLE_TTS_API_KEY in .env.

4. Lektions-Struktur (Zielbild) — erweitert 2026-04-24

Eine Lektion muss substantiell sein, damit Mayuko echten Lernwert hat. Zu dünn ⇒ zurückgeschickt. Jede generierte Lektion enthält mindestens 5 Seiten:

Lesson (title, description, jlpt_level→difficulty_level 1-5, instruction_language='german',
        lesson_type='free', is_published=False (erst nach Sichtung True),
        allow_guest_access=True für erste Lektion pro Thema,
        thumbnail_url=DALL-E-URL (Pflicht!))

├─ LessonPage 1: "Einführung" (page_type='normal')
│   └─ LessonContent: text — DE-Einleitung (4-8 Sätze, Plaintext!),
│      was lernst du, warum ist es im Alltag nützlich, typische Situation.
│
├─ LessonPage 2: "Vokabeln Teil 1" (page_type='normal')
│   └─ LessonContent: vocabulary ×8-12 — erste Hälfte der Wörter,
│      thematisch homogen. Jede Vokabel: word + reading + romaji + meaning_de +
│      example_sentence_japanese + example_sentence_english (mit Romaji-Prefix).
│      Mind. 1 dieser Vokabeln hat image_url (DALL-E).
│
├─ LessonPage 3: "Vokabeln Teil 2" (page_type='normal')
│   └─ LessonContent: vocabulary ×7-13 — zweite Hälfte.
│      Mind. 1-2 weitere image_urls.
│
├─ LessonPage 4: "Grammatik" (page_type='normal')
│   ├─ LessonContent: text — DE-Erklärung des Musters (Plaintext, mehrere Absätze).
│   └─ LessonContent: grammar ×2-4 — mit structure, romaji, 3-4 Beispielsätzen
│      je Eintrag (jeweils JP + Romaji + DE-Übersetzung).
│
├─ LessonPage 5: "Dialog / Konversation" (page_type='normal') — PFLICHT
│   └─ LessonContent: text — realistischer Mini-Dialog (6–10 Zeilen).
│      **KEIN Einleitungs-Absatz vor dem Dialog.** Der `content_text` beginnt
│      unmittelbar mit der ersten Sprecher-Zeile (`Tanaka: ...`), wie bei
│      MNN L1–L5 DE (Lessons 137–141). Szenario/Setting gehören in den
│      LessonContent.title (z.B. "Willkommensparty — Tanaka trifft Lisa"),
│      nicht in einen Prosa-Vorspann. Grund: `| nl2br` rendert nur Zeilen-
│      umbrüche — ein Prosa-Absatz vor dem Dialog lässt das Konversations-
│      Element visuell in einer Textwand verschwinden.
│      Format **exakt wie `_format_conversation()` in scripts/import_mnn.py:170**:
│         Speaker: 日本語テキスト
│           (romaji)
│           -> Deutsche Übersetzung       ← ASCII-Pfeil `->`, NICHT `→`
│         (Leerzeile)
│      **Format muss exakt dem MNN-DE-Standard entsprechen** (Lessons 137–141):
│      `_format_conversation()` in scripts/import_mnn.py:170 nutzt `->`, nicht
│      den Unicode-Pfeil. Templates rendern beide gleich via `| nl2br`, aber die
│      Konsistenz mit den bestehenden DE-Lektionen ist Pflicht.
│      Sprecher sind **eigene Namen** (nicht Miller/Satou aus MNN).
│      Wenn die Lektion thematisch einem MNN-Kapitel entspricht: Dialog-Struktur
│      orientiert sich an der MNN-`conversation`-Vorlage aus `scripts/mnn_data/`,
│      aber Text ist neu formuliert (andere Namen, leichte Variation). Siehe §2a.
│
├─ LessonPage 6: "Übung" (page_type='quiz_carousel')
│   └─ LessonContent mit QuizQuestions ×10-18 — Mix aus
│      multiple_choice / true_false / matching. Mind. 3 Typen, jeder Typ ≥2×.
│      Distraktoren aus derselben semantischen Domäne.
│
└─ LessonPage 7: "Zusammenfassung" (page_type='normal')
    └─ LessonContent: text — Review der Kern-Vokabeln/Grammatik,
       Lerntipps, konkreter Ausblick auf die nächste Lektion.

Budget pro Lektion (hart validiert):

  • Vokabeln: 15–25 (vorher 8–12 war zu wenig).
  • Grammatik: 2–4 (vorher 1–2 war zu dünn).
  • Quiz: 10–18 (vorher 6–10 war zu wenig Übung).
  • Pages: ≥5.
  • Thumbnail-Bild: 1 (Pflicht).
  • Vokabel-Bilder: ALLE Vokabeln (nicht mehr nur 3 — angehoben 2026-04-24 nach Sichtung von MNN L1–L5 DE, wo ausnahmslos jede Vocabulary-Zeile ein image_url hat). Pipeline-Schritt images generiert per AILessonContentGenerator. generate_vocabulary_image() für jede Vokabel ohne image_url ein Icon und speichert es unter app/static/uploads/vocab_generated/vocab_{id}_{hash}.png. Bestehende Vokabeln mit image_url werden übersprungen (idempotent).

Die Lektion ist kein 5-Minuten-Happen, sondern eine 20–30-Minuten-Einheit.

5. Content-Qualität: Beispiel-Patterns

Vocabulary-Eintrag (Claude schreibt)

json
1{ 2 "word": "家族", 3 "reading": "かぞく", 4 "romaji": "kazoku", 5 "meaning": "family", 6 "meaning_de": "Familie", 7 "jlpt_level": 5, 8 "example_sentence_japanese": "わたしの かぞくは よにんです。", 9 "example_sentence_english": "Watashi no kazoku wa yo-nin desu. — My family has four people.", 10 "image_url": null, 11 "status": "approved", 12 "created_by_ai": true 13}

Regeln:

  • word + reading + romaji + meaning + meaning_de sind alle Pflicht.
  • reading in Hiragana (nie Katakana, ausser bei Lehnwörtern wie メニュー).
  • romaji Hepburn-Transkription des ganzen Wortes, Kleinschreibung, Trennstriche bei zusammengesetzten Lesungen (yo-nin, o-cha).
  • example_sentence_japanese nutzt Leerzeichen zwischen Wörtern bei N5 (Hiragana-Fokus).
  • example_sentence_english muss Format "Romaji-Satz — English translation" haben — so liest Mayuko den Satz auch westlich, nicht nur Hiragana.
  • Beispielsatz max ~12 Silben / ca. 8 Wörter.
  • image_url: Bei Schlüsselvokabeln (≥3 pro Lektion) DALL-E-URL. Sonst null.

Grammar-Eintrag

json
1{ 2 "title": "です / ist (Höflichkeitsform)", 3 "explanation": "「です」 ist die höfliche Kopula und entspricht dem deutschen 'ist/sind'. Es steht am Satzende nach einem Nomen oder Na-Adjektiv und markiert einen Aussagesatz als formell.", 4 "structure": "[Nomen] + です", 5 "romaji": "[noun] + desu", 6 "jlpt_level": 5, 7 "example_sentences": "わたしは がくせいです。 (Watashi wa gakusei desu.) — Ich bin Student/in.\nこれは ほんです。 (Kore wa hon desu.) — Das ist ein Buch.", 8 "status": "approved", 9 "created_by_ai": true 10}

Regeln:

  • explanation auf Deutsch, 2-4 Sätze, konkret ohne Linguistik-Jargon
  • structure kurz und in eckigen Klammern, z.B. [Nomen] + です
  • example_sentences mit 2-3 Beispielen, jeweils Japanisch + Romaji + DE-Übersetzung

Multiple-Choice-Frage

json
1{ 2 "question_type": "multiple_choice", 3 "question_text": "Was bedeutet 家族 (かぞく)?", 4 "difficulty_level": 1, 5 "points": 1, 6 "hint": "Es geht um Personen, die zusammenleben.", 7 "explanation": "家族 (かぞく) heisst 'Familie'. Das erste Kanji 家 bedeutet 'Haus', das zweite 族 'Stamm/Gruppe'.", 8 "options": [ 9 {"option_text": "Familie", "is_correct": true, "feedback": "Richtig!"}, 10 {"option_text": "Schule", "is_correct": false, "feedback": "Das wäre 学校 (がっこう)."}, 11 {"option_text": "Freund", "is_correct": false, "feedback": "Das wäre 友達 (ともだち)."}, 12 {"option_text": "Arbeit", "is_correct": false, "feedback": "Das wäre 仕事 (しごと)."} 13 ] 14}

Regeln:

  • Genau 4 Optionen bei multiple_choice, davon genau 1 korrekt
  • Distraktoren müssen plausibel sein (andere N5-Vokabeln, nicht offensichtlich falsch)
  • feedback pro Option immer füllen — das ist Mayukos Lerneffekt bei Fehlern

True-False-Frage

json
1{ 2 "question_type": "true_false", 3 "question_text": "「ともだち」 bedeutet 'Bruder'.", 4 "difficulty_level": 1, 5 "explanation": "「ともだち」 heisst 'Freund'. 'Bruder' ist 「きょうだい」 (兄弟).", 6 "options": [ 7 {"option_text": "Richtig", "is_correct": false, "feedback": "Ungenau: ともだち = Freund."}, 8 {"option_text": "Falsch", "is_correct": true, "feedback": "Korrekt — ともだち heisst Freund."} 9 ] 10}

Matching-Frage

json
1{ 2 "question_type": "matching", 3 "question_text": "Verbinde das japanische Wort mit der deutschen Übersetzung.", 4 "difficulty_level": 2, 5 "options": [ 6 {"option_text": "父 (chichi)", "feedback": "Vater", "is_correct": true}, 7 {"option_text": "母 (haha)", "feedback": "Mutter", "is_correct": true}, 8 {"option_text": "姉 (ane)", "feedback": "ältere Schwester", "is_correct": true}, 9 {"option_text": "兄 (ani)", "feedback": "älterer Bruder", "is_correct": true} 10 ] 11}

Matching-Konvention in dieser Codebase (exakt wie Template lesson_view.html:744-752 erwartet):

  • option_text = linke Seite (Prompt, z.B. das japanische Wort mit Rōmaji in Klammern — NICHT mit |-Trenner).
  • feedback = rechte Seite (die Antwort, die im Dropdown auswählbar erscheint, z.B. die deutsche Übersetzung).
  • is_correct = true für alle Optionen — das Frontend shuffelt die feedback-Werte und der User muss jeden option_text dem richtigen feedback-Wert zuordnen.

Achtung — häufiger Fehler: Ein Format wie option_text="JP | DE" mit leerem feedback führt dazu, dass das Dropdown nur „None" anzeigt. Immer gesplittet speichern.

6. Pipeline-Ablauf

[1] Claude schreibt gesamten Lektions-JSON:
    .claude/skills/generate-lesson/drafts/{timestamp}_{topic}.json

[2] python .claude/skills/generate-lesson/pipeline.py validate {draft_path}
    → prüft Constraints (§3), Schema-Konformität, JLPT-Level-Konsistenz,
       HTML-Tag-Verbot in text-Content, Rōmaji-Pflicht, Thumbnail-Pflicht
    → Fehler = Abbruch mit detaillierter Liste

[3] python .claude/skills/generate-lesson/pipeline.py images {draft_path}
    → PFLICHT (nicht mehr optional). Ruft DALL-E für thumbnail +
       mind. 3 Schlüsselvokabel-Bilder. Ergänzt image_url/thumbnail_url
       im Draft. Bei fehlendem OPENAI_API_KEY: User fragen, NICHT weitermachen.

[4] python .claude/skills/generate-lesson/pipeline.py insert {draft_path}
    → Transaktionaler INSERT in Postgres (docker-compose DB)
    → Bei Fehler: Rollback, keine Teil-Lektion
    → Gibt lesson_id zurück

[4b] python .claude/skills/generate-lesson/pipeline.py audio {lesson_id}
    → PFLICHT nach Insert. Findet die Dialog-Page automatisch (per Titel:
       'Dialog' / 'Konversation' / 'Gespräch' / 'Conversation'), extrahiert
       die japanischen Sprecher-Zeilen aus dem text-Content, rendert EINE
       MP3 via Google Cloud TTS (SSML mit 700ms-Pausen) und legt einen
       LessonContent(content_type='audio') auf order_index=1 vor dem Text
       an. Idempotent: existierendes Audio wird übersprungen.
    → Benoetigt GOOGLE_API_KEY in .env.

[4c] python .claude/skills/generate-lesson/pipeline.py slideshow {lesson_id}
    → PFLICHT nach audio. Baut pro Dialog-Zeile ein Slide mit:
       - 1 MP3 (Google TTS, Gender-korrekte Voice aus SPEAKER_GENDER)
       - 1 PNG (OpenAI gpt-image-1-mini, Ghibli-Aquarell-Stil, quality='hd',
         STRIKT ohne Text/Kanji/Ziffern — Charakter-Schablone bleibt konstant
         ueber alle Slides).
       Legt LessonContent(content_type='dialog_slideshow') auf order_index=2
       an (audio=1, slideshow=2, text=3). Das Template in lesson_view.html
       rendert einen Alpine.js-Slideshow-Player mit Auto-Advance.
       Idempotent: existierende Zeilen-Assets werden uebersprungen, bestehender
       dialog_slideshow-Eintrag wird aktualisiert.
       Assets unter app/static/uploads/lessons/dialog_slideshow/lesson_{id}/.
       Charaktere werden in scripts/gen_dialog_slideshow.py CHARACTER_SHEETS
       gepflegt — neue Charaktere dort hinzufuegen, sonst generisches
       Portrait-Fallback.
       Kosten: ~50 Rappen pro Lektion (9 HD-Bilder + 9 TTS-Calls).

[5] Verifikation — zwei Pfade, je nach Verfügbarkeit:

    [5a] Bevorzugt: python .claude/skills/generate-lesson/verify.py {lesson_id}
         → Playwright-Headless-Browser: Login als admin (email/password aus .env!),
           /lessons/{id} öffnen, alle Pages durchklicken, Quiz, Deck-Karussell-CSS-Check.
         → Screenshots in verifications/{lesson_id}/.

    [5b] Fallback, wenn MCP-Chrome besetzt ("Browser is already in use"):
         HTTP-basierte Verifikation via requests.Session:
         - POST /login mit email=ADMIN_EMAIL, password=ADMIN_PASSWORD aus .env (CSRF-Token vorher via GET).
         - GET /lessons/{id} → HTTP 200, Titel + Vokabeln + Grammatik + Umlaute im HTML.
         - GET /api/admin/lessons (JSON!) → Lesson muss in Liste sein.
           ACHTUNG: /admin/manage/lessons ist eine AJAX-Shell; die Titel
           werden client-seitig geladen und stehen NICHT im Server-HTML.
         - Dann: User bitten, /lessons/{id} visuell durchzuklicken (Deck-Karussell).

[6] Git-Commit (automatisch):
    git add .claude/skills/generate-lesson/generated-lessons.jsonl
            .claude/skills/generate-lesson/learnings.md
    git commit -m "Lektion generiert: {title} (JLPT N{n}, ID={lesson_id})"
    git push

[7] learnings.md anhängen:
    Was hat funktioniert? Was war überraschend? Was sollte beim nächsten
    Run anders laufen? (Siehe learnings.md für Format.)

Wichtig: Kein Schritt 6 ohne erfolgreichen Schritt 5. Bei Verifikations-Fail: Lektion wird als is_published=False markiert und User bekommt Issue-Report.

7. Bild-Generierung (Ausnahme: externe API)

DALL-E wird nur für:

  • Lesson.thumbnail_url (1 Bild pro Lektion)
  • Vocabulary.image_url (optional, maximal 3 Schlüssel-Vokabeln pro Lektion)

Prompts immer auf Englisch, Stil: "minimalist flat illustration, soft pastels, no text, Japanese aesthetic". Kein Fotorealismus, kein Text im Bild, keine echten Personen.

Bilder werden in GCS hochgeladen via bestehende gcs_utils.upload_file(). Lokal-Mode (wenn GCS_BUCKET_NAME nicht gesetzt): Ablage in app/static/uploads/generated/.

8. Self-Improvement via learnings.md

Nach jedem Run anhängen (siehe learnings.md für Template):

markdown
1## 2026-04-20 12:30 — N5 Familie (Lesson ID 47) 2 3### Erfolge 4- 8 Vokabeln, Thema homogen, Difficulty einheitlich N5 5- Matching-Frage mit 4 Familien-Paaren — Mayuko-testbar 6- Beispielsätze nutzten ausschliesslich N5-Kanji ✓ 7 8### Probleme / Erkenntnisse 9- Distraktor in Q3 war zu offensichtlich ("Auto" bei Familie-Frage) — **Regel für nächstes Mal: Distraktoren MÜSSEN aus derselben semantischen Domäne kommen** 10- Grammar-Struktur-Feld enthielt JP-Text ohne Romaji — Frontend zeigt nur struktur, nicht romaji → **Regel: bei strukturbasiertes Grammar-Eintrag auch `romaji` immer füllen** 11- Playwright fand Quiz-Carousel-CSS-Problem bei 5. Frage → CLAUDE.md-Regel "Deck-Karussell-CSS prüfen" wurde vergessen → **Pre-Flight-Check in Schritt [2] ergänzen** 12 13### Aktuelle Regeln (Zusammenfassung nach diesem Run) 141. Distraktoren aus selber semantischer Domäne 152. Grammar.romaji immer füllen 163. Deck-Karussell CSS-Test als Validate-Step

Regel-Evolution: Wenn derselbe Fehler 2× in unterschiedlichen Runs auftritt → in §3 (harte Constraints) oder §5 (Patterns) dieses Dokuments hochheben, nicht nur in learnings.md stehen lassen.

9. Quellen-Referenzen

  • JLPT N5 Vokabel-Liste (offiziell): sources/jlpt-n5-vocab.md — 800 Kernwörter
  • Minna no Nihongo Rohdaten: scripts/mnn_data/beginner1_lesson01.jsonbeginner2_lesson50.json50 Lektionen, Schema {source, lesson_number, title, jlpt_level, description, vocabulary[], vocabulary_countries[], grammar[{title, structure, jlpt_level, explanation, example_sentences}], conversation{title, lines[{speaker, japanese, romaji, english}]}, additional_conversations[]}. Standard-Workflow: vor Schreiben einer Lektion MNN-JSON lesen, Vokabeln/Grammatik als thematischen Anker nutzen, eigenen Text + eigene Charaktere schreiben (siehe §2a).
  • MNN-Import-Referenz: scripts/import_mnn.py zeigt, wie die 10 Bestandslektionen (IDs 131–141) strukturiert wurden — 5-Seiten-Layout (Vocab → Grammar → Konversation → Übung → Prüfung). Die _format_conversation()-Funktion ab Zeile 170 ist die Referenz für das Dialog-Plaintext-Format.
  • Bestehender DB-Content als Referenz: SELECT in der DB zeigt, was schon da ist. Beispiel:
    sql
    1SELECT word, reading, meaning_de, jlpt_level FROM vocabulary WHERE jlpt_level = 5;
  • Mayuko-Lackmustest: improve-jpl/SKILL.md §1

10. Technische Referenzen (für den Skill, nicht für Claude's Inhalt)

  • DB-Modelle: app/models.py (Kana:127, Kanji:142, Vocabulary:162, Grammar:183, Lesson:218, LessonPage:409, LessonContent:423, QuizQuestion:522, QuizOption:542)
  • Verifikations-Endpoints:
    • /login — POST-Felder: email (nicht username!) + password + csrf_token. Erfolg-Redirect für Admin: /admin.
    • /lessons/{id} — Detailseite (Server-Rendered, gut für Content-Checks).
    • /api/admin/lessonsJSON-Liste aller Lektionen (für Sichtbarkeits-Check).
    • /admin/manage/lessonsAJAX-Shell, Daten kommen client-seitig. HTML enthält KEINE Titel, für Verifikation UNGEEIGNET.
  • Lokal-DB: postgresql://app_user:JapaneseApp2025!@localhost:5432/japanese_learning
  • Admin-Credentials stehen in .env als ADMIN_EMAIL (z.B. admin@example.com) und ADMIN_PASSWORD. Verify-Scripts MÜSSEN diese via dotenv laden. Niemals hardcoden.
  • pg_isready-Check: docker exec postgres_db pg_isready -U app_user -d japanese_learning ist der zuverlässigste Readiness-Check.
  • Windows-Shell-Encoding: Python-Scripts, die japanische Zeichen (Hiragana/Katakana/Kanji) per print() ausgeben, brauchen PYTHONIOENCODING=utf-8 als Env-Variable, sonst UnicodeEncodeError: cp1252. Beispiel: PYTHONIOENCODING=utf-8 python script.py. Alternativ beim Skript-Start: sys.stdout.reconfigure(encoding='utf-8').
  • Bestehende AILessonContentGenerator in app/ai_services.pyNICHT NUTZEN (User-Entscheidung: Claude schreibt selbst)

11. Deploy & Live-Schalten

Nach erfolgreicher Verifikation ist die Lektion in der lokalen DB. Für Production:

bash
1/sync-cloud-db # zuerst Cloud→Lokal prüfen, dann Lokal→Cloud

Nicht im Skill automatisiert — Push auf Production bleibt explizite User-Aktion, damit Mayuko keine halb-fertige Lektion sieht.

相关技能

寻找 generate-lesson 的替代方案 (Alternative) 或可搭配使用的同类 community Skill?探索以下相关开源技能。

查看全部

openclaw-release-maintainer

Logo of openclaw
openclaw

Your own personal AI assistant. Any OS. Any Platform. The lobster way. 🦞

333.8k
0
AI

widget-generator

Logo of f
f

Generate customizable widget plugins for the prompts.chat feed system

149.6k
0
AI

flags

Logo of vercel
vercel

The React Framework

138.4k
0
浏览器

pr-review

Logo of pytorch
pytorch

Tensors and Dynamic neural networks in Python with strong GPU acceleration

98.6k
0
开发者工具