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

About this Skill

Ideal for AI agents that need generate-lesson — anfänger-lektionen für japanese-learning.ch. generate-lesson is an AI agent skill for generate-lesson — anfänger-lektionen für japanese-learning.ch.

Features

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

# Core Topics

ClaudioLutz ClaudioLutz
[0]
[0]
Updated: 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 is an AI agent skill for generate-lesson — anfänger-lektionen für japanese-learning.ch.

Core Value

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 für Mayuko und andere deutschsprachige Anfänger. This AI agent skill supports Claude

Ideal Agent Persona

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

Capabilities Granted for 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)

! Prerequisites & Limits

  • 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.

After The Review

Decide The Next Action Before You Keep Reading Repository Material

Killer-Skills should not stop at opening repository instructions. It should help you decide whether to install this skill, when to cross-check against trusted collections, and when to move into workflow rollout.

Labs 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 & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is generate-lesson?

Ideal for AI agents that need generate-lesson — anfänger-lektionen für japanese-learning.ch. generate-lesson is an AI agent skill for generate-lesson — anfänger-lektionen für japanese-learning.ch.

How do I install generate-lesson?

Run the command: npx killer-skills add ClaudioLutz/Japanese_Learning_Website/generate-lesson. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

What are the use cases for generate-lesson?

Key use cases include: 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).

Which IDEs are compatible with generate-lesson?

This skill is compatible with 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. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for generate-lesson?

Requires repository-specific context from the skill documentation. Works best when the underlying tools and dependencies are already configured.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add ClaudioLutz/Japanese_Learning_Website/generate-lesson. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use generate-lesson immediately in the current project.

! Reference-Only Mode

This page remains useful for installation and reference, but Killer-Skills no longer treats it as a primary indexable landing page. Read the review above before relying on the upstream repository instructions.

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

Install generate-lesson, an AI agent skill for AI agent workflows and automation. Review the use cases, limitations, and setup path before rollout.

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.

Related Skills

Looking for an alternative to generate-lesson or another community skill for your workflow? Explore these related open-source skills.

View All

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
Browser

pr-review

Logo of pytorch
pytorch

Tensors and Dynamic neural networks in Python with strong GPU acceleration

98.6k
0
Developer