{
  "nodes": [
    {
      "id": "7d80a2b6-225b-41c3-9723-b1c533176dcd",
      "name": "Get Website HTML",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1680,
        180
      ],
      "parameters": {
        "url": "={{ $json['URL to analyze'] }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "598f30d8-ca38-469e-978b-c521b2163e6c",
      "name": "Get WAVE Report",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1420,
        180
      ],
      "parameters": {
        "url": "=https://wave.webaim.org/api/request?key={{ $('CHANGE THESE: dependencies').item.json.wave_api_key }}&reporttype=4&url={{ $('CHANGE THESE: dependencies').item.json['URL to analyze'] }}\n",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "0e6c3a12-ad82-4b84-85b2-b0d5a3ebe055",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -600,
        400
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"Accessibility Statement\": {\n\t\t\t\"type\": \"string\",\n            \"description\": \"output the HTML code for the accessibility statement here. The statement should use the specified language\"\n\t\t}\n\t}\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "3ceda0aa-662d-49c8-a009-520889c54332",
      "name": "Accessibility Statement Generator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -860,
        180
      ],
      "parameters": {
        "text": "=You are an expert legal-tech assistant. Your specialty is European digital accessibility law, specifically the **European Accessibility Act (EAA)** and the **Web Content Accessibility Guidelines (WCAG)**.\n\nYour task is to generate a formal **\"Accessibility Statement\"**.\n\nThe final statement must be written **in English** and formatted as a **clean, professional HTML document**. The content must be factually based on the provided data and compliant with the EAA's requirements.\n\n\nPlease generate a compliant Accessibility Statement by following these instructions precisely.\n\n**PART 1: INPUT DATA**\n\nYou will use the following information to construct the statement:\n\n* **Company Name:** `{{ $('CHANGE THESE: dependencies').item.json['Company Name'] }}`\n* **Company Country:** `{{ $('CHANGE THESE: dependencies').item.json['Country of the Company (used to apply local law)'] }}`\n* **Website URL:** `{{ $('CHANGE THESE: dependencies').item.json['URL to analyze'] }}`\n* **Accessibility Scan Results:** A JSON list of all accessibility problems detected on the website.\n    ```json\n    {{ $('Map WAVE Report Items to Website selectors.').item.json.analysisItems.toJsonString() }}\n    ```\n\n**PART 2: YOUR TASK & INSTRUCTIONS**\n\nCreate the HTML code for the \"Accessibility Statement\" by completing the following steps:\n\n**Step 1: Determine Compliance Status**\nAnalyze the `Accessibility Scan Results`. Since the data contains multiple items with an `issue_type` of \"error\", you **must** classify the website's status as **\"partially compliant\"**.\n\n**Step 2: Summarize Non-Accessible Content**\nFrom the `Accessibility Scan Results`, identify the main **categories** of problems. In the final statement, list 2-4 of these general categories. Do **not** list every single error. Good examples are:\n* \"Missing alternative text for images and graphics\"\n* \"Insufficient color contrasts between text and background\"\n* \"Form elements without associated labels\"\n* \"Menus or interactive elements not fully operable by keyboard\"\n\n**Step 3: Construct the Final HTML Document**\nGenerate a complete HTML document in English. The document **must** include the following sections, using the provided English titles:\n\n1.  **`Accessibility Statement`**: The main title of the page.\n2.  **`Commitment to Accessibility`**: A brief, professional introduction stating the company's commitment to digital accessibility in the name of `{{ $('CHANGE THESE: dependencies').item.json['Company Name'] }}`.\n3.  **`Conformance Status`**: State that the website is \"partially conformant with the Web Content Accessibility Guidelines (WCAG) 2.1 level AA\" due to the non-compliances listed below.\n4.  **`Non-Accessible Content`**: List the general problem categories you identified in Step 2.\n5.  **`Preparation of this Accessibility Statement`**: State that the assessment method was a `self-assessment` conducted with automated tools and that the statement was created on `{{ $now.toFormat('MMMM d, yyyy') }}`.\n6.  **`Feedback and Contact Information`**: Provide a section for users to report barriers. **Crucially, use a clear placeholder text** like `[Please insert your contact email address or a link to your contact form here]` so the end-user knows this part must be manually replaced.\n7.  **`Enforcement Procedure`**: This section is country-specific. **You must insert a clear placeholder** informing the user that they need to add the details of their country's official national enforcement body. Use placeholder text like: `[The website owner must insert the name, contact details, and web link for the official national enforcement/arbitration body for their country here.]`\n\n**Step 4: Final Output Requirement**\nYour final response must ONLY be the complete, raw HTML code for the statement in the required JSON format. The Accesibility Statement MUST be in {{ $('CHANGE THESE: dependencies').item.json['Desired Output Language'] }} language!!",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2
    },
    {
      "id": "70f20556-12de-4b43-8950-c3409be30e27",
      "name": "gemini 2.5 pro",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -920,
        400
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.5-pro-preview-06-05"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f16e7f9a-357f-4493-8b2f-677e5c3b3a97",
      "name": "Parse output as html",
      "type": "n8n-nodes-base.html",
      "position": [
        -480,
        180
      ],
      "parameters": {
        "html": "{{ $json.output['Accessibility Statement'] }}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "c71c1911-4de6-42f9-a804-477237962e47",
      "name": "Create accesibility statement html file",
      "type": "n8n-nodes-base.moveBinaryData",
      "position": [
        -180,
        180
      ],
      "parameters": {
        "mode": "jsonToBinary",
        "options": {
          "fileName": "=accessibility_statement_{{ $('CHANGE THESE: dependencies').item.json['Company Name'].toSnakeCase() }}.html",
          "mimeType": "text/html",
          "useRawData": true
        },
        "sourceKey": "html",
        "convertAllData": false
      },
      "typeVersion": 1
    },
    {
      "id": "a7b3c3c8-f6b5-42ce-bf7e-b321cb68906c",
      "name": "Map WAVE Report Items to Website selectors.",
      "type": "n8n-nodes-base.code",
      "position": [
        -1200,
        180
      ],
      "parameters": {
        "jsCode": "// --- Corrected Script ---\n\nconsole.log(\"--- 1. SCRIPT INITIALIZING ---\");\nconst cheerio = require('cheerio');\nconsole.log(\"Cheerio library loaded.\");\n\nconst fullHtml = $('Get Website HTML').first().json.data;\nconst waveCategories = $('Get WAVE Report').first().json.categories;\nconsole.log(`Input data loaded. HTML Length: ${fullHtml.length}`);\n\n// --- 3. INITIALIZING CHEERIO ---\nconst $$ = cheerio.load(fullHtml);\nconsole.log(`Cheerio loaded HTML successfully. Document title: \"${$$('title').text()}\"`);\n\nconst analysisItems = [];\n\n// --- 4. PROCESSING LOOP ---\nif (waveCategories && typeof waveCategories === 'object') {\n  for (const categoryName in waveCategories) {\n    const category = waveCategories[categoryName];\n    if (category && category.items && typeof category.items === 'object') {\n      for (const itemId in category.items) {\n        const item = category.items[itemId];\n        if (item.selectors && Array.isArray(item.selectors)) {\n          \n          // Loop through the array of selector strings\n          for (const selectorString of item.selectors) {\n            \n            // --- THIS IS THE CORRECTED LINE ---\n            // The selector is the string itself from the array.\n            const selector = selectorString;\n\n            // Ensure the selector is a valid string before using it\n            if (typeof selector === 'string' && selector) {\n              console.log(`  -> Searching for selector: \"${selector.substring(0, 80)}...\"`);\n              const elementNode = $$(selector).first();\n              \n              if (elementNode.length > 0) {\n                console.log(`    -> SUCCESS: Found element!`);\n                let contextHtml = elementNode.parent().html();\n                \n                if (contextHtml && contextHtml.length > 2000) {\n                  contextHtml = $$.html(elementNode);\n                }\n\n                analysisItems.push({\n                  issue_type: categoryName,\n                  description: item.description,\n                  selector: selector,\n                  context_html: contextHtml ? contextHtml.trim() : \"\"\n                });\n              } else {\n                console.log(`    -> WARNING: Could not find element for selector.`);\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\n// --- 5. FINAL OUTPUT ---\nconsole.log(`\\n--- PROCESSING COMPLETE ---`);\nconsole.log(`Total items collected for AI: ${analysisItems.length}`);\n\nreturn {\n  json: {\n    analysisItems\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "e8750f9c-778f-41fd-aead-270d33e255e4",
      "name": "CHANGE THESE: dependencies",
      "type": "n8n-nodes-base.set",
      "position": [
        -1880,
        -100
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "678e5308-808a-46c5-89b4-c68b272e03c6",
              "name": "wave_api_key",
              "type": "string",
              "value": ""
            },
            {
              "id": "470042c1-8609-41ab-ab1e-bf817035d426",
              "name": "URL to analyze",
              "type": "string",
              "value": "="
            },
            {
              "id": "d3c198ec-2bba-45d1-8687-b918fc2f2499",
              "name": "Email for summary",
              "type": "string",
              "value": "user@example.com"
            },
            {
              "id": "f15f810e-ce67-463e-8b99-61de6f1bcb6c",
              "name": "Desired Output Language",
              "type": "string",
              "value": "english"
            },
            {
              "id": "219c0199-a819-4e45-bd9e-aa7197060da1",
              "name": "Company Name",
              "type": "string",
              "value": "Tiro"
            },
            {
              "id": "9423eed7-e169-4312-8293-149d305d156e",
              "name": "Country of the Company (used to apply local law)",
              "type": "string",
              "value": "Germany"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "510ed358-75a8-4842-a8aa-0b2fa95144b6",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -2080,
        180
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "1ebee155-5b9a-4da3-8e63-054bf14b945a",
      "name": "Send accessibility statement by email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        80,
        180
      ],
      "parameters": {
        "sendTo": "={{ $('CHANGE THESE: dependencies').item.json['Email for summary'] }}",
        "message": "=This Email contains your Accessibility Statement. Check the attached files.",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          }
        },
        "subject": "=Accessibility Statement for {{ $('CHANGE THESE: dependencies').item.json['Company Name'] }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "cdda9066-42d8-4d9f-97a8-9a5184bd58e6",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3020,
        -280
      ],
      "parameters": {
        "color": 5,
        "width": 880,
        "height": 920,
        "content": "# \ud83d\ude80 Automatically Generate Your EU Accessibility Statement\n\n**What This Template Does:**\nThis workflow scans any website, analyzes its accessibility issues, and uses an AI agent to automatically generate a formal Accessibility Statement (Erkl\u00e4rung zur Barrierefreiheit). This document is a legal requirement for most EU businesses under the **European Accessibility Act (EAA)**, with a compliance deadline of **June 28, 2025**.\n\n**How It Works:**\nIt uses the **WAVE API** to find accessibility issues and **Google Gemini** to write the statement based on a specialized legal prompt, creating a ready-to-use `.html` file.\n\n---\n\n### **Setup in 3 Steps:**\n\n**1. Configure All Variables \u270f\ufe0f**\n* Click the **'CHANGE THESE: dependencies'** node. This is your central control panel.\n* Fill in all the values, including your WAVE API Key, the URL to analyze, company details, and desired output language.\n\n**2. Set Up Credentials \u2728**\n* You need to connect your Google accounts for this workflow to run.\n* **Gemini:** Click the **'gemini2.5 pro'** node and connect your Google Gemini (or Google AI Studio) API credentials. You can swap this out for any other language model as well.\n* **Gmail:** Click the **'Send report by email'** node and connect your Gmail account to allow sending the final report.\n\n**3. Run the Workflow \u25b6\ufe0f**\n* Click **'Execute workflow'** to run the analysis. The generated `.html` statement will be sent to the email address you specified."
      },
      "typeVersion": 1
    },
    {
      "id": "f3a66efe-8bce-4f08-871d-9a9a70f8ab9e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1980,
        -380
      ],
      "parameters": {
        "color": 4,
        "width": 320,
        "height": 460,
        "content": "# \u2699\ufe0f Step 1: Start Here!\n\nThis is the main configuration node for the workflow.\n\nClick on this node and fill in all the required fields on the right-hand panel before running the workflow."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "gemini 2.5 pro": {
      "ai_languageModel": [
        [
          {
            "node": "Accessibility Statement Generator",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get WAVE Report": {
      "main": [
        [
          {
            "node": "Map WAVE Report Items to Website selectors.",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Website HTML": {
      "main": [
        [
          {
            "node": "Get WAVE Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse output as html": {
      "main": [
        [
          {
            "node": "Create accesibility statement html file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Accessibility Statement Generator",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "CHANGE THESE: dependencies": {
      "main": [
        [
          {
            "node": "Get Website HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Accessibility Statement Generator": {
      "main": [
        [
          {
            "node": "Parse output as html",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "CHANGE THESE: dependencies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create accesibility statement html file": {
      "main": [
        [
          {
            "node": "Send accessibility statement by email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map WAVE Report Items to Website selectors.": {
      "main": [
        [
          {
            "node": "Accessibility Statement Generator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}