diff --git a/.claude/agents/hugo-ui-dev.md b/.claude/agents/hugo-ui-dev.md
new file mode 100644
index 0000000000..e1e8a9de59
--- /dev/null
+++ b/.claude/agents/hugo-ui-dev.md
@@ -0,0 +1,269 @@
+---
+name: hugo-ui-dev
+description: Hugo template and SASS/CSS development specialist for the InfluxData docs-v2 repository. Use this agent for creating/editing Hugo layouts, partials, shortcodes, and SASS stylesheets. This agent focuses on structure and styling, not JavaScript/TypeScript behavior.
+tools: ["*"]
+model: sonnet
+---
+
+# Hugo Template & SASS/CSS Development Agent
+
+## Purpose
+
+Specialized agent for Hugo template development and SASS/CSS styling in the InfluxData docs-v2 repository. Handles the **structure and styling** layer of the documentation site UI.
+
+## Scope and Responsibilities
+
+### Primary Capabilities
+
+1. **Hugo Template Development**
+ - Create and modify layouts in `layouts/`, `layouts/partials/`, `layouts/shortcodes/`
+ - Implement safe data access patterns for Hugo templates
+ - Handle Hugo's template inheritance and partial inclusion
+ - Configure page types and content organization
+
+2. **SASS/CSS Styling**
+ - Develop styles in `assets/styles/`
+ - Implement responsive layouts and component styling
+ - Follow BEM or project-specific naming conventions
+ - Optimize CSS for production builds
+
+3. **Hugo Data Integration**
+ - Access data from `data/` directory safely
+ - Pass data to components via `data-*` attributes
+ - Handle YAML/JSON data files for dynamic content
+
+### Out of Scope (Use ts-component-dev agent instead)
+
+- TypeScript/JavaScript component implementation
+- Event handlers and user interaction logic
+- State management and DOM manipulation
+- Component registry and initialization
+
+## Critical Testing Requirement
+
+**Hugo's `npx hugo --quiet` only validates template syntax, not runtime execution.**
+
+Template errors like accessing undefined fields, nil values, or incorrect type assertions only appear when Hugo actually renders pages.
+
+### Mandatory Testing Protocol
+
+After modifying any file in `layouts/`:
+
+```bash
+# Step 1: Start Hugo server and check for errors
+npx hugo server --port 1314 2>&1 | head -50
+```
+
+**Success criteria:**
+
+- No `error calling partial` messages
+- No `can't evaluate field` errors
+- No `template: ... failed` messages
+- Server shows "Web Server is available at "
+
+```bash
+# Step 2: Verify the page renders
+curl -s -o /dev/null -w "%{http_code}" http://localhost:1314/PATH/TO/PAGE/
+```
+
+```bash
+# Step 3: Stop the test server
+pkill -f "hugo server --port 1314"
+```
+
+### Quick Test Command
+
+```bash
+timeout 15 npx hugo server --port 1314 2>&1 | grep -E "(error|Error|ERROR|fail|FAIL)" | head -20; pkill -f "hugo server --port 1314" 2>/dev/null
+```
+
+If output is empty, no errors were detected.
+
+## Common Hugo Template Patterns
+
+### Safe Data Access
+
+**Wrong - direct hyphenated key access:**
+
+```go
+{{ .Site.Data.article-data.influxdb }}
+```
+
+**Correct - use index function:**
+
+```go
+{{ index .Site.Data "article-data" "influxdb" }}
+```
+
+### Safe Nested Access
+
+```go
+{{ $articleDataRoot := index .Site.Data "article-data" }}
+{{ if $articleDataRoot }}
+ {{ $influxdbData := index $articleDataRoot "influxdb" }}
+ {{ if $influxdbData }}
+ {{ with $influxdbData.articles }}
+ {{/* Safe to use . here */}}
+ {{ end }}
+ {{ end }}
+{{ end }}
+```
+
+### Safe Field Access with isset
+
+```go
+{{ if and $data (isset $data "field") }}
+ {{ index $data "field" }}
+{{ end }}
+```
+
+### Iterating Safely
+
+```go
+{{ range $idx, $item := $articles }}
+ {{ $path := "" }}
+ {{ if isset $item "path" }}
+ {{ $path = index $item "path" }}
+ {{ end }}
+ {{ if $path }}
+ {{/* Now safe to use $path */}}
+ {{ end }}
+{{ end }}
+```
+
+## Template-to-TypeScript Communication
+
+Pass data via `data-*` attributes - **never use inline JavaScript**:
+
+**Template:**
+
+```html
+
+ {{/* HTML structure only - no onclick handlers */}}
+
+```
+
+The TypeScript component (handled by ts-component-dev agent) will read these attributes.
+
+## File Organization
+
+```
+layouts/
+├── _default/ # Default templates
+├── partials/ # Reusable template fragments
+│ └── api/ # API-specific partials
+├── shortcodes/ # Content shortcodes
+└── TYPE/ # Type-specific templates
+ └── single.html # Single page template
+
+assets/styles/
+├── styles-default.scss # Main stylesheet
+└── layouts/
+ └── _api-layout.scss # Layout-specific styles
+```
+
+### Partial Naming
+
+- Use descriptive names: `api/sidebar-nav.html`, not `nav.html`
+- Group related partials in subdirectories
+- Include comments at the top describing purpose and required context
+
+## Debugging Templates
+
+### Print Variables for Debugging
+
+```go
+{{/* Temporary debugging - REMOVE before committing */}}
+
{{ printf "%#v" $myVariable }}
+```
+
+### Enable Verbose Mode
+
+```bash
+npx hugo server --port 1314 --verbose 2>&1 | head -100
+```
+
+### Check Data File Loading
+
+```bash
+cat data/article-data/influxdb/influxdb3-core/articles.yml | head -20
+```
+
+## SASS/CSS Guidelines
+
+### File Organization
+
+- Component styles in `assets/styles/layouts/`
+- Use SASS variables from existing theme
+- Follow mobile-first responsive design
+
+### Naming Conventions
+
+- Use BEM or project conventions
+- Prefix component styles (e.g., `.api-nav`, `.api-toc`)
+- Use state classes: `.is-active`, `.is-open`, `.is-hidden`
+
+### Common Patterns
+
+```scss
+// Component container
+.api-nav {
+ // Base styles
+
+ &-group-header {
+ // Child element
+ }
+
+ &.is-open {
+ // State modifier
+ }
+}
+```
+
+## Workflow
+
+1. **Understand Requirements**
+ - What page type or layout is being modified?
+ - What data does the template need?
+ - Does this require styling changes?
+
+2. **Implement Template**
+ - Use safe data access patterns
+ - Add `data-component` attributes for interactive elements
+ - Do not add inline JavaScript
+
+3. **Add Styling**
+ - Create/modify SCSS files as needed
+ - Follow existing patterns and variables
+
+4. **Test Runtime**
+ - Run Hugo server (not just build)
+ - Verify page renders without errors
+ - Check styling in browser
+
+5. **Clean Up**
+ - Remove debug statements
+ - Stop test server
+
+## Quality Checklist
+
+Before considering template work complete:
+
+- [ ] No inline `
+```
+
+**Correct - Clean separation:**
+
+Template (`layouts/partials/api/sidebar-nav.html`):
+
+```html
+
+```
+
+TypeScript (`assets/js/components/api-nav.ts`):
+
+```typescript
+interface ApiNavOptions {
+ component: HTMLElement;
+}
+
+export default function initApiNav({ component }: ApiNavOptions): void {
+ const headers = component.querySelectorAll('.api-nav-group-header');
+
+ headers.forEach((header) => {
+ header.addEventListener('click', () => {
+ const isOpen = header.classList.toggle('is-open');
+ header.setAttribute('aria-expanded', String(isOpen));
+ header.nextElementSibling?.classList.toggle('is-open', isOpen);
+ });
+ });
+}
+```
+
+Register in `main.js`:
+
+```javascript
+import initApiNav from './components/api-nav.js';
+
+const componentRegistry = {
+ 'api-nav': initApiNav,
+ // ... other components
+};
+```
+
+### Data Passing Pattern
+
+Pass Hugo data to TypeScript via `data-*` attributes:
+
+Template:
+
+```html
+
+
+```
+
+TypeScript:
+
+```typescript
+interface TocOptions {
+ component: HTMLElement;
+}
+
+interface TocData {
+ headings: string[];
+ scrollOffset: number;
+}
+
+function parseData(component: HTMLElement): TocData {
+ const headingsRaw = component.dataset.headings;
+ const headings = headingsRaw ? JSON.parse(headingsRaw) : [];
+ const scrollOffset = parseInt(component.dataset.scrollOffset || '0', 10);
+
+ return { headings, scrollOffset };
+}
+
+export default function initApiToc({ component }: TocOptions): void {
+ const data = parseData(component);
+ // Use data.headings and data.scrollOffset
+}
+```
+
+### Minimal Inline Scripts (Exception)
+
+The **only** acceptable inline scripts are minimal initialization that MUST run before component registration:
+
+```html
+{{/* Acceptable: Critical path, no logic, runs immediately */}}
+
+```
+
+Everything else belongs in `assets/js/`.
+
+### File Organization for Components
+
+```
+assets/
+├── js/
+│ ├── main.js # Entry point, component registry
+│ ├── components/
+│ │ ├── api-nav.ts # API navigation behavior
+│ │ ├── api-toc.ts # Table of contents
+│ │ ├── api-tabs.ts # Tab switching (if needed beyond CSS)
+│ │ └── api-scalar.ts # Scalar/RapiDoc integration
+│ └── utils/
+│ └── dom-helpers.ts # Shared DOM utilities
+└── styles/
+ └── layouts/
+ └── _api-layout.scss # API-specific styles
+```
+
+### TypeScript Component Checklist
+
+When creating a new interactive feature:
+
+1. [ ] Create TypeScript file in `assets/js/components/`
+2. [ ] Define interface for component options
+3. [ ] Export default initializer function
+4. [ ] Register in `main.js` componentRegistry
+5. [ ] Add `data-component` attribute to HTML element
+6. [ ] Pass data via `data-*` attributes (not inline JS)
+7. [ ] Write Cypress tests for the component
+8. [ ] **NO inline `
+
+
+```
+
+**Step 2: Verify the inline script is removed**
+
+Run: `grep -c "
+
+
diff --git a/layouts/partials/api/renderer.html b/layouts/partials/api/renderer.html
new file mode 100644
index 0000000000..de3dfe9389
--- /dev/null
+++ b/layouts/partials/api/renderer.html
@@ -0,0 +1,10 @@
+{{/*
+ API Renderer
+
+ Renders API documentation using RapiDoc.
+
+ Required page params:
+ - staticFilePath: Path to the OpenAPI specification file
+*/}}
+
+{{ partial "api/rapidoc.html" . }}
diff --git a/layouts/partials/api/section-children.html b/layouts/partials/api/section-children.html
new file mode 100644
index 0000000000..a381e8d091
--- /dev/null
+++ b/layouts/partials/api/section-children.html
@@ -0,0 +1,87 @@
+{{/*
+ API Section Children
+
+ Renders tag pages from article data as a children list.
+ Sort order: conceptual tags (traitTags) first, then other tags alphabetically.
+
+ Uses data from:
+ - data/article_data/influxdb/{product}/articles.yml
+*/}}
+
+{{ $currentPage := . }}
+
+{{/* Extract product and version from URL */}}
+{{ $productPathData := findRE "[^/]+.*?" .RelPermalink }}
+{{ $product := index $productPathData 0 }}
+{{ $version := index $productPathData 1 }}
+
+{{/* Build data key for article data lookup */}}
+{{ $dataKey := "" }}
+{{ if eq $product "influxdb3" }}
+ {{ $dataKey = print "influxdb3_" $version }}
+{{ else if eq $product "influxdb" }}
+ {{ $dataKey = print $version }}
+{{ else }}
+ {{ $dataKey = $product }}
+{{ end }}
+
+{{/* Get article data for this product */}}
+{{ $articles := slice }}
+{{ with site.Data.article_data }}
+ {{ with index . "influxdb" }}
+ {{ with index . $dataKey }}
+ {{ with index . "articles" }}
+ {{ with .articles }}
+ {{ $articles = . }}
+ {{ end }}
+ {{ end }}
+ {{ end }}
+ {{ end }}
+{{ end }}
+
+{{ if gt (len $articles) 0 }}
+ {{/* Separate conceptual (traitTag) and non-conceptual articles */}}
+ {{ $conceptualArticles := slice }}
+ {{ $operationArticles := slice }}
+
+ {{ range $articles }}
+ {{ if and (reflect.IsMap .) (isset . "fields") }}
+ {{ $fields := index . "fields" }}
+ {{ if reflect.IsMap $fields }}
+ {{ $isConceptual := false }}
+ {{ if isset $fields "isConceptual" }}
+ {{ $isConceptual = index $fields "isConceptual" }}
+ {{ end }}
+ {{ if $isConceptual }}
+ {{ $conceptualArticles = $conceptualArticles | append . }}
+ {{ else }}
+ {{ $operationArticles = $operationArticles | append . }}
+ {{ end }}
+ {{ end }}
+ {{ end }}
+ {{ end }}
+
+ {{/* Sort each group alphabetically by tag name */}}
+ {{ $conceptualArticles = sort $conceptualArticles "fields.tag" }}
+ {{ $operationArticles = sort $operationArticles "fields.tag" }}
+
+ {{/* Combine: conceptual first, then operations */}}
+ {{ $sortedArticles := $conceptualArticles | append $operationArticles }}
+
+
+ {{ range $sortedArticles }}
+ {{ $path := index . "path" }}
+ {{ $fields := index . "fields" }}
+ {{ $tag := index $fields "tag" }}
+ {{ $description := index $fields "description" | default "" }}
+ {{ $tagPageUrl := print "/" $product "/" $version "/" $path "/" | relURL }}
+
+