From ed65fb4bee08d0f2292fa0ef7468561bc8448e9a Mon Sep 17 00:00:00 2001 From: Jason Stirnaman Date: Wed, 31 Dec 2025 13:21:15 -0600 Subject: [PATCH] chore: remove design files --- ...12-10-standalone-operation-pages-design.md | 181 ---- .../plans/2024-12-12-api-code-review-fixes.md | 779 ------------------ .../2025-01-10-docs-cli-workflow-design.md | 134 --- 3 files changed, 1094 deletions(-) delete mode 100644 docs/plans/2024-12-10-standalone-operation-pages-design.md delete mode 100644 docs/plans/2024-12-12-api-code-review-fixes.md delete mode 100644 docs/plans/2025-01-10-docs-cli-workflow-design.md diff --git a/docs/plans/2024-12-10-standalone-operation-pages-design.md b/docs/plans/2024-12-10-standalone-operation-pages-design.md deleted file mode 100644 index 54d084ddc..000000000 --- a/docs/plans/2024-12-10-standalone-operation-pages-design.md +++ /dev/null @@ -1,181 +0,0 @@ -# Standalone API Operation Pages Design - -## Overview - -Create individual pages for each API operation with path-based URLs, rendered using RapiDoc Mini with existing tag-level OpenAPI specs. - -## Goals - -- **SEO/discoverability**: Each operation indexable with its own URL and metadata -- **Deep linking**: Reliable bookmarkable/shareable URLs for specific operations -- **Navigation UX**: Sidebar links navigate to actual pages (not hash fragments) -- **Content customization**: Foundation for adding operation-specific guides and examples - -## URL Structure - -Path-based URLs with HTTP method as the final segment: - -| Operation | API Path | Page URL | -| ------------------ | ----------------------------------- | ------------------------------------ | -| PostV1Write | `POST /write` | `/api/write/post/` | -| PostV2Write | `POST /api/v2/write` | `/api/v2/write/post/` | -| PostWriteLP | `POST /api/v3/write_lp` | `/api/v3/write_lp/post/` | -| GetV1ExecuteQuery | `GET /query` | `/api/query/get/` | -| PostExecuteV1Query | `POST /query` | `/api/query/post/` | -| GetExecuteQuerySQL | `GET /api/v3/query_sql` | `/api/v3/query_sql/get/` | -| GetDatabases | `GET /api/v3/configure/database` | `/api/v3/configure/database/get/` | -| DeleteDatabase | `DELETE /api/v3/configure/database` | `/api/v3/configure/database/delete/` | - -## Architecture - -### Existing Components (unchanged) - -- **Tag pages**: `/api/write-data/`, `/api/query-data/` etc. remain as landing pages -- **Tag-level specs**: `static/openapi/influxdb-{product}/tags/tags/ref-{tag}.yaml` (\~30-50KB each) -- **Sidebar structure**: Tag-based groups with operation summaries as link text - -### New Components - -1. **Operation page content files**: Generated at path-based locations -2. **Operation page template**: Hugo layout using RapiDoc Mini -3. **Updated sidebar links**: Point to path-based URLs instead of hash fragments - -## Content File Structure - -Generated operation pages at `content/influxdb3/{product}/api/{path}/{method}/_index.md`: - -```yaml ---- -title: Write line protocol (v1-compatible) -description: Write data using InfluxDB v1-compatible line protocol endpoint -type: api-operation -layout: operation -# RapiDoc Mini configuration -specFile: /openapi/influxdb-influxdb3_core/tags/tags/ref-write-data.yaml -matchPaths: post /write -# Operation metadata -operationId: PostV1Write -method: POST -apiPath: /write -tag: Write data -compatVersion: v1 -# Links -related: - - /influxdb3/core/write-data/http-api/compatibility-apis/ ---- -``` - -## Hugo Template - -New layout `layouts/api-operation/operation.html`: - -```html -{{ define "main" }} -
-
-

{{ .Title }}

