Wprowadzenie
Workflow odciąża nauczyciela zawodu z najbardziej żmudnego zadania — adaptacji e-materiału ZPE do konkretnej lekcji. Nauczyciel wkleja URL, podaje czas lekcji, a w ~90 sekund dostaje w przeglądarce gotowy pakiet: scenariusz, kartę pracy, quiz z kluczem odpowiedzi i ćwiczenia praktyczne.
Pod spodem: 8 nodów, n8n AI Agent z GPT-4.1-mini, automatyczne pobieranie podstron pomocniczych ze ZPE (Słownik pojęć, Przewodnik dla nauczyciela).
System prompt do AI Agent (Metodyk)
Jesteś doświadczonym metodykiem kształcenia zawodowego z 20-letnim stażem oraz autorem materiałów dla CKE. Specjalizujesz się w łączeniu teorii z praktyką warsztatową.
Twoim zadaniem jest przygotowanie KOMPLETNEGO PAKIETU MATERIAŁÓW na lekcję zawodową na podstawie e-materiału ze Zintegrowanej Platformy Edukacyjnej (ZPE).
Pakiet MUSI zawierać 4 sekcje w formacie Markdown:
# 1. SCENARIUSZ LEKCJI
Powinien zawierać:
- Temat lekcji (precyzyjny, zoperacjonalizowany)
- Kwalifikacja zawodowa i jednostka efektów kształcenia (jeśli da się wywnioskować z treści)
- Cele lekcji w języku ucznia (3-5 celów, sformułowane jako "Po lekcji uczeń potrafi...")
- Metody i formy pracy
- Środki dydaktyczne (z odniesieniem do konkretnych elementów e-materiału ZPE)
- Tabela przebiegu lekcji z dokładnym podziałem na fazy i czas:
| Faza | Czas | Działania nauczyciela | Działania ucznia | Materiały |
|------|------|----------------------|------------------|-----------|
# 2. KARTA PRACY UCZNIA
- Nagłówek: Imię i nazwisko / data / klasa (puste pola do wypełnienia)
- Polecenie wprowadzające
- 4-6 zadań różnego typu: definicje do uzupełnienia, schematy, mini-projekt, analiza przypadku
- Miejsce na odpowiedzi (oznaczone liniami, tabelami)
- Zadanie problemowe na koniec (otwarte)
# 3. QUIZ KONTROLNY
- 6 pytań zamkniętych (jednokrotny wybór, opcje A-D)
- 2 pytania otwarte krótkiej odpowiedzi
- KLUCZ ODPOWIEDZI na końcu sekcji (oddzielony nagłówkiem "### Klucz odpowiedzi")
# 4. ĆWICZENIA PRAKTYCZNE / WARSZTATOWE
3-5 propozycji ćwiczeń łączących treść lekcji z realiami warsztatu lub miejsca pracy. Każde ćwiczenie zawiera:
- Tytuł
- Cel
- Potrzebne materiały / wyposażenie
- Czas wykonania
- Krótka instrukcja (3-5 punktów)
- Kryteria oceny
=== ZASADY OGÓLNE ===
- Pisz po polsku (z poprawnymi znakami diakrytycznymi)
- Język profesjonalny ale przystępny
- Bezpośrednio odwołuj się do treści e-materiału ZPE
- Uwzględnij specyfikę kwalifikacji zawodowej
- Dopasuj objętość lekcji do podanego czasu
- Bez waty - każde zdanie musi mieć wartość
- Pamiętaj: ten materiał trafi do prawdziwego nauczyciela, który użyje go jutro w klasie
ZWRÓĆ TYLKO MARKDOWN ZACZYNAJĄCY SIĘ OD "# 1. SCENARIUSZ LEKCJI" - bez wstępu, bez kodu, bez metakomentarzy.
Linki do przykładowych e-materiałów ZPE (różne typy treści)
Tekst:
https://zpe.gov.pl/a/projektowanie-sieci-i-przylaczy-wodociagowych/DZ2GyLsQa
Wideo:
https://zpe.gov.pl/a/poslugiwanie-sie-narzedziami-i-urzadzeniami-do-budowy-lokalnej-sieci-komputerowej/D1EURn772
Interaktywna prezentacja:
https://zpe.gov.pl/a/wykonywanie-gwintowania-i-obrobki-koncow-rur/DUfdYLIUA
Konfiguracja AI Agent
- Model:
gpt-4.1-mini— wystarczająca jakość dla generacji edukacyjnej przy znacznie niższym koszcie niż GPT-4o - Temperature:
0.4— balans między spójnością a kreatywnością - Max tokens:
8000— zmieści pełny pakiet 4 sekcji - Timeout:
120000 ms— generacja zajmuje 60-90s - Retry: 2 próby z 3s przerwą
Sub-node OpenAI Chat Model można w każdej chwili wymienić na inny (Claude, Mistral, Ollama lokalnie) bez zmiany reszty workflow — AI Agent rozmawia z każdym przez ten sam interfejs ai_languageModel.
Pełny kod
Skopiuj poniszy kod i wklej w swojej
{
"nodes": [
{
"parameters": {
"formTitle": "Generator lekcji ZPE",
"formDescription": "Wklej URL e-materiału ze ZPE, opisz swoją klasę i otrzymaj gotową lekcję wyświetloną w przeglądarce w 1-2 minuty.",
"formFields": {
"values": [
{
"fieldLabel": "URL e-materialu ZPE",
"placeholder": "https://zpe.gov.pl/a/... lub https://zpe.gov.pl/b/...",
"requiredField": true
},
{
"fieldLabel": "Czas lekcji",
"fieldType": "dropdown",
"fieldOptions": {
"values": [
{
"option": "45 minut"
},
{
"option": "90 minut"
}
]
},
"requiredField": true
}
]
},
"responseMode": "lastNode",
"options": {}
},
"id": "1b34af74-0c7d-411d-a5a9-94beaece613f",
"name": "Formularz nauczyciela",
"type": "n8n-nodes-base.formTrigger",
"typeVersion": 2.5,
"position": [
-144,
-112
],
"webhookId": "e1834c68-4a41-447e-a927-03f61b7c38ea"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "function getField(item, ...possibleKeys) {\n for (const k of possibleKeys) {\n if (item[k] !== undefined && item[k] !== null && item[k] !== '') return item[k];\n }\n return '';\n}\n\nconst item = $input.item.json;\n\nconst url = String(getField(item, 'URL e-materialu ZPE', 'URL e-materiału ZPE', 'url_zpe')).trim();\nconst duration = String(getField(item, 'Czas lekcji', 'lesson_duration', 'czas_lekcji', '90 minut'));\nconst profile = String(getField(item, 'Profil klasy', 'class_profile', 'profil_klasy')).trim();\nconst special = String(getField(item, 'Specjalne wymagania', 'special_requirements', 'wymagania') || 'brak').trim();\n\nconst zpePattern = /^https:\\/\\/zpe\\.gov\\.pl\\/(a|b)\\/[a-zA-Z0-9-]+\\/[A-Za-z0-9]+$/;\nif (!zpePattern.test(url)) {\n throw new Error('Nieprawidlowy URL ZPE: ' + url + '. Oczekiwany format: https://zpe.gov.pl/a/... lub https://zpe.gov.pl/b/...');\n}\n\nconst urlType = url.includes('/a/') ? 'page' : 'index';\nconst urlParts = url.split('/');\nconst materialId = urlParts[urlParts.length - 1];\nconst durationMinutes = parseInt(duration) || 90;\n\nreturn {\n url_validated: url,\n url_type: urlType,\n material_id: materialId,\n duration_minutes: durationMinutes,\n class_profile: profile,\n special_requirements: special,\n generation_id: Date.now() + '-' + Math.random().toString(36).substring(2, 8),\n generation_timestamp: new Date().toISOString()\n};\n"
},
"id": "57e01e42-4a63-4c18-bb84-d1b10e3ee3f7",
"name": "Walidacja i przygotowanie",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
80,
-112
],
"notes": "Walidacja URL ZPE, ekstrakcja parametrów."
},
{
"parameters": {
"url": "={{ $json.url_validated }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "User-Agent",
"value": "Mozilla/5.0 (compatible; ZPE-Lesson-Generator/1.0)"
},
{
"name": "Accept",
"value": "text/html"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "text"
}
},
"timeout": 30000
}
},
"id": "70dba8fa-a386-46a5-9702-8b45fe223eea",
"name": "Pobranie strony ZPE",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"retryOnFail": true,
"maxTries": 2,
"waitBetweenTries": 2000,
"position": [
304,
-112
],
"notes": "Pobranie HTML głównej strony e-materiału ze ZPE."
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const inputHtml = $input.item.json.data || $input.item.json.body || '';\nconst validated = $('Walidacja i przygotowanie').item.json;\n\nfunction cleanHtml(html) {\n if (!html) return '';\n let c = html\n .replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<nav[^>]*>[\\s\\S]*?<\\/nav>/gi, '')\n .replace(/<header[^>]*>[\\s\\S]*?<\\/header>/gi, '')\n .replace(/<footer[^>]*>[\\s\\S]*?<\\/footer>/gi, '');\n \n const mainMatch = c.match(/<main[^>]*>([\\s\\S]*?)<\\/main>/i);\n if (mainMatch) c = mainMatch[1];\n \n c = c\n .replace(/<h1[^>]*>/gi, '\\n\\n# ').replace(/<\\/h1>/gi, '\\n')\n .replace(/<h2[^>]*>/gi, '\\n\\n## ').replace(/<\\/h2>/gi, '\\n')\n .replace(/<h3[^>]*>/gi, '\\n\\n### ').replace(/<\\/h3>/gi, '\\n')\n .replace(/<h[4-6][^>]*>/gi, '\\n\\n#### ').replace(/<\\/h[4-6]>/gi, '\\n')\n .replace(/<\\/(p|div|li|tr)>/gi, '\\n')\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<\\/?(strong|b)[^>]*>/gi, '**')\n .replace(/<\\/?(em|i)[^>]*>/gi, '*')\n .replace(/<[^>]+>/g, ' ')\n .replace(/ /g, ' ')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/&#(\\d+);/g, function(_, n) { return String.fromCharCode(parseInt(n)); })\n .replace(/&[a-z]+;/gi, ' ')\n .replace(/[ \\t]+/g, ' ')\n .replace(/\\n[ \\t]+/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n \n const lines = c.split('\\n');\n const seen = new Set();\n const out = [];\n for (const line of lines) {\n const norm = line.trim().toLowerCase();\n if (norm.length < 30 || !seen.has(norm)) {\n out.push(line);\n if (norm.length >= 30) seen.add(norm);\n }\n }\n return out.join('\\n').trim();\n}\n\nfunction getTitle(html) {\n const m = html.match(/<h1[^>]*>([\\s\\S]*?)<\\/h1>/i);\n return m ? m[1].replace(/<[^>]+>/g, '').trim() : 'E-material ZPE';\n}\n\nfunction findHelperLinks(html) {\n const helpers = [];\n const linkRegex = /<a[^>]+href=\"([^\"]+)\"[^>]*>([\\s\\S]*?)<\\/a>/gi;\n const keywords = ['słownik', 'slownik', 'przewodnik dla nauczyciela', 'przewodnik dla uczacego', 'przewodnik dla uczącego'];\n let m;\n while ((m = linkRegex.exec(html)) !== null) {\n const href = m[1];\n const text = m[2].replace(/<[^>]+>/g, '').toLowerCase().trim();\n if (href.includes('/a/') && keywords.some(function(k) { return text.includes(k); })) {\n const full = href.startsWith('http') ? href : 'https://zpe.gov.pl' + href;\n if (!helpers.includes(full)) helpers.push(full);\n }\n }\n return helpers.slice(0, 3);\n}\n\nconst pageTitle = getTitle(inputHtml);\nconst mainContent = cleanHtml(inputHtml);\nconst helperUrls = findHelperLinks(inputHtml);\n\nlet helperContent = '';\nlet helpersFetched = 0;\nfor (const hUrl of helperUrls) {\n try {\n const resp = await $helpers.httpRequest({\n method: 'GET',\n url: hUrl,\n timeout: 15000,\n returnFullResponse: false,\n headers: { 'User-Agent': 'Mozilla/5.0 ZPE-Lesson-Generator' }\n });\n const cleaned = cleanHtml(typeof resp === 'string' ? resp : (resp.body || ''));\n if (cleaned && cleaned.length > 100) {\n helperContent += '\\n\\n--- TRESC POMOCNICZA: ' + hUrl + ' ---\\n\\n' + cleaned;\n helpersFetched++;\n }\n } catch (e) {}\n}\n\nconst combinedContent = mainContent + (helperContent ? '\\n\\n========== TRESCI POMOCNICZE ==========' + helperContent : '');\n\n// Budowanie userPrompt dla AI Agent inline tutaj\nconst userPrompt = '=== TRESC E-MATERIALU ZPE ===\\n\\n' +\n 'TYTUL: ' + pageTitle + '\\n' +\n 'URL: ' + validated.url_validated + '\\n\\n' +\n 'PELNA TRESC MERYTORYCZNA (wraz z opisami plansz, slownikiem pojec i przewodnikiem dla nauczyciela jesli zostaly znalezione):\\n\\n' +\n combinedContent + '\\n\\n' +\n '=== PARAMETRY LEKCJI ===\\n\\n' +\n 'CZAS LEKCJI: ' + validated.duration_minutes + ' minut\\n\\n' +\n 'PROFIL KLASY:\\n' + validated.class_profile + '\\n\\n' +\n 'SPECJALNE WYMAGANIA NAUCZYCIELA:\\n' + validated.special_requirements + '\\n\\n' +\n '=== ZADANIE ===\\n\\n' +\n 'Wygeneruj kompletny pakiet 5 sekcji wedlug struktury z instrukcji systemowej. Zaczynaj od \"# 1. SCENARIUSZ LEKCJI\".';\n\nreturn {\n ...validated,\n page_title: pageTitle,\n main_content: mainContent,\n combined_content: combinedContent,\n helpers_fetched: helpersFetched,\n content_length: combinedContent.length,\n userPrompt: userPrompt\n};\n"
},
"id": "6e3a6d40-9eff-4d19-a3ec-5419f6c9d4a5",
"name": "Przetwarzanie tresci",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
528,
-112
],
"notes": "Czyszczenie HTML do tekstu + automatyczne pobranie podstron pomocniczych (Słownik, Przewodnik). Wyjście: userPrompt gotowy dla AI Agent."
},
{
"parameters": {
"promptType": "define",
"text": "={{ $json.userPrompt }}",
"options": {
"systemMessage": "Jesteś doświadczonym metodykiem kształcenia zawodowego z 20-letnim stażem oraz autorem materiałów dla CKE. Specjalizujesz się w łączeniu teorii z praktyką warsztatową.\n\nTwoim zadaniem jest przygotowanie KOMPLETNEGO PAKIETU MATERIAŁÓW na lekcję zawodową na podstawie e-materiału ze Zintegrowanej Platformy Edukacyjnej (ZPE).\n\nPakiet MUSI zawierać 5 sekcji w formacie Markdown:\n\n# 1. SCENARIUSZ LEKCJI\n\nPowinien zawierać:\n- Temat lekcji (precyzyjny, zoperacjonalizowany)\n- Kwalifikacja zawodowa i jednostka efektów kształcenia (jeśli da się wywnioskować z treści)\n- Cele lekcji w języku ucznia (3-5 celów, sformułowane jako \"Po lekcji uczeń potrafi...\")\n- Metody i formy pracy\n- Środki dydaktyczne (z odniesieniem do konkretnych elementów e-materiału ZPE)\n- Tabela przebiegu lekcji z dokładnym podziałem na fazy i czas:\n\n| Faza | Czas | Działania nauczyciela | Działania ucznia | Materiały |\n|------|------|----------------------|------------------|-----------|\n\n# 2. KARTA PRACY UCZNIA\n\n- Nagłówek: Imię i nazwisko / data / klasa (puste pola do wypełnienia)\n- Polecenie wprowadzające\n- 4-6 zadań różnego typu: definicje do uzupełnienia, schematy, mini-projekt, analiza przypadku\n- Miejsce na odpowiedzi (oznaczone liniami, tabelami)\n- Zadanie problemowe na koniec (otwarte)\n\n# 3. QUIZ KONTROLNY\n\n- 6 pytań zamkniętych (jednokrotny wybór, opcje A-D)\n- 2 pytania otwarte krótkiej odpowiedzi\n- KLUCZ ODPOWIEDZI na końcu sekcji (oddzielony nagłówkiem \"### Klucz odpowiedzi\")\n\n\n# 4. ĆWICZENIA PRAKTYCZNE / WARSZTATOWE\n\n3-5 propozycji ćwiczeń łączących treść lekcji z realiami warsztatu lub miejsca pracy. Każde ćwiczenie zawiera:\n- Tytuł\n- Cel\n- Potrzebne materiały / wyposażenie\n- Czas wykonania\n- Krótka instrukcja (3-5 punktów)\n- Kryteria oceny\n\n=== ZASADY OGÓLNE ===\n\n- Pisz po polsku (z poprawnymi znakami diakrytycznymi)\n- Język profesjonalny ale przystępny\n- Bezpośrednio odwołuj się do treści e-materiału ZPE\n- Uwzględnij specyfikę kwalifikacji zawodowej\n- Dopasuj objętość lekcji do podanego czasu\n- Bez waty - każde zdanie musi mieć wartość\n- Pamiętaj: ten materiał trafi do prawdziwego nauczyciela, który użyje go jutro w klasie\n\nZWRÓĆ TYLKO MARKDOWN ZACZYNAJĄCY SIĘ OD \"# 1. SCENARIUSZ LEKCJI\" - bez wstępu, bez kodu, bez metakomentarzy."
}
},
"id": "e53e29a8-836c-41bb-8813-dd4a47b00beb",
"name": "AI Agent - Metodyk",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 3.1,
"position": [
768,
-112
],
"retryOnFail": true,
"maxTries": 2,
"waitBetweenTries": 3000,
"notes": "AI Agent z rolą metodyka kształcenia zawodowego. Generuje 5 sekcji: scenariusz, karta pracy, quiz, wskazówki SPE, ćwiczenia. Łatwo wymienić model na inny przez podpięcie innego sub-node Chat Model."
},
{
"parameters": {
"model": {
"__rl": true,
"value": "gpt-4.1-mini",
"mode": "list",
"cachedResultName": "gpt-4.1-mini"
},
"builtInTools": {},
"options": {
"maxTokens": 8000,
"temperature": 0.4,
"timeout": 120000
}
},
"id": "2c39e17e-4c65-434f-b72f-7cb02d77231a",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.3,
"position": [
768,
128
],
"credentials": {
"openAiApi": {
"id": "7lmHcPMAjhsZFa1f",
"name": "OpenAi account"
}
},
"notes": "GPT-4o jako mózg AI Agent. Można wymienić na Claude, Mistral, Ollama (lokalny) - wystarczy podpiąć inny Chat Model sub-node."
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const ctx = $input.item.json;\nconst markdown = ctx.output || ctx.text || '';\n\nif (!markdown) {\n throw new Error('Brak odpowiedzi z AI Agent. Sprawdz poprzedni node.');\n}\n\nconst validated = $('Walidacja i przygotowanie').item.json;\nconst processed = $('Przetwarzanie tresci').item.json;\n\nfunction mdToHtml(md) {\n let h = md;\n \n // Tabele markdown (zanim sparujemy paragrafy)\n h = h.replace(/((?:\\|[^\\n]+\\|\\n?)+)/g, function(match) {\n const rows = match.trim().split('\\n').filter(r => r.trim().startsWith('|'));\n if (rows.length < 2) return match;\n \n let table = '<table>';\n let isFirstRow = true;\n rows.forEach(function(row, idx) {\n if (/^\\|[\\s\\-|:]+\\|$/.test(row.trim())) return;\n const cells = row.split('|').slice(1, -1).map(c => c.trim());\n const tag = isFirstRow ? 'th' : 'td';\n table += '<tr>' + cells.map(c => '<' + tag + '>' + c + '</' + tag + '>').join('') + '</tr>';\n isFirstRow = false;\n });\n table += '</table>';\n return '\\n\\n' + table + '\\n\\n';\n });\n \n // Naglowki\n h = h.replace(/^#### (.+)$/gm, '<h4>$1</h4>');\n h = h.replace(/^### (.+)$/gm, '<h3>$1</h3>');\n h = h.replace(/^## (.+)$/gm, '<h2>$1</h2>');\n h = h.replace(/^# (.+)$/gm, '<h1>$1</h1>');\n \n // Bold + italic\n h = h.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n h = h.replace(/(?<!\\*)\\*(?!\\*)([^*\\n]+?)(?<!\\*)\\*(?!\\*)/g, '<em>$1</em>');\n \n // Listy nienumerowane\n h = h.replace(/^[\\-\\*] (.+)$/gm, '<li-u>$1</li-u>');\n h = h.replace(/(<li-u>[\\s\\S]*?<\\/li-u>(?:\\n|$))+/g, function(m) {\n return '<ul>' + m.replace(/li-u/g, 'li') + '</ul>';\n });\n \n // Listy numerowane\n h = h.replace(/^\\d+\\. (.+)$/gm, '<li-o>$1</li-o>');\n h = h.replace(/(<li-o>[\\s\\S]*?<\\/li-o>(?:\\n|$))+/g, function(m) {\n return '<ol>' + m.replace(/li-o/g, 'li') + '</ol>';\n });\n \n // Paragrafy\n h = h.split('\\n\\n').map(function(block) {\n const t = block.trim();\n if (!t) return '';\n if (t.startsWith('<')) return t;\n return '<p>' + t.replace(/\\n/g, '<br>') + '</p>';\n }).join('\\n');\n \n return h;\n}\n\nconst bodyHtml = mdToHtml(markdown);\n\nconst fullPage = '<style>' +\n '.zpe-lesson { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif; max-width: 900px; margin: 0 auto; padding: 30px; color: #1a1a1a; line-height: 1.6; }' +\n '.zpe-lesson .meta { background: #f0f4f8; padding: 16px 20px; border-radius: 8px; margin-bottom: 30px; font-size: 14px; color: #4a5568; border-left: 4px solid #1a5490; }' +\n '.zpe-lesson .meta strong { color: #1a5490; }' +\n '.zpe-lesson h1 { color: #1a5490; border-bottom: 3px solid #1a5490; padding-bottom: 8px; margin-top: 40px; font-size: 28px; }' +\n '.zpe-lesson h2 { color: #2c6fb0; margin-top: 32px; font-size: 22px; }' +\n '.zpe-lesson h3 { color: #3a7ec0; margin-top: 24px; font-size: 18px; }' +\n '.zpe-lesson h4 { color: #4a8ed0; margin-top: 20px; font-size: 16px; }' +\n '.zpe-lesson table { width: 100%; border-collapse: collapse; margin: 16px 0; background: white; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }' +\n '.zpe-lesson th { background: #e8f0fe; color: #1a5490; padding: 12px; text-align: left; border: 1px solid #cbd5e0; font-weight: 600; }' +\n '.zpe-lesson td { padding: 12px; border: 1px solid #e2e8f0; vertical-align: top; }' +\n '.zpe-lesson tr:nth-child(even) td { background: #f7fafc; }' +\n '.zpe-lesson ul, .zpe-lesson ol { margin: 12px 0; padding-left: 24px; }' +\n '.zpe-lesson li { margin: 6px 0; }' +\n '.zpe-lesson p { margin: 12px 0; }' +\n '.zpe-lesson strong { color: #1a5490; }' +\n '.zpe-lesson .footer { margin-top: 50px; padding-top: 20px; border-top: 1px solid #e2e8f0; font-size: 13px; color: #718096; text-align: center; }' +\n '.zpe-lesson .actions { margin: 20px 0; text-align: center; }' +\n '.zpe-lesson .btn { display: inline-block; background: #1a5490; color: white; padding: 12px 24px; border-radius: 6px; text-decoration: none; font-weight: 500; margin: 0 8px; }' +\n '.zpe-lesson .btn:hover { background: #2c6fb0; }' +\n '@media print { .zpe-lesson .actions { display: none; } }' +\n '</style>' +\n '<div class=\"zpe-lesson\">' +\n '<div class=\"meta\">' +\n '<strong>📚 ' + processed.page_title + '</strong><br>' +\n 'Czas lekcji: <strong>' + validated.duration_minutes + ' minut</strong> | ' +\n 'Profil klasy: ' + validated.class_profile + '<br>' +\n 'Źródło: <a href=\"' + validated.url_validated + '\" target=\"_blank\">' + validated.url_validated + '</a> | ' +\n 'Wygenerowano: ' + new Date(validated.generation_timestamp).toLocaleString('pl-PL') +\n '</div>' +\n '<div class=\"actions\">' +\n '<a href=\"javascript:window.print()\" class=\"btn\">🖨️ Drukuj / zapisz jako PDF</a>' +\n '</div>' +\n bodyHtml +\n '<div class=\"footer\">' +\n '⚠️ Materiał wygenerowany automatycznie z wykorzystaniem AI na podstawie e-materiału z platformy zpe.gov.pl.<br>' +\n 'Treść wymaga weryfikacji nauczyciela przed użyciem w klasie.' +\n '</div>' +\n '</div>';\n\nreturn {\n ...validated,\n page_title: processed.page_title,\n markdown_content: markdown,\n formatted_html: fullPage\n};\n"
},
"id": "35653b69-e3c3-4ee8-ac6f-047dac97413d",
"name": "Formatowanie do HTML",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1120,
-112
],
"notes": "Konwersja markdown z AI Agent na stylowy HTML z tabelami, nagłówkami, listami. Gotowy do wyświetlenia."
},
{
"parameters": {
"operation": "completion",
"respondWith": "showText",
"responseText": "={{ $json.formatted_html }}"
},
"id": "6f02b0f3-5293-4b99-a3c0-5cfad6d9a276",
"name": "Wyswietlenie lekcji",
"type": "n8n-nodes-base.form",
"typeVersion": 2.5,
"position": [
1344,
-112
],
"webhookId": "zpe-lesson-display",
"notes": "Wyświetla wygenerowaną lekcję jako stronę HTML w przeglądarce. Zawiera przycisk drukowania / zapisu jako PDF."
}
],
"connections": {
"Formularz nauczyciela": {
"main": [
[
{
"node": "Walidacja i przygotowanie",
"type": "main",
"index": 0
}
]
]
},
"Walidacja i przygotowanie": {
"main": [
[
{
"node": "Pobranie strony ZPE",
"type": "main",
"index": 0
}
]
]
},
"Pobranie strony ZPE": {
"main": [
[
{
"node": "Przetwarzanie tresci",
"type": "main",
"index": 0
}
]
]
},
"Przetwarzanie tresci": {
"main": [
[
{
"node": "AI Agent - Metodyk",
"type": "main",
"index": 0
}
]
]
},
"AI Agent - Metodyk": {
"main": [
[
{
"node": "Formatowanie do HTML",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent - Metodyk",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Formatowanie do HTML": {
"main": [
[
{
"node": "Wyswietlenie lekcji",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "2295c029f4cb86c8f849f9c87dade323734dc279619eb9e2704f8473c381e4d1"
}
}












Komentarze