diff --git a/.ci/vale/styles/Google/Quotes.yml b/.ci/vale/styles/Google/Quotes.yml index 3cb6f1abd..e5260263a 100644 --- a/.ci/vale/styles/Google/Quotes.yml +++ b/.ci/vale/styles/Google/Quotes.yml @@ -1,7 +1,8 @@ extends: existence -message: "Commas and periods go inside quotation marks." +message: "Commas and periods go inside quotation marks (unless in code examples or technical values)." link: 'https://developers.google.com/style/quotation-marks' -level: error +# Changed to warning due to false positives with code examples +level: warning nonword: true tokens: - '"[^"]+"[.,?]' diff --git a/.ci/vale/styles/config/vocabularies/InfluxDataDocs/accept.txt b/.ci/vale/styles/config/vocabularies/InfluxDataDocs/accept.txt index e9f7aa19a..7f61bcf0a 100644 --- a/.ci/vale/styles/config/vocabularies/InfluxDataDocs/accept.txt +++ b/.ci/vale/styles/config/vocabularies/InfluxDataDocs/accept.txt @@ -42,7 +42,7 @@ System.Data.Odbc TBs? \bUI\b URL -\w*-?\w*url\w*-\w* +(?i)\w*-?\w*url\w*-\w* US (East|West|Central|North|South|Northeast|Northwest|Southeast|Southwest) Unix WALs? diff --git a/.circleci/config.yml b/.circleci/config.yml index 6636a0370..22fda0c22 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,6 +42,16 @@ jobs: - run: name: Hugo Build command: yarn hugo --environment production --logLevel info --gc --destination workspace/public + - run: + name: Generate LLM-friendly Markdown + command: | + if [ "$CIRCLE_BRANCH" = "master" ]; then + # Full build for production deployments + yarn build:md --public-dir workspace/public + else + # Incremental build for PRs - only process changed files + yarn build:md --public-dir workspace/public --only-changed --base-branch origin/master + fi - persist_to_workspace: root: workspace paths: diff --git a/.claude/agents/hugo-ui-dev.md b/.claude/agents/hugo-ui-dev.md new file mode 100644 index 000000000..e1e8a9de5 --- /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 `