-
- {{ .Params.method }} - {{ .Params.apiPath }} - {{ with .Params.compatVersion }} - {{ . }} - {{ end }} -
-
- - - - - {{ with .Params.related }} - - {{ end }} -
-{{ end }} -``` - -## Sidebar Navigation Changes - -Update `layouts/partials/sidebar/api-menu-items.html` to generate path-based URLs: - -**Before:** - -```go -{{ $fragment := printf "#operation/%s" .operationId }} -{{ $fullUrl := printf "%s%s" $tagPageUrl $fragment }} -``` - -**After:** - -```go -{{ $apiPath := .path }} -{{ $method := lower .method }} -{{ $pathSlug := $apiPath | replaceRE "^/" "" }} -{{ $operationUrl := printf "/%s/%s/api/%s/%s/" $product $version $pathSlug $method | relURL }} -``` - -## Generator Changes - -Update `api-docs/scripts/openapi-paths-to-hugo-data/index.ts`: - -1. Add new function `generateOperationPages()` that creates content files for each operation -2. Include operation metadata: specFile path, matchPaths filter, tag association -3. Call from `generateHugoDataByTag()` after generating tag-based articles - -## File Generation Summary - -For InfluxDB 3 Core (\~43 operations), this creates: - -- \~43 new content files at `content/influxdb3/core/api/{path}/{method}/_index.md` -- No new spec files (reuses existing tag-level specs) - -## Data Flow - -``` -OpenAPI Spec - ↓ -Generator extracts operations - ↓ -Creates content files with frontmatter (specFile, matchPaths, metadata) - ↓ -Hugo builds pages using api-operation/operation.html template - ↓ -RapiDoc Mini loads tag-level spec, filters to single operation client-side -``` - -## Testing Plan - -1. Generate operation pages for Core product -2. Verify URLs resolve correctly -3. Verify RapiDoc Mini renders single operation -4. Verify sidebar links navigate to operation pages -5. Test deep linking (direct URL access) -6. Check page titles and meta descriptions for SEO - -## Future Improvements - -- Generate operation-level specs for smaller payloads (if performance issues arise) -- Add custom content sections per operation -- Implement operation search/filtering on tag pages - -## Migration Notes - -When migrating other product specs from Redoc to RapiDoc: - -1. **Remove `x-tagGroups`**: This is a Redoc-specific extension for sidebar navigation grouping. RapiDoc doesn't use it. The Hugo sidebar uses `data/api_nav_groups.yml` instead. - -2. **Ensure tag consistency**: The sidebar navigation (`api_nav_groups.yml`) must match the tag names in the spec's `tags` section exactly. - -3. **Single-tag operations**: Operations should ideally have a single tag to avoid duplicate rendering. If an operation has multiple tags, the generator restricts it to the primary tag in tag-specific specs. diff --git a/docs/plans/2024-12-12-api-code-review-fixes.md b/docs/plans/2024-12-12-api-code-review-fixes.md deleted file mode 100644 index 6360c9f69..000000000 --- a/docs/plans/2024-12-12-api-code-review-fixes.md +++ /dev/null @@ -1,779 +0,0 @@ -# API Code Review Fixes Implementation Plan - -> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. - -**Goal:** Fix code review violations by extracting inline JavaScript from rapidoc.html into a TypeScript component and removing unused Scalar renderer code. - -**Architecture:** Create a new `api-rapidoc.ts` TypeScript component following the established component pattern (same as `rapidoc-mini.ts`). The component handles theme synchronization, shadow DOM manipulation, and MutationObserver setup. Remove the Scalar renderer, api-tabs component, and associated partials since they're no longer used. - -**Tech Stack:** TypeScript, Hugo templates, SCSS, Cypress - -*** - -## Task 1: Create api-rapidoc.ts TypeScript Component - -**Files:** - -- Create: `assets/js/components/api-rapidoc.ts` - -**Step 1: Create the TypeScript component file** - -Create `assets/js/components/api-rapidoc.ts` with the following content: - -```typescript -/** - * RapiDoc API Documentation Component - * - * Initializes the full RapiDoc renderer with theme synchronization. - * This is the component version of the inline JavaScript from rapidoc.html. - * - * Features: - * - Theme detection from Hugo's stylesheet toggle system - * - Automatic theme synchronization when user toggles dark/light mode - * - Shadow DOM manipulation to hide unwanted UI elements - * - CSS custom property injection for styling - * - * Usage: - *
- * - * The component expects a element to already exist in the container - * (created by Hugo template) or will wait for it to be added. - */ - -import { getPreference } from '../services/local-storage.js'; - -interface ComponentOptions { - component: HTMLElement; -} - -interface ThemeColors { - theme: 'light' | 'dark'; - bgColor: string; - textColor: string; - headerColor: string; - primaryColor: string; - navBgColor: string; - navTextColor: string; - navHoverBgColor: string; - navHoverTextColor: string; - navAccentColor: string; - codeTheme: string; -} - -type CleanupFn = () => void; - -/** - * Get current theme from localStorage (source of truth for Hugo theme system) - */ -function getTheme(): 'dark' | 'light' { - const theme = getPreference('theme'); - return theme === 'dark' ? 'dark' : 'light'; -} - -/** - * Get theme colors matching Hugo SCSS variables - */ -function getThemeColors(isDark: boolean): ThemeColors { - if (isDark) { - return { - theme: 'dark', - bgColor: '#14141F', // $grey10 ($article-bg in dark theme) - textColor: '#D4D7DD', // $g15-platinum - headerColor: '#D4D7DD', - primaryColor: '#a0a0ff', - navBgColor: '#1a1a2a', - navTextColor: '#D4D7DD', - navHoverBgColor: '#252535', - navHoverTextColor: '#ffffff', - navAccentColor: '#a0a0ff', - codeTheme: 'monokai', - }; - } - - return { - theme: 'light', - bgColor: '#ffffff', // $g20-white - textColor: '#2b2b2b', - headerColor: '#020a47', // $br-dark-blue - primaryColor: '#020a47', - navBgColor: '#f7f8fa', - navTextColor: '#2b2b2b', - navHoverBgColor: '#e8e8f0', - navHoverTextColor: '#020a47', - navAccentColor: '#020a47', - codeTheme: 'prism', - }; -} - -/** - * Apply theme to RapiDoc element - */ -function applyTheme(rapiDoc: HTMLElement): void { - const isDark = getTheme() === 'dark'; - const colors = getThemeColors(isDark); - - rapiDoc.setAttribute('theme', colors.theme); - rapiDoc.setAttribute('bg-color', colors.bgColor); - rapiDoc.setAttribute('text-color', colors.textColor); - rapiDoc.setAttribute('header-color', colors.headerColor); - rapiDoc.setAttribute('primary-color', colors.primaryColor); - rapiDoc.setAttribute('nav-bg-color', colors.navBgColor); - rapiDoc.setAttribute('nav-text-color', colors.navTextColor); - rapiDoc.setAttribute('nav-hover-bg-color', colors.navHoverBgColor); - rapiDoc.setAttribute('nav-hover-text-color', colors.navHoverTextColor); - rapiDoc.setAttribute('nav-accent-color', colors.navAccentColor); - rapiDoc.setAttribute('code-theme', colors.codeTheme); -} - -/** - * Set custom CSS properties on RapiDoc element - */ -function setInputBorderStyles(rapiDoc: HTMLElement): void { - rapiDoc.style.setProperty('--border-color', '#00A3FF'); -} - -/** - * Hide unwanted elements in RapiDoc shadow DOM - */ -function hideExpandCollapseControls(rapiDoc: HTMLElement): void { - const maxAttempts = 10; - let attempts = 0; - - const tryHide = (): void => { - attempts++; - - try { - const shadowRoot = rapiDoc.shadowRoot; - if (!shadowRoot) { - if (attempts < maxAttempts) { - setTimeout(tryHide, 500); - } - return; - } - - // Find all elements and hide those containing "Expand all" / "Collapse all" - const allElements = shadowRoot.querySelectorAll('*'); - let hiddenCount = 0; - - allElements.forEach((element) => { - const text = element.textContent || ''; - - if (text.includes('Expand all') || text.includes('Collapse all')) { - (element as HTMLElement).style.display = 'none'; - if (element.parentElement) { - element.parentElement.style.display = 'none'; - } - hiddenCount++; - } - }); - - // Hide "Overview" headings - const headings = shadowRoot.querySelectorAll('h1, h2, h3, h4'); - headings.forEach((heading) => { - const text = (heading.textContent || '').trim(); - if (text.includes('Overview')) { - (heading as HTMLElement).style.display = 'none'; - hiddenCount++; - } - }); - - // Inject CSS as backup - const style = document.createElement('style'); - style.textContent = ` - .section-gap.section-tag, - [id*="overview"], - .regular-font.section-gap:empty, - h1:empty, h2:empty, h3:empty { - display: none !important; - } - `; - shadowRoot.appendChild(style); - - if (hiddenCount === 0 && attempts < maxAttempts) { - setTimeout(tryHide, 500); - } - } catch (e) { - if (attempts < maxAttempts) { - setTimeout(tryHide, 500); - } - } - }; - - setTimeout(tryHide, 500); -} - -/** - * Watch for theme changes via stylesheet toggle - */ -function watchThemeChanges(rapiDoc: HTMLElement): CleanupFn { - const handleThemeChange = (): void => { - applyTheme(rapiDoc); - }; - - // Watch stylesheet disabled attribute changes (Hugo theme.js toggles this) - const observer = new MutationObserver((mutations) => { - for (const mutation of mutations) { - if ( - mutation.type === 'attributes' && - mutation.target instanceof HTMLLinkElement && - mutation.target.title?.includes('theme') - ) { - handleThemeChange(); - break; - } - // Also watch data-theme changes as fallback - if (mutation.attributeName === 'data-theme') { - handleThemeChange(); - } - } - }); - - // Observe head for stylesheet changes - observer.observe(document.head, { - attributes: true, - attributeFilter: ['disabled'], - subtree: true, - }); - - // Observe documentElement for data-theme changes - observer.observe(document.documentElement, { - attributes: true, - attributeFilter: ['data-theme'], - }); - - return (): void => { - observer.disconnect(); - }; -} - -/** - * Initialize RapiDoc component - */ -export default function ApiRapiDoc({ - component, -}: ComponentOptions): CleanupFn | void { - // Find the rapi-doc element inside the container - const rapiDoc = component.querySelector('rapi-doc') as HTMLElement | null; - - if (!rapiDoc) { - console.warn('[API RapiDoc] No rapi-doc element found in container'); - return; - } - - // Apply initial theme - applyTheme(rapiDoc); - - // Set custom CSS properties - if (customElements && customElements.whenDefined) { - customElements.whenDefined('rapi-doc').then(() => { - setInputBorderStyles(rapiDoc); - setTimeout(() => setInputBorderStyles(rapiDoc), 500); - }); - } else { - setInputBorderStyles(rapiDoc); - setTimeout(() => setInputBorderStyles(rapiDoc), 500); - } - - // Hide unwanted UI elements - hideExpandCollapseControls(rapiDoc); - - // Watch for theme changes - return watchThemeChanges(rapiDoc); -} -``` - -**Step 2: Verify the file was created correctly** - -Run: `head -30 assets/js/components/api-rapidoc.ts` -Expected: File header and imports visible - -**Step 3: Commit** - -```bash -git add assets/js/components/api-rapidoc.ts -git commit -m "feat(api): Create api-rapidoc TypeScript component - -Extract inline JavaScript from rapidoc.html into a proper TypeScript -component following the established component pattern." -``` - -*** - -## Task 2: Register api-rapidoc Component in main.js - -**Files:** - -- Modify: `assets/js/main.js:49-88` - -**Step 1: Add import for ApiRapiDoc** - -Add this import after line 52 (after RapiDocMini import): - -```javascript -import ApiRapiDoc from './components/api-rapidoc.ts'; -``` - -**Step 2: Register component in componentRegistry** - -Add this entry in the componentRegistry object (after line 87, the 'rapidoc-mini' entry): - -```javascript - 'api-rapidoc': ApiRapiDoc, -``` - -**Step 3: Verify changes** - -Run: `grep -n "api-rapidoc\|ApiRapiDoc" assets/js/main.js` -Expected: Both the import and registry entry appear - -**Step 4: Commit** - -```bash -git add assets/js/main.js -git commit -m "feat(api): Register api-rapidoc component in main.js" -``` - -*** - -## Task 3: Update rapidoc.html to Use Component Pattern - -**Files:** - -- Modify: `layouts/partials/api/rapidoc.html` - -**Step 1: Replace inline JavaScript with data-component attribute** - -Replace the entire content of `layouts/partials/api/rapidoc.html` with: - -```html -{{/* - RapiDoc API Documentation Renderer - - Primary API documentation renderer using RapiDoc with "Mix your own HTML" slots. - See: https://rapidocweb.com/examples.html - - Required page params: - - staticFilePath: Path to the OpenAPI specification file - - Optional page params: - - operationId: Specific operation to display (renders only that operation) - - tag: Tag to filter operations by - - RapiDoc slots available for custom content: - - slot="header" - Custom header - - slot="footer" - Custom footer - - slot="overview" - Custom overview content - - slot="auth" - Custom authentication section - - slot="nav-logo" - Custom navigation logo -*/}} - -{{ $specPath := .Params.staticFilePath }} -{{ $specPathJSON := replace $specPath ".yaml" ".json" | replace ".yml" ".json" }} -{{ $operationId := .Params.operationId | default "" }} -{{ $tag := .Params.tag | default "" }} - -{{/* Machine-readable links for AI agent discovery */}} -{{ if $specPath }} - - -{{ end }} - -
- {{/* RapiDoc component with slot-based customization */}} - - {{/* Custom overview slot - Hugo page content */}} - {{ with .Content }} -
- {{ . }} -
- {{ end }} - - {{/* Custom examples from frontmatter */}} - {{ with .Params.examples }} -
-

Examples

- {{ range . }} -
-

{{ .title }}

- {{ with .description }}

{{ . | markdownify }}

{{ end }} -
{{ .code }}
-
- {{ end }} -
- {{ end }} -
-
- -{{/* Load RapiDoc from CDN */}} - - - -``` - -**Step 2: Verify the inline script is removed** - -Run: `grep -c "