diff --git a/docs/en/modules/ROOT/nav.adoc b/docs/en/modules/ROOT/nav.adoc
index 627ebf19d1..91dd3e8103 100644
--- a/docs/en/modules/ROOT/nav.adoc
+++ b/docs/en/modules/ROOT/nav.adoc
@@ -237,7 +237,12 @@
**** xref:develop:view_hooks.adoc[View Hooks]
**** xref:develop:view_models_aka_cells.adoc[View Models (Cells)]
** xref:develop:api/index.adoc[API]
-*** xref:develop:api/proposals/mutations.adoc[Proposals]
+*** xref:develop:api/authentication.adoc[Authentication]
+*** xref:develop:api/core-concepts.adoc[Core concepts]
+*** API reference by module
+**** Spaces
+**** Components
+***** xref:develop:api/reference/components/proposals.adoc[Proposals]
* Understand
** xref:understand:about.adoc[About]
diff --git a/supplemental_ui/css/tabs.css b/supplemental_ui/css/tabs.css
new file mode 100644
index 0000000000..fa97096e3c
--- /dev/null
+++ b/supplemental_ui/css/tabs.css
@@ -0,0 +1,87 @@
+/* Generic Tabs Component for Antora Documentation */
+
+.tabs {
+ margin: 1.5rem 0;
+}
+
+.tabs-nav {
+ display: flex;
+ gap: 8px;
+ margin-bottom: 0;
+ border-bottom: 2px solid #e2e8f0;
+ padding-bottom: 2px;
+ flex-wrap: wrap;
+}
+
+.tabs-nav__button {
+ padding: 8px 16px;
+ background: none;
+ border: none;
+ color: #718096;
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: 500;
+ transition: all 0.2s;
+ border-radius: 6px 6px 0 0;
+ position: relative;
+ font-family: inherit;
+}
+
+.tabs-nav__button:hover {
+ color: #667eea;
+ background: #f7fafc;
+}
+
+.tabs-nav__button.is-active {
+ color: #667eea;
+ background: #edf2f7;
+}
+
+.tabs-nav__button.is-active::after {
+ content: '';
+ position: absolute;
+ bottom: -2px;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: #667eea;
+}
+
+.tabs-content {
+ position: relative;
+}
+
+.tabs-content__panel {
+ display: none;
+}
+
+.tabs-content__panel.is-active {
+ display: block;
+ animation: fadeIn 0.3s ease-in;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(-5px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+/* Ensure proper spacing for nested content */
+.tabs .tabs-content__panel > *:first-child {
+ margin-top: 0;
+}
+
+.tabs .tabs-content__panel > *:last-child {
+ margin-bottom: 0;
+}
+
+/* Specific styling for code blocks in tabs */
+.tabs-content .listingblock {
+ margin-top: 0;
+ margin-bottom: 0;
+}
diff --git a/supplemental_ui/js/tabs.js b/supplemental_ui/js/tabs.js
new file mode 100644
index 0000000000..e2fff50445
--- /dev/null
+++ b/supplemental_ui/js/tabs.js
@@ -0,0 +1,156 @@
+/**
+ * Generic Tabs Component for Antora Documentation
+ * Handles tabbed content with preference persistence
+ */
+
+(function() {
+ 'use strict';
+
+ // Constants
+ const SELECTORS = {
+ TABS_BLOCK: '.tabs',
+ TABS_NAV: '.tabs-nav',
+ TAB_BUTTON: '.tabs-nav__button',
+ TABS_CONTENT: '.tabs-content',
+ TAB_PANEL: '.tabs-content__panel'
+ };
+
+ const CLASSES = {
+ ACTIVE: 'is-active'
+ };
+
+ const STORAGE_PREFIX = 'tabs-preference-';
+
+ /**
+ * Storage utilities for tab preferences
+ */
+ const Storage = {
+ get(key) {
+ try {
+ return localStorage.getItem(STORAGE_PREFIX + key);
+ } catch (e) {
+ return null;
+ }
+ },
+
+ set(key, value) {
+ try {
+ localStorage.setItem(STORAGE_PREFIX + key, value);
+ } catch (e) {
+ // Silently fail if localStorage is not available
+ }
+ }
+ };
+
+ /**
+ * Tab controller for a single tab group
+ */
+ class TabGroup {
+ constructor(element) {
+ this.element = element;
+ this.groupId = element.dataset.tabGroup;
+ this.nav = element.querySelector(SELECTORS.TABS_NAV);
+ this.content = element.querySelector(SELECTORS.TABS_CONTENT);
+
+ if (!this.nav || !this.content) {
+ console.warn('Tabs component missing required elements', element);
+ return;
+ }
+
+ this.buttons = Array.from(this.nav.querySelectorAll(SELECTORS.TAB_BUTTON));
+ this.panels = Array.from(this.content.querySelectorAll(SELECTORS.TAB_PANEL));
+
+ this.init();
+ }
+
+ init() {
+ this.attachEventListeners();
+ this.restorePreference();
+ }
+
+ attachEventListeners() {
+ this.buttons.forEach(button => {
+ button.addEventListener('click', () => this.handleTabClick(button));
+ });
+ }
+
+ handleTabClick(clickedButton) {
+ const tabId = clickedButton.dataset.tab;
+ this.activateTab(tabId);
+ this.savePreference(tabId);
+ }
+
+ activateTab(tabId) {
+ this.deactivateAllTabs();
+ this.activateButton(tabId);
+ this.activatePanel(tabId);
+ }
+
+ deactivateAllTabs() {
+ this.buttons.forEach(button => {
+ button.classList.remove(CLASSES.ACTIVE);
+ });
+ this.panels.forEach(panel => {
+ panel.classList.remove(CLASSES.ACTIVE);
+ });
+ }
+
+ activateButton(tabId) {
+ const button = this.findButtonByTabId(tabId);
+ if (button) {
+ button.classList.add(CLASSES.ACTIVE);
+ }
+ }
+
+ activatePanel(tabId) {
+ const panel = this.findPanelByTabId(tabId);
+ if (panel) {
+ panel.classList.add(CLASSES.ACTIVE);
+ }
+ }
+
+ findButtonByTabId(tabId) {
+ return this.buttons.find(button => button.dataset.tab === tabId);
+ }
+
+ findPanelByTabId(tabId) {
+ return this.panels.find(panel => panel.dataset.tab === tabId);
+ }
+
+ savePreference(tabId) {
+ if (this.groupId) {
+ Storage.set(this.groupId, tabId);
+ }
+ }
+
+ restorePreference() {
+ if (!this.groupId) return;
+
+ const savedTab = Storage.get(this.groupId);
+ if (savedTab && this.findButtonByTabId(savedTab)) {
+ this.activateTab(savedTab);
+ }
+ }
+ }
+
+ /**
+ * Initialize all tab groups on the page
+ */
+ function initializeTabs() {
+ const tabElements = document.querySelectorAll(SELECTORS.TABS_BLOCK);
+ tabElements.forEach(element => new TabGroup(element));
+ }
+
+ /**
+ * Bootstrap the tabs when DOM is ready
+ */
+ function bootstrap() {
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', initializeTabs);
+ } else {
+ initializeTabs();
+ }
+ }
+
+ bootstrap();
+})();
diff --git a/supplemental_ui/partials/head-meta.hbs b/supplemental_ui/partials/head-meta.hbs
index a577b9dd8c..ed7bb88b66 100644
--- a/supplemental_ui/partials/head-meta.hbs
+++ b/supplemental_ui/partials/head-meta.hbs
@@ -1,3 +1,6 @@
-
+
+
+
+