{"id":7132,"date":"2026-03-19T17:58:02","date_gmt":"2026-03-19T12:28:02","guid":{"rendered":"https:\/\/scrolltest.com\/ai-powered-e2e-testing-framework-playwright\/"},"modified":"2026-03-31T17:51:17","modified_gmt":"2026-03-31T12:21:17","slug":"ai-powered-e2e-testing-framework-playwright","status":"publish","type":"post","link":"https:\/\/scrolltest.com\/ai-powered-e2e-testing-framework-playwright\/","title":{"rendered":"Building an AI-Powered E2E Testing Framework with Playwright: Self-Healing, Failure Analysis, and Test Generation"},"content":{"rendered":"\n<p>A test automation engineer spent three weeks building an end-to-end test framework for a fintech application. Playwright for browser automation, TypeScript for type safety, Page Object Model for structure, and custom reporters for dashboards. The framework was elegant. 200 tests. 95% pass rate.<\/p>\n\n\n\n<p>Then the frontend team redesigned the settings page. 47 tests broke \u2014 not because of bugs, but because button labels changed, form layouts shifted, and modal dialogs were replaced with inline editing. The engineer spent another week updating locators, adjusting wait conditions, and rewriting assertions.<\/p>\n\n\n\n<p>Two months later, the checkout flow was redesigned. Another 60 broken tests. Another week of maintenance.<\/p>\n\n\n\n<p>This maintenance death spiral is the fundamental problem that AI-powered E2E frameworks aim to solve \u2014 not by eliminating the need for test design, but by making tests resilient to the UI changes that consume most of a test engineer&#8217;s time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Makes an E2E Framework &#8220;AI-Powered&#8221;?<\/h2>\n\n\n\n<p>The term gets thrown around loosely. Let&#8217;s be specific about what AI actually does in a testing framework \u2014 and what it doesn&#8217;t do.<\/p>\n\n\n\n<p><strong>What AI can do well in E2E testing:<\/strong> Self-heal broken locators by finding alternative ways to identify elements. Generate test data that covers edge cases humans might miss. Analyze test failures to distinguish real bugs from test infrastructure issues. Suggest new test scenarios based on application changes.<\/p>\n\n\n\n<p><strong>What AI can&#8217;t do (yet):<\/strong> Replace human judgment about what matters to test. Understand business logic without being told. Design a test strategy from scratch. Guarantee correctness \u2014 AI-generated tests still need human review.<\/p>\n\n\n\n<p>An AI-powered E2E framework is a traditional framework (Playwright, Cypress, Selenium) enhanced with AI capabilities at specific points in the testing lifecycle. It&#8217;s not a replacement for test engineering. It&#8217;s an amplifier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Architecture: Building an AI-Enhanced Playwright Framework<\/h2>\n\n\n\n<p>Here&#8217;s a practical architecture that integrates AI capabilities into a Playwright-based framework without requiring ML expertise.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Layer 1: Core Test Framework (Playwright + TypeScript)<\/h3>\n\n\n\n<pre><code>\/\/ playwright.config.ts\nimport { defineConfig } from '@playwright\/test';\n\nexport default defineConfig({\n  testDir: '.\/tests',\n  timeout: 30000,\n  retries: 1,\n  use: {\n    baseURL: process.env.BASE_URL || 'https:\/\/staging.example.com',\n    screenshot: 'only-on-failure',\n    trace: 'retain-on-failure',\n    video: 'retain-on-failure',\n  },\n  reporter: [\n    ['html'],\n    ['.\/reporters\/ai-analyzer.ts'],  \/\/ Custom AI failure analyzer\n  ],\n});\n\n\/\/ Project structure\n\/\/ tests\/\n\/\/ \u251c\u2500\u2500 e2e\/\n\/\/ \u2502   \u251c\u2500\u2500 checkout.spec.ts\n\/\/ \u2502   \u251c\u2500\u2500 authentication.spec.ts\n\/\/ \u2502   \u2514\u2500\u2500 dashboard.spec.ts\n\/\/ \u251c\u2500\u2500 pages\/\n\/\/ \u2502   \u251c\u2500\u2500 BasePage.ts          \u2190 AI-enhanced base page\n\/\/ \u2502   \u251c\u2500\u2500 CheckoutPage.ts\n\/\/ \u2502   \u2514\u2500\u2500 DashboardPage.ts\n\/\/ \u251c\u2500\u2500 ai\/\n\/\/ \u2502   \u251c\u2500\u2500 locator-healer.ts    \u2190 Self-healing locators\n\/\/ \u2502   \u251c\u2500\u2500 test-generator.ts    \u2190 AI test suggestions\n\/\/ \u2502   \u2514\u2500\u2500 failure-analyzer.ts  \u2190 Intelligent failure analysis\n\/\/ \u2514\u2500\u2500 fixtures\/\n\/\/     \u251c\u2500\u2500 auth.fixture.ts\n\/\/     \u2514\u2500\u2500 data.fixture.ts<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Layer 2: Self-Healing Locators<\/h3>\n\n\n\n<p>The highest-value AI enhancement. When a locator fails, the self-healing layer attempts to find the element using alternative strategies before reporting a failure.<\/p>\n\n\n\n<pre><code>\/\/ ai\/locator-healer.ts\nimport { Page, Locator } from '@playwright\/test';\n\ninterface HealingStrategy {\n  name: string;\n  find: (page: Page, context: ElementContext) => Promise&lt;Locator | null&gt;;\n}\n\ninterface ElementContext {\n  originalLocator: string;\n  tagName?: string;\n  textContent?: string;\n  ariaLabel?: string;\n  testId?: string;\n  nearbyText?: string;\n}\n\nexport class LocatorHealer {\n  private strategies: HealingStrategy[] = [\n    {\n      name: 'text-content',\n      find: async (page, ctx) => {\n        if (ctx.textContent) {\n          const loc = page.getByText(ctx.textContent, { exact: true });\n          if (await loc.count() === 1) return loc;\n        }\n        return null;\n      }\n    },\n    {\n      name: 'aria-label',\n      find: async (page, ctx) => {\n        if (ctx.ariaLabel) {\n          const loc = page.getByLabel(ctx.ariaLabel);\n          if (await loc.count() === 1) return loc;\n        }\n        return null;\n      }\n    },\n    {\n      name: 'role-based',\n      find: async (page, ctx) => {\n        if (ctx.textContent && ctx.tagName === 'button') {\n          const loc = page.getByRole('button', { name: ctx.textContent });\n          if (await loc.count() === 1) return loc;\n        }\n        return null;\n      }\n    },\n    {\n      name: 'test-id-fuzzy',\n      find: async (page, ctx) => {\n        if (ctx.testId) {\n          \/\/ Try common test-id variations\n          const variations = [\n            ctx.testId,\n            ctx.testId.replace(\/-\/g, '_'),\n            ctx.testId.replace(\/_\/g, '-'),\n            `btn-${ctx.testId}`,\n            `${ctx.testId}-btn`,\n          ];\n          for (const v of variations) {\n            const loc = page.locator(`[data-testid=\"${v}\"]`);\n            if (await loc.count() === 1) return loc;\n          }\n        }\n        return null;\n      }\n    }\n  ];\n\n  async heal(page: Page, context: ElementContext): Promise&lt;Locator | null&gt; {\n    for (const strategy of this.strategies) {\n      const result = await strategy.find(page, context);\n      if (result) {\n        console.log(\n          `[HEALED] \"${context.originalLocator}\" \u2192 `+\n          `strategy: ${strategy.name}`\n        );\n        return result;\n      }\n    }\n    return null;\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Layer 3: AI-Powered Failure Analysis<\/h3>\n\n\n\n<p>When tests fail, the AI analyzer categorizes failures to help engineers triage faster. It distinguishes between: real application bugs, test infrastructure issues (timing, environment), UI changes requiring test updates, and known flaky tests.<\/p>\n\n\n\n<pre><code>\/\/ ai\/failure-analyzer.ts\ninterface FailureAnalysis {\n  category: 'bug' | 'infrastructure' | 'ui-change' | 'flaky';\n  confidence: number;\n  explanation: string;\n  suggestedAction: string;\n}\n\nexport class FailureAnalyzer {\n  private flakyHistory: Map&lt;string, number[]&gt; = new Map();\n\n  analyze(testName: string, error: Error, \n          screenshot?: Buffer): FailureAnalysis {\n    \/\/ Check flaky history\n    const history = this.flakyHistory.get(testName) || [];\n    const recentFailRate = this.calculateRecentFailRate(history);\n    \n    if (recentFailRate > 0.2 && recentFailRate < 0.8) {\n      return {\n        category: 'flaky',\n        confidence: 0.85,\n        explanation: `Test has ${(recentFailRate*100).toFixed(0)}% failure rate over last 20 runs`,\n        suggestedAction: 'Quarantine and investigate root cause'\n      };\n    }\n\n    \/\/ Check for locator failures\n    if (error.message.includes('locator resolved to') || \n        error.message.includes('waiting for selector')) {\n      return {\n        category: 'ui-change',\n        confidence: 0.9,\n        explanation: 'Element locator no longer matches any element',\n        suggestedAction: 'Review recent UI changes and update locator'\n      };\n    }\n\n    \/\/ Check for timeout\/infrastructure issues\n    if (error.message.includes('timeout') || \n        error.message.includes('net::ERR')) {\n      return {\n        category: 'infrastructure',\n        confidence: 0.8,\n        explanation: 'Network or timeout issue detected',\n        suggestedAction: 'Check test environment health'\n      };\n    }\n\n    \/\/ Default: likely a real bug\n    return {\n      category: 'bug',\n      confidence: 0.7,\n      explanation: 'Assertion failure on expected behavior',\n      suggestedAction: 'Investigate application behavior'\n    };\n  }\n\n  private calculateRecentFailRate(history: number[]): number {\n    const recent = history.slice(-20);\n    if (recent.length < 5) return 0;\n    return recent.filter(r => r === 0).length \/ recent.length;\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Layer 4: AI-Assisted Test Generation<\/h3>\n\n\n\n<p>Use LLMs to suggest test scenarios based on page analysis. The generator crawls the application, identifies interactive elements, and suggests test cases that a human reviewer can approve, modify, or reject.<\/p>\n\n\n\n<pre><code>\/\/ ai\/test-generator.ts\nimport { Page } from '@playwright\/test';\n\ninterface TestSuggestion {\n  name: string;\n  description: string;\n  steps: string[];\n  priority: 'high' | 'medium' | 'low';\n  type: 'happy-path' | 'edge-case' | 'error-handling';\n}\n\nexport class TestGenerator {\n  async analyzePageAndSuggest(page: Page): Promise&lt;TestSuggestion[]&gt; {\n    \/\/ Gather page context\n    const forms = await page.locator('form').all();\n    const buttons = await page.locator('button, [role=\"button\"]').all();\n    const inputs = await page.locator('input, textarea, select').all();\n    const links = await page.locator('a[href]').all();\n    \n    const suggestions: TestSuggestion[] = [];\n    \n    \/\/ For each form, suggest validation tests\n    for (const form of forms) {\n      const formInputs = await form.locator('input').all();\n      \n      suggestions.push({\n        name: 'Submit form with all valid data',\n        description: 'Verify form submission succeeds with valid inputs',\n        steps: ['Fill all required fields', 'Click submit', 'Verify success'],\n        priority: 'high',\n        type: 'happy-path'\n      });\n      \n      suggestions.push({\n        name: 'Submit form with empty required fields',\n        description: 'Verify form shows validation errors',\n        steps: ['Leave required fields empty', 'Click submit', \n                'Verify error messages appear'],\n        priority: 'high',\n        type: 'error-handling'\n      });\n      \n      \/\/ Suggest edge case tests for each input\n      for (const input of formInputs) {\n        const type = await input.getAttribute('type');\n        if (type === 'email') {\n          suggestions.push({\n            name: 'Submit form with invalid email format',\n            description: 'Verify email validation rejects invalid formats',\n            steps: ['Enter invalid email', 'Submit', 'Verify error'],\n            priority: 'medium',\n            type: 'edge-case'\n          });\n        }\n      }\n    }\n    \n    return suggestions;\n  }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Putting It All Together: A Complete Test Example<\/h2>\n\n\n\n<pre><code>\/\/ tests\/e2e\/checkout.spec.ts\nimport { test, expect } from '@playwright\/test';\nimport { CheckoutPage } from '..\/pages\/CheckoutPage';\nimport { FailureAnalyzer } from '..\/ai\/failure-analyzer';\n\nconst analyzer = new FailureAnalyzer();\n\ntest.describe('Checkout Flow', () => {\n  \n  test('complete purchase with valid payment', async ({ page }) => {\n    const checkout = new CheckoutPage(page);\n    \n    await checkout.goto();\n    await checkout.addItem('Premium Plan');\n    await checkout.fillPaymentDetails({\n      cardNumber: '4111111111111111',\n      expiry: '12\/28',\n      cvv: '123'\n    });\n    await checkout.submitOrder();\n    \n    \/\/ AI-enhanced assertion: checks both UI and API\n    await checkout.verifyOrderConfirmation();\n    \n    \/\/ Verify via API that order was actually created\n    const order = await checkout.getOrderViaAPI();\n    expect(order.status).toBe('confirmed');\n    expect(order.total).toBeGreaterThan(0);\n  });\n\n  test('handles payment decline gracefully', async ({ page }) => {\n    const checkout = new CheckoutPage(page);\n    \n    await checkout.goto();\n    await checkout.addItem('Premium Plan');\n    await checkout.fillPaymentDetails({\n      cardNumber: '4000000000000002', \/\/ Test decline card\n      expiry: '12\/28',\n      cvv: '123'\n    });\n    await checkout.submitOrder();\n    \n    \/\/ Verify user-friendly error\n    await expect(\n      page.locator('[data-testid=\"payment-error\"]')\n    ).toContainText('Payment was declined');\n    \n    \/\/ Verify user can retry\n    await expect(\n      page.locator('[data-testid=\"retry-payment\"]')\n    ).toBeVisible();\n  });\n});<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">What This Framework Won&#8217;t Do<\/h2>\n\n\n\n<p>AI-powered doesn&#8217;t mean magic-powered. This framework won&#8217;t write your entire test suite for you. AI-generated test suggestions need human review \u2014 they catch obvious patterns but miss business-specific nuances. The self-healer handles common locator changes but not major redesigns. The failure analyzer categorizes with 70-90% accuracy, not 100%.<\/p>\n\n\n\n<p>The value proposition isn&#8217;t &#8220;replace test engineers.&#8221; It&#8217;s &#8220;make test engineers 2-3x more productive by automating the mechanical parts of the job.&#8221;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Started<\/h2>\n\n\n\n<p><strong>Week 1:<\/strong> Set up the core Playwright + TypeScript framework with Page Object Model structure. Write 10 tests for your most critical user flows.<\/p>\n\n\n\n<p><strong>Week 2:<\/strong> Add the self-healing locator layer. Implement the text-content, aria-label, and role-based strategies. Log all healing events.<\/p>\n\n\n\n<p><strong>Week 3:<\/strong> Implement the failure analyzer. Start categorizing test failures automatically. Build a dashboard showing bug vs. infrastructure vs. UI-change failure ratios.<\/p>\n\n\n\n<p><strong>Week 4:<\/strong> Add AI-assisted test generation. Run the page analyzer against your application. Review suggestions and implement the high-priority ones.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Do I need an LLM API key for this?<\/h3>\n\n\n\n<p>Not for layers 1-3. The self-healing and failure analysis use pattern matching and heuristics. Layer 4 (test generation) can optionally use an LLM for more sophisticated suggestions, but the basic version works with rule-based analysis.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How does this compare to commercial tools like Testim or Mabl?<\/h3>\n\n\n\n<p>Commercial tools offer polished UIs, managed infrastructure, and pre-built AI features. This framework gives you full control, no vendor lock-in, and the ability to customize AI behavior to your specific application. Trade-off: more setup effort, more flexibility.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can I add this to an existing test framework?<\/h3>\n\n\n\n<p>Yes. Each AI layer is independent. You can add self-healing locators to an existing Playwright project without touching the other layers. Start with the layer that addresses your biggest pain point.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Bottom Line<\/h2>\n\n\n\n<p>The test engineer who spent weeks updating locators after UI redesigns wasn&#8217;t doing bad work. The framework design made that work inevitable. Every UI change triggered a maintenance cascade because the framework had no resilience, no intelligence, and no ability to adapt.<\/p>\n\n\n\n<p>An AI-powered framework doesn&#8217;t eliminate maintenance. It reduces it dramatically by making tests resilient to common changes, by categorizing failures intelligently so engineers spend time on real bugs instead of false alarms, and by suggesting tests that humans might not think of.<\/p>\n\n\n\n<p>Start with self-healing locators. That alone will cut your maintenance burden in half. Then add failure analysis. Then test generation. Each layer compounds the productivity gains of the previous one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/playwright.dev\/docs\/intro\" target=\"_blank\" rel=\"noopener\">Playwright Documentation<\/a> \u2014 Core browser automation framework<\/li>\n<li><a href=\"https:\/\/playwright.dev\/docs\/locators\" target=\"_blank\" rel=\"noopener\">Playwright Locators Guide<\/a> \u2014 Built-in locator strategies and best practices<\/li>\n<li><a href=\"https:\/\/playwright.dev\/docs\/api-testing\" target=\"_blank\" rel=\"noopener\">Playwright API Testing<\/a> \u2014 Hybrid testing capabilities<\/li>\n<li><a href=\"https:\/\/github.com\/healenium\/healenium-web\" target=\"_blank\" rel=\"noopener\">Healenium<\/a> \u2014 Open-source self-healing framework for Selenium<\/li>\n<li><a href=\"https:\/\/www.typescriptlang.org\/docs\/\" target=\"_blank\" rel=\"noopener\">TypeScript Documentation<\/a> \u2014 Type-safe test development<\/li>\n<li><a href=\"https:\/\/martinfowler.com\/bliki\/PageObject.html\" target=\"_blank\" rel=\"noopener\">Martin Fowler \u2014 Page Object Pattern<\/a> \u2014 Test structure best practices<\/li>\n<li><a href=\"https:\/\/docs.github.com\/en\/actions\" target=\"_blank\" rel=\"noopener\">GitHub Actions<\/a> \u2014 CI\/CD for automated test execution<\/li>\n<li><a href=\"https:\/\/github.com\/features\/copilot\" target=\"_blank\" rel=\"noopener\">GitHub Copilot<\/a> \u2014 AI pair programming for test code<\/li>\n<li><a href=\"https:\/\/testing.googleblog.com\/\" target=\"_blank\" rel=\"noopener\">Google Testing Blog<\/a> \u2014 Industry perspectives on test automation<\/li>\n<li><a href=\"https:\/\/www.ministryoftesting.com\/\" target=\"_blank\" rel=\"noopener\">Ministry of Testing<\/a> \u2014 Test automation community and resources<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Build an AI-enhanced Playwright framework with self-healing locators, intelligent failure analysis, and AI-assisted test generation. Includes complete TypeScript code examples and a 4-week implementation plan.<\/p>\n","protected":false},"author":4471,"featured_media":7133,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[1001,737,837,26],"tags":[],"class_list":["post-7132","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-testing","category-playwright-tutorial-java","category-test-automation","category-testing"],"taxonomy_info":{"category":[{"value":1001,"label":"AI Testing"},{"value":737,"label":"Playwright tutorial Java"},{"value":837,"label":"Test Automation"},{"value":26,"label":"Testing"}]},"featured_image_src_large":["https:\/\/scrolltest.com\/wp-content\/uploads\/2026\/03\/ai-powered-e2e-framework-featured-1024x538.png",1024,538,true],"author_info":{"display_name":"Pramod Dutta","author_link":"https:\/\/scrolltest.com\/author\/prrammoddutta\/"},"comment_info":0,"category_info":[{"term_id":1001,"name":"AI Testing","slug":"ai-testing","term_group":0,"term_taxonomy_id":1001,"taxonomy":"category","description":"AI-powered testing tools, agentic QE, LLM testing, and AI quality engineering","parent":0,"count":25,"filter":"raw","cat_ID":1001,"category_count":25,"category_description":"AI-powered testing tools, agentic QE, LLM testing, and AI quality engineering","cat_name":"AI Testing","category_nicename":"ai-testing","category_parent":0},{"term_id":737,"name":"Playwright tutorial Java","slug":"playwright-tutorial-java","term_group":0,"term_taxonomy_id":737,"taxonomy":"category","description":"","parent":0,"count":14,"filter":"raw","cat_ID":737,"category_count":14,"category_description":"","cat_name":"Playwright tutorial Java","category_nicename":"playwright-tutorial-java","category_parent":0},{"term_id":837,"name":"Test Automation","slug":"test-automation","term_group":0,"term_taxonomy_id":837,"taxonomy":"category","description":"","parent":0,"count":10,"filter":"raw","cat_ID":837,"category_count":10,"category_description":"","cat_name":"Test Automation","category_nicename":"test-automation","category_parent":0},{"term_id":26,"name":"Testing","slug":"testing","term_group":0,"term_taxonomy_id":26,"taxonomy":"category","description":"","parent":0,"count":457,"filter":"raw","cat_ID":26,"category_count":457,"category_description":"","cat_name":"Testing","category_nicename":"testing","category_parent":0}],"tag_info":false,"_links":{"self":[{"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/posts\/7132","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/users\/4471"}],"replies":[{"embeddable":true,"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/comments?post=7132"}],"version-history":[{"count":1,"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/posts\/7132\/revisions"}],"predecessor-version":[{"id":7134,"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/posts\/7132\/revisions\/7134"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/media\/7133"}],"wp:attachment":[{"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/media?parent=7132"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/categories?post=7132"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scrolltest.com\/wp-json\/wp\/v2\/tags?post=7132"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}