diff --git a/docs/changelog.adoc b/docs/changelog.adoc
new file mode 100644
index 0000000..e4ce9d8
--- /dev/null
+++ b/docs/changelog.adoc
@@ -0,0 +1,158 @@
+= Changelog
+:toc:
+:toc-placement: preamble
+:toclevels: 2
+
+A chronological record of all semantic anchors added to the catalog. Community contributors are credited with thanks.
+
+== 2026-03-09
+
+* *CQRS* — contributed by https://github.com/Nantero1[@Nantero1] in https://github.com/LLM-Coding/Semantic-Anchors/pull/137[#137]. Thank you!
+* *GoF Design Patterns* — contributed by https://github.com/Nantero1[@Nantero1] in https://github.com/LLM-Coding/Semantic-Anchors/pull/140[#140]. Thank you!
+* *Test Double (Meszaros)* — contributed by https://github.com/Nantero1[@Nantero1] in https://github.com/LLM-Coding/Semantic-Anchors/pull/142[#142]. Thank you!
+* *Event-Driven Architecture* — contributed by https://github.com/Nantero1[@Nantero1] in https://github.com/LLM-Coding/Semantic-Anchors/pull/143[#143]. Thank you!
+* *BDD (Given-When-Then)* — contributed by https://github.com/Nantero1[@Nantero1] in https://github.com/LLM-Coding/Semantic-Anchors/pull/138[#138], merged via https://github.com/LLM-Coding/Semantic-Anchors/pull/152[#152]. Thank you!
+* *YAGNI* — contributed by https://github.com/Nantero1[@Nantero1] in https://github.com/LLM-Coding/Semantic-Anchors/pull/139[#139], merged via https://github.com/LLM-Coding/Semantic-Anchors/pull/152[#152]. Thank you!
+
+== 2026-03-06
+
+* *ATAM* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/133[#133]
+* *LASR* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/135[#135]
+
+== 2026-03-04
+
+* *OWASP Top 10* — proposed by https://github.com/Advisior[@Advisior] in https://github.com/LLM-Coding/Semantic-Anchors/issues/130[#130]. Thank you!
+
+== 2026-03-01
+
+* *GoM (Grundsätze ordnungsmäßiger Modellierung)* — proposed by https://github.com/raifdmueller[@raifdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/126[#126]
+
+== 2026-02-23
+
+* *Regulated Environment* — proposed by https://github.com/bit-jkraushaar[@bit-jkraushaar] in https://github.com/LLM-Coding/Semantic-Anchors/issues/120[#120]. Thank you!
+
+== 2026-02-22
+
+* *MoSCoW* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/115[#115]
+
+== 2026-02-17
+
+* *Chatham House Rule* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/101[#101]
+
+== 2026-02-16
+
+* *Fowler Patterns (PEAA)* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/99[#99]
+
+== 2026-02-13
+
+* *Morphological Box* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/67[#67]
+* *IEC 61508 SIL Levels* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/67[#67]
+* Split from monolithic README.adoc into individual anchor files (https://github.com/LLM-Coding/Semantic-Anchors/pull/38[#38])
+
+== 2026-02-12
+
+* *Socratic Method* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/31[#31]
+* *BLUF* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/31[#31]
+* *Rubber Duck Debugging* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/31[#31]
+* *Chain of Thought* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/31[#31]
+* *Devil's Advocate* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/31[#31]
+* *Five Whys* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/31[#31]
+* *Feynman Technique* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/31[#31]
+* *MADR* — proposed by https://github.com/raifdmueller[@raifdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/29[#29]
+
+== 2026-02-11
+
+* *TIMTOWTDI* — contributed by https://github.com/rehsack[@rehsack] in https://github.com/LLM-Coding/Semantic-Anchors/pull/28[#28]. Thank you!
+
+== 2026-02-07
+
+* *MECE Principle* — proposed by https://github.com/ingo-eichhorst[@ingo-eichhorst] in https://github.com/LLM-Coding/Semantic-Anchors/issues/26[#26]. Thank you!
+
+== 2026-02-05
+
+* *Nelson Rules* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/20[#20]
+* *Control Chart (Shewhart)* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/21[#21]
+* *SPC* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/22[#22]
+
+== 2026-02-03
+
+* *DRY Principle* — added in https://github.com/LLM-Coding/Semantic-Anchors/pull/19[#19]
+* *SPOT Principle* — added in https://github.com/LLM-Coding/Semantic-Anchors/pull/19[#19]
+* *SSOT Principle* — added in https://github.com/LLM-Coding/Semantic-Anchors/pull/19[#19]
+* *SOTA* — proposed by https://github.com/raifdmueller[@raifdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/16[#16]
+* *todo.txt-flavoured Markdown* — proposed by https://github.com/raifdmueller[@raifdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/14[#14]
+
+== 2026-01-21
+
+* *Pyramid Principle* — proposed by https://github.com/rdmueller[@rdmueller] in https://github.com/LLM-Coding/Semantic-Anchors/issues/12[#12]
+
+== 2025-11-18
+
+* *Mutation Testing* — contributed by ThomasPeuss. Thank you!
+
+== 2025-11-13
+
+* *BEM Methodology* — contributed by Robert Nimax. Thank you!
+
+== 2025-11-11
+
+* *Conventional Commits* — contributed by https://github.com/rehsack[@rehsack] in https://github.com/LLM-Coding/Semantic-Anchors/pull/4[#4]. Thank you!
+* *Semantic Versioning* — contributed by https://github.com/rehsack[@rehsack] in https://github.com/LLM-Coding/Semantic-Anchors/pull/4[#4]. Thank you!
+* *SOLID Principles* — contributed by https://github.com/bit-jkraushaar[@bit-jkraushaar]. Thank you!
+
+== 2025-11-10 — Initial Catalog
+
+First commit by https://github.com/rdmueller[@rdmueller] with 23 founding anchors:
+
+* *TDD, London School*
+* *TDD, Chicago School*
+* *Problem Space NVC*
+* *Mental Model (Naur)*
+* *EARS Requirements*
+* *arc42*
+* *ADR (Nygard)*
+* *Pugh Matrix*
+* *C4 Diagrams*
+* *Docs-as-Code*
+* *Domain-Driven Design*
+* *Hexagonal Architecture*
+* *Clean Architecture*
+* *User Story Mapping*
+* *Impact Mapping*
+* *Jobs To Be Done*
+* *Cynefin Framework*
+* *Wardley Mapping*
+* *Property-Based Testing*
+* *Testing Pyramid*
+* *Diátaxis Framework*
+* *What Qualifies as a Semantic Anchor*
+
+== Community Contributors
+
+Thank you to everyone who has contributed anchors to the catalog!
+
+[cols="1,3"]
+|===
+| Contributor | Contributions
+
+| https://github.com/rehsack[@rehsack]
+| Conventional Commits, Semantic Versioning, TIMTOWTDI
+
+| https://github.com/bit-jkraushaar[@bit-jkraushaar]
+| SOLID Principles, Regulated Environment
+
+| Robert Nimax
+| BEM Methodology
+
+| ThomasPeuss
+| Mutation Testing
+
+| https://github.com/ingo-eichhorst[@ingo-eichhorst]
+| MECE Principle
+
+| https://github.com/Advisior[@Advisior]
+| OWASP Top 10
+
+| https://github.com/Nantero1[@Nantero1]
+| CQRS, GoF Design Patterns, Test Double (Meszaros), Event-Driven Architecture, BDD, YAGNI
+|===
diff --git a/website/src/components/header.js b/website/src/components/header.js
index 0f23205..587f9a9 100644
--- a/website/src/components/header.js
+++ b/website/src/components/header.js
@@ -37,6 +37,7 @@ export function renderHeader() {
${i18n.t('nav.catalog')}
${i18n.t('nav.about')}
${i18n.t('nav.contributing')}
+ ${i18n.t('nav.changelog')}
diff --git a/website/src/main.js b/website/src/main.js
index b162018..6fb5541 100644
--- a/website/src/main.js
+++ b/website/src/main.js
@@ -102,6 +102,7 @@ function initApp() {
addRoute('/', renderHomePage)
addRoute('/about', renderAboutPage)
addRoute('/contributing', renderContributingPage)
+ addRoute('/changelog', renderChangelogPage)
addRoute('/all-anchors', renderAllAnchorsPage)
const app = document.querySelector('#app')
@@ -178,6 +179,15 @@ function renderContributingPage() {
loadDocContent('CONTRIBUTING.adoc')
}
+function renderChangelogPage() {
+ const pageContent = document.getElementById('page-content')
+ if (!pageContent) return
+
+ pageContent.innerHTML = renderDocPage()
+ updateActiveNavLink()
+ loadDocContent('docs/changelog.adoc')
+}
+
function renderAllAnchorsPage() {
const pageContent = document.getElementById('page-content')
if (!pageContent) return
@@ -381,6 +391,8 @@ function handleLanguageChange() {
loadDocContent('docs/about.adoc')
} else if (currentRoute === '/contributing') {
loadDocContent('CONTRIBUTING.adoc')
+ } else if (currentRoute === '/changelog') {
+ loadDocContent('docs/changelog.adoc')
} else if (currentRoute === '/all-anchors') {
loadDocContent('docs/all-anchors.adoc')
} else if (currentRoute === '/') {
diff --git a/website/src/translations/de.json b/website/src/translations/de.json
index e710ddf..f07a1b1 100644
--- a/website/src/translations/de.json
+++ b/website/src/translations/de.json
@@ -8,6 +8,7 @@
"nav.catalog": "Katalog",
"nav.about": "Über",
"nav.contributing": "Mitwirken",
+ "nav.changelog": "Änderungsprotokoll",
"main.heading": "Semantic Anchors erkunden",
"main.subheading": "Ein kuratierter Katalog klar definierter Begriffe, Methoden und Frameworks für effektive LLM-Kommunikation.",
"main.aboutLink": "Über",
diff --git a/website/src/translations/en.json b/website/src/translations/en.json
index 6ea0531..22a551d 100644
--- a/website/src/translations/en.json
+++ b/website/src/translations/en.json
@@ -8,6 +8,7 @@
"nav.catalog": "Catalog",
"nav.about": "About",
"nav.contributing": "Contributing",
+ "nav.changelog": "Changelog",
"main.heading": "Explore Semantic Anchors",
"main.subheading": "A curated catalog of well-defined terms, methodologies, and frameworks for effective LLM communication.",
"main.aboutLink": "About",
diff --git a/website/tests/e2e/website.spec.js b/website/tests/e2e/website.spec.js
index 8989d9d..3216dba 100644
--- a/website/tests/e2e/website.spec.js
+++ b/website/tests/e2e/website.spec.js
@@ -1,5 +1,12 @@
import { test, expect } from '@playwright/test'
+// Dismiss onboarding modal before all tests
+test.beforeEach(async ({ page }) => {
+ await page.addInitScript(() => {
+ localStorage.setItem('onboarding-seen', 'true')
+ })
+})
+
test.describe('Homepage - Card Grid', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/')
@@ -7,7 +14,7 @@ test.describe('Homepage - Card Grid', () => {
test('should load homepage successfully', async ({ page }) => {
await expect(page).toHaveTitle(/Semantic Anchors/)
- await expect(page.locator('h1')).toContainText('Semantic Anchors')
+ await expect(page.locator('h2').first()).toContainText('Semantic Anchors')
})
test('should display header with navigation', async ({ page }) => {
@@ -41,14 +48,18 @@ test.describe('Homepage - Card Grid', () => {
})
test('should display search and filter controls', async ({ page }) => {
- await expect(page.locator('#search-input')).toBeVisible()
- await expect(page.locator('#role-filter')).toBeVisible()
+ // On desktop, search and filter are in the header
+ await expect(page.locator('#header-search-input')).toBeVisible()
+ await expect(page.locator('#header-role-filter')).toBeVisible()
- // Role filter should have options
- const roleFilter = page.locator('#role-filter')
+ // Role filter should have options (wait for data to load)
+ await page.waitForSelector('.anchor-card', { timeout: 10000 })
+ const roleFilter = page.locator('#header-role-filter')
const options = roleFilter.locator('option')
- const count = await options.count()
- expect(count).toBeGreaterThan(1) // At least "All Roles" + 1 role
+ await expect(async () => {
+ const count = await options.count()
+ expect(count).toBeGreaterThan(1)
+ }).toPass({ timeout: 10000 })
})
test('should filter cards by role', async ({ page }) => {
@@ -58,8 +69,8 @@ test.describe('Homepage - Card Grid', () => {
const initialCount = await page.locator('.anchor-card').count()
expect(initialCount).toBeGreaterThan(0)
- // Select a role
- await page.selectOption('#role-filter', 'software-developer')
+ // Select a role (use header filter on desktop)
+ await page.selectOption('#header-role-filter', 'software-developer')
// Some cards should still be visible
const filteredCount = await page.locator('.anchor-card:visible').count()
@@ -69,15 +80,15 @@ test.describe('Homepage - Card Grid', () => {
test('should filter cards by search query', async ({ page }) => {
await page.waitForSelector('.anchor-card', { timeout: 10000 })
- // Type in search
- await page.fill('#search-input', 'TDD')
+ // Type in search (use header search on desktop)
+ await page.fill('#header-search-input', 'TDD')
// Some cards should be visible with TDD
const visibleCards = await page.locator('.anchor-card:visible').count()
expect(visibleCards).toBeGreaterThan(0)
// Clear search
- await page.fill('#search-input', '')
+ await page.fill('#header-search-input', '')
// All cards should be visible again
const allCards = await page.locator('.anchor-card:visible').count()
@@ -212,8 +223,8 @@ test.describe('Routing - Documentation Pages', () => {
})
test('should navigate to About page', async ({ page }) => {
- // Click About link
- await page.click('a[data-route="/about"]')
+ // Click About link (use first for desktop nav)
+ await page.locator('a[data-route="/about"]').first().click()
// URL should update
expect(page.url()).toContain('#/about')
@@ -228,8 +239,8 @@ test.describe('Routing - Documentation Pages', () => {
})
test('should navigate to Contributing page', async ({ page }) => {
- // Click Contributing link
- await page.click('a[data-route="/contributing"]')
+ // Click Contributing link (use first for desktop nav)
+ await page.locator('a[data-route="/contributing"]').first().click()
// URL should update
expect(page.url()).toContain('#/contributing')
@@ -244,11 +255,11 @@ test.describe('Routing - Documentation Pages', () => {
})
test('should navigate back to Catalog from About', async ({ page }) => {
- // Go to About
- await page.click('a[data-route="/about"]')
+ // Go to About (use first for desktop nav)
+ await page.locator('a[data-route="/about"]').first().click()
// Go back to Catalog
- await page.click('a[data-route="/"]')
+ await page.locator('a[data-route="/"]').first().click()
// URL should be home
expect(page.url()).toMatch(/#\/$|#$/)
@@ -271,8 +282,8 @@ test.describe('Routing - Documentation Pages', () => {
})
test('should handle browser back button', async ({ page }) => {
- // Navigate to About
- await page.click('a[data-route="/about"]')
+ // Navigate to About (use first for desktop nav)
+ await page.locator('a[data-route="/about"]').first().click()
// Go back
await page.goBack()
@@ -287,14 +298,14 @@ test.describe('Responsive Design', () => {
await page.goto('/')
await page.setViewportSize({ width: 375, height: 667 })
- // Page should still be visible
- await expect(page.locator('h1')).toBeVisible()
+ // Page should still be visible (heading is h2 in current layout)
+ await expect(page.locator('h2').first()).toBeVisible()
await page.waitForSelector('.anchor-card', { timeout: 10000 })
await expect(page.locator('.anchor-card').first()).toBeVisible()
- // Navigation should be hidden on mobile
- const nav = page.locator('.nav-link').first()
- const isVisible = await nav.isVisible()
+ // Desktop navigation should be hidden on mobile
+ const desktopNav = page.locator('.hidden.sm\\:flex .nav-link').first()
+ const isVisible = await desktopNav.isVisible()
expect(isVisible).toBe(false)
})
@@ -302,7 +313,7 @@ test.describe('Responsive Design', () => {
await page.goto('/')
await page.setViewportSize({ width: 768, height: 1024 })
- await expect(page.locator('h1')).toBeVisible()
+ await expect(page.locator('h2').first()).toBeVisible()
await page.waitForSelector('.anchor-card', { timeout: 10000 })
await expect(page.locator('.anchor-card').first()).toBeVisible()
@@ -314,7 +325,7 @@ test.describe('Responsive Design', () => {
await page.goto('/')
await page.setViewportSize({ width: 1920, height: 1080 })
- await expect(page.locator('h1')).toBeVisible()
+ await expect(page.locator('h2').first()).toBeVisible()
await page.waitForSelector('.anchor-card', { timeout: 10000 })
await expect(page.locator('.anchor-card').first()).toBeVisible()
})
@@ -354,12 +365,13 @@ test.describe('Accessibility', () => {
})
test('should have proper heading hierarchy', async ({ page }) => {
- // Check h1 exists
- await expect(page.locator('h1')).toBeVisible()
+ // Check page heading exists (h2 in current layout)
+ await expect(page.locator('h2').first()).toBeVisible()
- // Check h2 headings (category headings)
- const h2s = page.locator('h2')
- const count = await h2s.count()
+ // Check h3 headings (category headings)
+ await page.waitForSelector('.category-section', { timeout: 10000 })
+ const h3s = page.locator('.category-heading')
+ const count = await h3s.count()
expect(count).toBeGreaterThan(0)
})
})
@@ -393,7 +405,7 @@ test.describe('Performance', () => {
test('should load search index asynchronously', async ({ page }) => {
await page.waitForSelector('.anchor-card', { timeout: 10000 })
- const searchInput = page.locator('#search-input')
+ const searchInput = page.locator('#header-search-input')
await searchInput.fill('tdd')
await expect(searchInput).toHaveAttribute('placeholder', /full-text/, { timeout: 15000 })
})