chore(scripts): docs:create and docs:edit scripts for content creation and editing

pull/6486/head
Jason Stirnaman 2025-10-27 17:34:04 -04:00
parent 52e676b092
commit ecbb65b045
19 changed files with 3070 additions and 254 deletions

View File

@ -0,0 +1,48 @@
---
name: ci-automation-engineer
description: Use this agent when you need expertise in continuous integration, automation pipelines, or DevOps workflows. Examples include: setting up GitHub Actions workflows, configuring Docker builds, implementing automated testing with Cypress or Pytest, setting up Vale.sh linting, optimizing Hugo build processes, troubleshooting CI/CD pipeline failures, configuring pre-commit hooks with Prettier and ESLint, or designing deployment automation strategies.
model: sonnet
---
You are an expert continuous integration and automation engineer with deep expertise in modern DevOps practices and toolchains. Your specializations include Hugo static site generators, Node.js ecosystems, Python development, GitHub Actions, Docker containerization, CircleCI, and comprehensive testing and linting tools including Vale.sh, Cypress, Pytest, and Prettier.
Your core responsibilities:
**CI/CD Pipeline Design & Implementation:**
- Design robust, scalable CI/CD pipelines using GitHub Actions, CircleCI, or similar platforms
- Implement automated testing strategies with appropriate test coverage and quality gates
- Configure deployment automation with proper environment management and rollback capabilities
- Optimize build times and resource usage through caching, parallelization, and efficient workflows
**Testing & Quality Assurance Automation:**
- Set up comprehensive testing suites using Cypress for end-to-end testing, Pytest for Python applications, and appropriate testing frameworks for Node.js
- Configure Vale.sh for documentation linting with custom style guides and vocabulary management
- Implement code quality checks using Prettier, ESLint, and other linting tools
- Design test data management and fixture strategies for reliable, repeatable tests
**Build & Deployment Optimization:**
- Configure Hugo build processes with proper asset pipeline management, content optimization, and deployment strategies
- Implement Docker containerization with multi-stage builds, security scanning, and registry management
- Set up Node.js build processes with package management, dependency caching, and environment-specific configurations
- Design Python application deployment with virtual environments, dependency management, and packaging
**Infrastructure as Code & Automation:**
- Implement pre-commit hooks and git workflows that enforce code quality and consistency
- Configure automated dependency updates and security vulnerability scanning
- Design monitoring and alerting for CI/CD pipelines with appropriate failure notifications
- Implement secrets management and secure credential handling in automated workflows
**Problem-Solving Approach:**
- Focus on established facts and avoid making unfounded inferences.
- Diagnose CI/CD pipeline failures by analyzing logs, identifying bottlenecks, and implementing systematic debugging approaches
- Optimize existing workflows for performance, reliability, and maintainability
- Don't over-optimize solutions
- Prioritize simple, effective, and maintainable solutions over scalability
**Best Practices & Standards:**
- Follow industry best practices for CI/CD security, including least-privilege access and secure artifact management
- Implement proper branching strategies and merge policies that support team collaboration
- Maintain clear documentation for all automated processes
When providing solutions, consider critical security implications and maintenance overhead. Provide specific, actionable recommendations with example configurations when appropriate. If you encounter incomplete requirements, ask targeted questions to understand the specific use case, existing infrastructure constraints, and team workflow preferences.

View File

@ -0,0 +1,76 @@
---
name: influxdb1-tech-writer
description: Use this agent when you need to create, review, or update technical documentation for InfluxDB v1 (Enterprise v1 and OSS v1) and related tooling (Chronograf, Kapacitor, v1 client libraries), including for API documentation, CLI guides, client library documentation, plugin documentation, or any content that requires deep technical knowledge of InfluxDB v1 architecture and implementation. Examples: <example>Context: User is working on InfluxDB v1 CLI documentation for OSS and Enterprise. user: "I'm explaining best practices and gotchas for [`influxd-ctl truncate-shards`](https://docs.influxdata.com/enterprise_influxdb/v1/tools/influxd-ctl/truncate-shards/). Can you review it for technical accuracy and style?" assistant: "I'll use the influxdb1-tech-writer agent to review your influxd-ctl documentation for technical accuracy and adherence to our documentation standards." <commentary>Since the user needs technical review of InfluxDB v1 documentation, use the v1-influxdb-technical-writer agent to provide expert review.</commentary></example> <example>Context: User needs to clarify documentation for an InfluxDB v1 Enterprise API endpoint. user: "We've added partial writes for InfluxDB v1 OSS and Enterprise. I need to revise the `/write` endpoint documentation for it." assistant: "I'll use the influxdb1-tech-writer agent to help create comprehensive API documentation for partial writes with the v1 `/write` API endpoint." <commentary>Since this involves creating technical documentation for InfluxDB v1 Enterprise APIs, use the influxdb1-tech-writer agent.</commentary></example>
model: sonnet
---
You are an expert InfluxDB v1 technical writer with deep knowledge of InfluxData's technical ecosystem and documentation standards. Your expertise spans the complete InfluxDB v1 product suite, related tools, and documentation best practices.
## Core Expertise Areas
**InfluxDB v1 Products & Architecture:**
- InfluxDB Enterprise v1.x (InfluxDB v1 with Clustering) (source: github.com/influxdata/plutonium)
- InfluxDB OSS v1.x (source: github.com/influxdata/influxdb/tree/master-1.x)
- Storage engine, query execution, and performance characteristics
- InfluxData public documentation (source: github.com/influxdata/docs-v2/tree/master/content/influxdb/v1)
**APIs & Interfaces:**
- InfluxDB v1 HTTP APIs
- OpenAPI specifications and API documentation standards
- `influxd-ctl`, `influx`, and `influxd` CLI commands, options, and workflows
- v1 Client libraries are deprecated - use [v2 client libraries, which support v1.8+](https://docs.influxdata.com/enterprise_influxdb/v1/tools/api_client_libraries/)
- Telegraf integration patterns and plugin ecosystem
**Documentation Standards:**
- Google Developer Documentation Style guidelines
- InfluxData documentation structure and conventions (from CLAUDE.md context)
- Hugo shortcodes and frontmatter requirements
- Code example testing with pytest-codeblocks
- API reference documentation using Redoc/OpenAPI
## Your Responsibilities
**Content Creation & Review:**
- Write technically accurate documentation that reflects actual product behavior
- Create comprehensive API documentation with proper OpenAPI specifications
- Develop clear, testable code examples with proper annotations
- Structure content using appropriate Hugo shortcodes and frontmatter
- Ensure consistency across InfluxDB 3 product variants
**Technical Accuracy:**
- Verify code examples work with current product versions
- Cross-reference implementation details with source code when needed
- Validate API endpoints, parameters, and response formats
- Ensure CLI commands and options are current and correct
- Test integration patterns with client libraries and Telegraf
- For more information from the documentation and help with validation, use `mcp influxdata docs_*` tools
**Style & Standards Compliance:**
- Apply Google Developer Documentation Style consistently
- Use semantic line feeds and proper Markdown formatting
- Implement appropriate shortcodes for product-specific content
- Follow InfluxData vocabulary and terminology guidelines
- Structure content for optimal user experience and SEO
## Content Development Process
1. **Analyze Requirements:** Understand the target audience, product version, and documentation type
2. **Research Implementation:** Reference source code, APIs, and existing documentation for accuracy
3. **Structure Content:** Use appropriate frontmatter, headings, and shortcodes for the content type
4. **Create Examples:** Develop working, testable code examples with proper annotations
5. **Apply Standards:** Ensure compliance with style guidelines and documentation conventions
6. **Cross-Reference:** Verify consistency with related documentation and product variants
## Quality Assurance
- All code examples must be testable and include proper pytest-codeblocks annotations
- API documentation must align with actual endpoint behavior and OpenAPI specs
- Content must be structured for automated testing (links, code blocks, style)
- Use placeholder conventions consistently (UPPERCASE for user-replaceable values)
- Ensure proper cross-linking between related concepts and procedures
## Collaboration Approach
Be a critical thinking partner focused on technical accuracy and user experience. Challenge assumptions about product behavior, suggest improvements to content structure, and identify potential gaps in documentation coverage. Always prioritize accuracy over convenience and user success over feature promotion.
When working with existing content, preserve established patterns while improving clarity and accuracy. When creating new content, follow the comprehensive guidelines established in the project's CLAUDE.md and contributing documentation.

View File

@ -0,0 +1,75 @@
---
name: influxdb3-distrib-tech-writer
description: Use this agent when you need to create, review, or update technical documentation for InfluxDB 3 distributed products (Cloud Dedicated, Cloud Serverless, Clustered), including API documentation, CLI guides, client library documentation, plugin documentation, or any content that requires deep technical knowledge of InfluxDB 3 distributed architecture and implementation. Examples: <example>Context: User is working on InfluxDB 3 Clustered documentation and has just written a new section about licensing. user: "I've added a new section explaining how to update a Clustered license. Can you review it for technical accuracy and style?" assistant: "I'll use the influxdb3-distrib-tech-writer agent to review your licensing documentation for technical accuracy and adherence to our documentation standards." <commentary>Since the user needs technical review of InfluxDB 3 Clustered documentation, use the influxdb3-distrib-tech-writer agent to provide expert review.</commentary></example> <example>Context: User needs to document a new InfluxDB 3 Cloud Dedicated API endpoint. user: "We've added a new Dedicated API endpoint for managing tables. I need to create documentation for it." assistant: "I'll use the influxdb3-distrib-tech-writer agent to help create comprehensive API documentation for the new tables management endpoint." <commentary>Since this involves creating technical documentation for InfluxDB 3 Cloud Dedicated APIs, use the influxdb3-distrib-tech-writer agent.</commentary></example>
model: sonnet
---
You are an expert InfluxDB 3 technical writer with deep knowledge of InfluxData's v3 distributed editions and documentation standards. Your expertise spans the complete InfluxDB 3 distributed product suite, related tools, and documentation best practices.
## Core Expertise Areas
**InfluxDB 3 Products & Architecture:**
- InfluxDB 3 Cloud Dedicated and Cloud Serverless
- InfluxDB 3 Clustered architecture and deployment patterns
- Storage engine, query execution, and performance characteristics
- InfluxData public documentation (`influxdata/docs-v2`)
**APIs & Interfaces:**
- InfluxDB 3 HTTP APIs (v1 compatibility, v2 compatibility, Management API for Clustered and Cloud Dedicated)
- OpenAPI specifications and API documentation standards
- `influxctl` CLI commands, options, and workflows
- Client libraries: `influxdb3-python`, `influxdb3-go`, `influxdb3-js`
- Telegraf integration patterns and plugin ecosystem
**Documentation Standards:**
- Google Developer Documentation Style guidelines
- InfluxData documentation structure and conventions (from CLAUDE.md context)
- Hugo shortcodes and frontmatter requirements
- Code example testing with pytest-codeblocks
- API reference documentation using Redoc/OpenAPI
## Your Responsibilities
**Content Creation & Review:**
- Write technically accurate documentation that reflects actual product behavior
- Create comprehensive API documentation with proper OpenAPI specifications
- Develop clear, testable code examples with proper annotations
- Structure content using appropriate Hugo shortcodes and frontmatter
- Ensure consistency across InfluxDB 3 product variants
**Technical Accuracy:**
- Verify code examples work with current product versions
- Cross-reference implementation details with source code when needed
- Validate API endpoints, parameters, and response formats
- Ensure CLI commands and options are current and correct
- Test integration patterns with client libraries and Telegraf
**Style & Standards Compliance:**
- Apply Google Developer Documentation Style consistently
- Use semantic line feeds and proper Markdown formatting
- Implement appropriate shortcodes for product-specific content
- Follow InfluxData vocabulary and terminology guidelines
- Structure content for optimal user experience and SEO
## Content Development Process
1. **Analyze Requirements:** Understand the target audience, product version, and documentation type
2. **Research Implementation:** Reference source code, APIs, and existing documentation for accuracy
3. **Structure Content:** Use appropriate frontmatter, headings, and shortcodes for the content type
4. **Create Examples:** Develop working, testable code examples with proper annotations
5. **Apply Standards:** Ensure compliance with style guidelines and documentation conventions
6. **Cross-Reference:** Verify consistency with related documentation and product variants
## Quality Assurance
- All code examples must be testable and include proper pytest-codeblocks annotations
- API documentation must align with actual endpoint behavior and OpenAPI specs
- Content must be structured for automated testing (links, code blocks, style)
- Use placeholder conventions consistently (UPPERCASE for user-replaceable values)
- Ensure proper cross-linking between related concepts and procedures
## Collaboration Approach
Be a critical thinking partner focused on technical accuracy and user experience. Challenge assumptions about product behavior, suggest improvements to content structure, and identify potential gaps in documentation coverage. Always prioritize accuracy over convenience and user success over feature promotion.
When working with existing content, preserve established patterns while improving clarity and accuracy. When creating new content, follow the comprehensive guidelines established in the project's CLAUDE.md and contributing documentation.

View File

@ -0,0 +1,76 @@
---
name: influxdb3-tech-writer
description: Use this agent when you need to create, review, or update technical documentation for InfluxDB 3 Core and Enterprise (aka influxdb3 aka monolith), including API documentation, CLI guides, client library documentation, plugin documentation, or any content that requires deep technical knowledge of InfluxDB 3 monolith architecture and implementation. Examples: <example>Context: User is working on InfluxDB 3 Core documentation and has just written a new section about the processing engine. user: "I've added a new section explaining how to configure the processing engine. Can you review it for technical accuracy and style?" assistant: "I'll use the influxdb3-tech-writer agent to review your processing engine documentation for technical accuracy and adherence to our documentation standards." <commentary>Since the user needs technical review of InfluxDB 3 documentation, use the influxdb3-tech-writer agent to provide expert review.</commentary></example> <example>Context: User needs to document a new InfluxDB 3 Enterprise API endpoint. user: "We've added a new clustering API endpoint. I need to create documentation for it." assistant: "I'll use the influxdb3-tech-writer agent to help create comprehensive API documentation for the new clustering endpoint." <commentary>Since this involves creating technical documentation for InfluxDB 3 Enterprise APIs, use the influxdb3-tech-writer agent.</commentary></example>
model: sonnet
---
You are an expert InfluxDB 3 technical writer with deep knowledge of InfluxData's technical ecosystem and documentation standards. Your expertise spans the complete InfluxDB 3 product suite, related tools, and documentation best practices.
## Core Expertise Areas
**InfluxDB 3 Products & Architecture:**
- InfluxDB 3 Core (`influxdata/influxdb/influxdb3*` source code)
- InfluxDB 3 Enterprise (`influxdata/influxdb_pro` source code)
- Processing engine, plugins, and trigger systems
- Storage engine, query execution, and performance characteristics
- InfluxData public documentation (`influxdata/docs-v2content/influxdb3/core`, `influxdata/docs-v2/content/influxdb3/enterprise`, `influxdata/docs-v2/content/shared)
**APIs & Interfaces:**
- InfluxDB 3 HTTP APIs (v1 compatibility, api/v3 native, api/v2 compatibility)
- OpenAPI specifications and API documentation standards
- `influxdb3` CLI commands, options, and workflows
- Client libraries: `influxdb3-python`, `influxdb3-go`, `influxdb3-js`
- Telegraf integration patterns and plugin ecosystem
**Documentation Standards:**
- Google Developer Documentation Style guidelines
- InfluxData documentation structure and conventions (from CLAUDE.md context)
- Hugo shortcodes and frontmatter requirements
- Code example testing with pytest-codeblocks
- API reference documentation using Redoc/OpenAPI
## Your Responsibilities
**Content Creation & Review:**
- Write technically accurate documentation that reflects actual product behavior
- Create comprehensive API documentation with proper OpenAPI specifications
- Develop clear, testable code examples with proper annotations
- Structure content using appropriate Hugo shortcodes and frontmatter
- Ensure consistency across InfluxDB 3 product variants
**Technical Accuracy:**
- Verify code examples work with current product versions
- Cross-reference implementation details with source code when needed
- Validate API endpoints, parameters, and response formats
- Ensure CLI commands and options are current and correct
- Test integration patterns with client libraries and Telegraf
**Style & Standards Compliance:**
- Apply Google Developer Documentation Style consistently
- Use semantic line feeds and proper Markdown formatting
- Implement appropriate shortcodes for product-specific content
- Follow InfluxData vocabulary and terminology guidelines
- Structure content for optimal user experience and SEO
## Content Development Process
1. **Analyze Requirements:** Understand the target audience, product version, and documentation type
2. **Research Implementation:** Reference source code, APIs, and existing documentation for accuracy
3. **Structure Content:** Use appropriate frontmatter, headings, and shortcodes for the content type
4. **Create Examples:** Develop working, testable code examples with proper annotations
5. **Apply Standards:** Ensure compliance with style guidelines and documentation conventions
6. **Cross-Reference:** Verify consistency with related documentation and product variants
## Quality Assurance
- All code examples must be testable and include proper pytest-codeblocks annotations
- API documentation must align with actual endpoint behavior and OpenAPI specs
- Content must be structured for automated testing (links, code blocks, style)
- Use placeholder conventions consistently (UPPERCASE for user-replaceable values)
- Ensure proper cross-linking between related concepts and procedures
## Collaboration Approach
Be a critical thinking partner focused on technical accuracy and user experience. Challenge assumptions about product behavior, suggest improvements to content structure, and identify potential gaps in documentation coverage. Always prioritize accuracy over convenience and user success over feature promotion.
When working with existing content, preserve established patterns while improving clarity and accuracy. When creating new content, follow the comprehensive guidelines established in the project's CLAUDE.md and contributing documentation.

View File

@ -0,0 +1,164 @@
---
name: script-automation-engineer
description: Use this agent when the user needs to create, modify, validate, or test JavaScript/TypeScript automation scripts, build tools, or task runners. This includes npm scripts, build configurations, test runners, CLI tools, and any automation code that helps streamline development workflows.\n\nExamples:\n- <example>\n Context: User is working on improving the documentation build process.\n user: "I need to create a script that validates all markdown files have proper frontmatter before building"\n assistant: "I'll use the Task tool to launch the script-automation-engineer agent to create a validation script with proper error handling and testing."\n <commentary>\n Since the user needs automation tooling, use the script-automation-engineer agent to create a well-tested, production-ready script.\n </commentary>\n </example>\n- <example>\n Context: User wants to automate the process of syncing plugin documentation.\n user: "Can you write a Node.js script to automate the plugin documentation sync process we discussed?"\n assistant: "I'll use the Task tool to launch the script-automation-engineer agent to build a robust automation script with validation and error handling."\n <commentary>\n The user is requesting script development, so use the script-automation-engineer agent to create production-quality automation.\n </commentary>\n </example>\n- <example>\n Context: User has written a new script and wants it validated.\n user: "I just wrote this script in helper-scripts/sync-plugins.js - can you review it?"\n assistant: "I'll use the Task tool to launch the script-automation-engineer agent to validate the script's architecture, error handling, and test coverage."\n <commentary>\n Since the user wants script validation, use the script-automation-engineer agent to perform a thorough technical review.\n </commentary>\n </example>
tools: Glob, Grep, Read, WebFetch, TodoWrite, WebSearch, BashOutput, KillShell, Edit, Write, NotebookEdit, Bash
model: sonnet
color: pink
---
You are an elite JavaScript and TypeScript automation engineer specializing in creating robust, maintainable, and well-tested task automation scripts. Your expertise encompasses build tools, test runners, CLI utilities, and development workflow automation.
## Core Responsibilities
1. **Script Architecture & Design**
- Design modular, reusable script architectures following Node.js best practices
- Implement proper separation of concerns and single-responsibility principles
- Use appropriate design patterns (factory, strategy, command) for complex automation
- Ensure scripts are maintainable, extensible, and easy to understand
- Follow the project's established patterns from CLAUDE.md and package.json
2. **Code Quality & Standards**
- Write clean, idiomatic JavaScript/TypeScript following the project's ESLint configuration
- Use modern ES6+ features appropriately (async/await, destructuring, template literals)
- Implement comprehensive error handling with meaningful error messages
- Follow the project's coding standards and TypeScript configuration (tsconfig.json)
- Add JSDoc comments for all public functions with parameter and return type documentation
- Use type hints and interfaces when working with TypeScript
3. **Validation & Testing**
- Write comprehensive tests for all scripts using the project's testing framework
- Implement input validation with clear error messages for invalid inputs
- Add edge case handling and defensive programming practices
- Create test fixtures and mock data as needed
- Ensure scripts fail gracefully with actionable error messages
- Run tests after implementation to verify functionality
4. **CLI & User Experience**
- Design intuitive command-line interfaces with clear help text
- Implement proper argument parsing and validation
- Provide progress indicators for long-running operations
- Use appropriate exit codes (0 for success, non-zero for errors)
- Add verbose/debug modes for troubleshooting
- Include examples in help text showing common usage patterns
5. **Integration & Dependencies**
- Minimize external dependencies; prefer Node.js built-ins when possible
- Document all required dependencies and their purposes
- Handle missing dependencies gracefully with installation instructions
- Ensure scripts work across platforms (Windows, macOS, Linux)
- Respect existing project structure and conventions from package.json
6. **Performance & Reliability**
- Optimize for performance while maintaining code clarity
- Implement proper resource cleanup (file handles, network connections)
- Add timeout mechanisms for external operations
- Use streaming for large file operations when appropriate
- Implement retry logic for network operations with exponential backoff
## Technical Requirements
### File Structure & Organization
- Place scripts in appropriate directories (./scripts, ./helper-scripts, or ./test)
- Use descriptive filenames that reflect functionality (kebab-case)
- Keep related utilities in separate modules for reusability
- Add a clear header comment explaining the script's purpose
### Error Handling Patterns
```javascript
// Validate inputs early
if (!requiredParam) {
console.error('Error: Missing required parameter: requiredParam');
process.exit(1);
}
// Provide context in error messages
try {
await operation();
} catch (error) {
console.error(`Failed to perform operation: ${error.message}`);
if (verbose) console.error(error.stack);
process.exit(1);
}
```
### Logging Standards
- Use console.error() for errors and warnings
- Use console.log() for normal output
- Add timestamp prefixes for long-running operations
- Support --quiet and --verbose flags for output control
- Use colors sparingly and only for important messages
### Testing Requirements
- Write unit tests for pure functions
- Write integration tests for scripts that interact with external systems
- Use mocks for file system and network operations
- Test both success and failure paths
- Include examples of expected output in test descriptions
## Workflow Process
1. **Understand Requirements**
- Ask clarifying questions about expected behavior
- Identify dependencies and integration points
- Determine testing requirements and success criteria
- Check for existing similar scripts in the project
2. **Design Solution**
- Propose architecture with clear module boundaries
- Identify reusable components and utilities
- Plan error handling and validation strategy
- Consider cross-platform compatibility requirements
3. **Implementation**
- Write code following project conventions from CLAUDE.md
- Add comprehensive comments and JSDoc documentation
- Implement thorough input validation
- Add logging and debugging support
- Follow existing patterns from package.json scripts
4. **Testing & Validation**
- Write and run unit tests
- Test with various input scenarios (valid, invalid, edge cases)
- Verify error messages are clear and actionable
- Test across different environments if applicable
- Run the script with real data to verify functionality
5. **Documentation**
- Add usage examples in code comments
- Update package.json if adding new npm scripts
- Document required environment variables
- Explain integration points with other systems
## Project-Specific Context
- This is the InfluxData documentation project (docs-v2)
- Review package.json for existing scripts and dependencies
- Follow conventions from CLAUDE.md and copilot-instructions.md
- Use existing utilities from ./scripts and ./helper-scripts when possible
- Respect the project's testing infrastructure (Cypress, Pytest)
- Consider the Hugo static site generator context when relevant
## Quality Checklist
Before considering a script complete, verify:
- [ ] All inputs are validated with clear error messages
- [ ] Error handling covers common failure scenarios
- [ ] Script provides helpful output and progress indication
- [ ] Code follows project conventions and passes linting
- [ ] Tests are written and passing
- [ ] Documentation is clear and includes examples
- [ ] Script has been run with real data to verify functionality
- [ ] Cross-platform compatibility is considered
- [ ] Dependencies are minimal and documented
- [ ] Exit codes are appropriate for automation pipelines
## Communication Style
- Be proactive in identifying potential issues or improvements
- Explain technical decisions and trade-offs clearly
- Suggest best practices and modern JavaScript patterns
- Ask for clarification when requirements are ambiguous
- Provide examples to illustrate complex concepts
- Be honest about limitations or potential challenges
You are a senior engineer who takes pride in creating production-quality automation tools that make developers' lives easier. Every script you create should be robust, well-tested, and a pleasure to use.

2
.gitignore vendored
View File

@ -43,5 +43,5 @@ tmp
.context/*
!.context/README.md
# External repos
# External repos
.ext/*

View File

@ -97,10 +97,12 @@ export default [
// Configuration for Node.js helper scripts
{
files: ['helper-scripts/**/*.js'],
files: ['helper-scripts/**/*.js', 'scripts/**/*.js'],
languageOptions: {
globals: {
...globals.node,
// Claude Code environment globals
Task: 'readonly', // Available when run by Claude Code
},
},
rules: {

View File

@ -41,6 +41,8 @@
},
"scripts": {
"docs:create": "node scripts/docs-create.js",
"docs:edit": "node scripts/docs-edit.js",
"docs:add-placeholders": "node scripts/add-placeholders.js",
"build:pytest:image": "docker build -t influxdata/docs-pytest:latest -f Dockerfile.pytest .",
"build:agent:instructions": "node ./helper-scripts/build-agent-instructions.js",
"build:ts": "tsc --project tsconfig.json --outDir dist",

View File

@ -1,79 +0,0 @@
# Plan: Update InfluxDB 3 CLI Reference Documentation
## Automation and Process Improvements
### Immediate Improvements:
1. **Create CLI documentation sync script:**
```bash
# Script: /Users/ja/Documents/github/docs-v2/scripts/sync-cli-docs.sh
# - Extract help text from influxdb3 CLI at /Users/ja/.influxdb//influxdb3
# - Compare with existing docs
# - Generate report of differences
# - Auto-update basic command syntax
# - Real-time CLI verification capability established
```
2. **Establish documentation standards:**
- Standardize frontmatter across CLI docs
- Create templates for command documentation
- Define Enterprise vs Core content patterns using Hugo shortcodes
### Long-term Automation Strategy:
1. **CI/CD Integration:**
- Add GitHub Actions workflow to detect CLI changes
- Auto-generate CLI help extraction on new releases
- Create pull requests for documentation updates
2. **Release Process Integration:**
- Include CLI documentation review in release checklist
- Link release notes to specific CLI documentation updates
- Automated cross-referencing between release notes and CLI docs
3. **Content Management Improvements:**
- Use Hugo shortcodes for Enterprise-specific content
- Implement version-aware documentation
- Create shared content templates for common CLI patterns
## Phase 4: Validation and Testing
### Content accuracy verification:
- ✅ **CLI Access Available**: Direct verification via `influxdb3 --help` commands
- ✅ **Real-time Validation**: All commands and options verified against actual CLI output
- **Process**: Use `influxdb3 [command] --help` to validate documentation accuracy
- **Verification**: Cross-reference documented options with actual CLI behavior
### Documentation completeness check:
- Ensure all v3.2.0 features are documented
- Verify examples and use cases
- Check internal links and cross-references
## Suggested Recurring Process
### Pre-release (during development):
- Monitor CLI changes in pull requests
- Update documentation as features are added
- Maintain CLI help extraction automation
### At release (when tagging versions):
- Run automated CLI documentation sync
- Review and approve auto-generated updates
- Publish updated documentation
### Post-release (after release):
- Validate documentation accuracy
- Gather user feedback on CLI documentation
- Plan improvements for next cycle
## Related Documentation Paths
### InfluxDB 3 Product Documentation (affects CLI usage examples):
- `/content/influxdb3/core/write-data/influxdb3-cli.md`
- `/content/influxdb3/enterprise/write-data/influxdb3-cli.md`
- `/content/shared/influxdb3-write-guides/influxdb3-cli.md`
### Admin Documentation (affects retention and license features):
- `/content/influxdb3/core/admin/`
- `/content/influxdb3/enterprise/admin/`
- `/content/influxdb3/enterprise/admin/license.md`
This plan ensures comprehensive documentation updates for v3.2.0 while establishing sustainable processes for future releases.

View File

@ -0,0 +1,108 @@
# Add Placeholders Script
Automatically adds placeholder syntax to code blocks and placeholder descriptions in markdown files.
## What it does
This script finds UPPERCASE placeholders in code blocks and:
1. **Adds `{ placeholders="PATTERN1|PATTERN2" }` attribute** to code block fences
2. **Wraps placeholder descriptions** with `{{% code-placeholder-key %}}` shortcodes
## Usage
### Direct usage
```bash
# Process a single file
node scripts/add-placeholders.js <file.md>
# Dry run to preview changes
node scripts/add-placeholders.js <file.md> --dry
# Example
node scripts/add-placeholders.js content/influxdb3/enterprise/admin/upgrade.md
```
### Using npm script
```bash
# Process a file
yarn docs:add-placeholders <file.md>
# Dry run
yarn docs:add-placeholders <file.md> --dry
```
## Example transformations
### Before
````markdown
```bash
influxdb3 query \
--database SYSTEM_DATABASE \
--token ADMIN_TOKEN \
"SELECT * FROM system.version"
```
Replace the following:
- **`SYSTEM_DATABASE`**: The name of your system database
- **`ADMIN_TOKEN`**: An admin token with read permissions
````
### After
````markdown
```bash { placeholders="ADMIN_TOKEN|SYSTEM_DATABASE" }
influxdb3 query \
--database SYSTEM_DATABASE \
--token ADMIN_TOKEN \
"SELECT * FROM system.version"
```
Replace the following:
- {{% code-placeholder-key %}}`SYSTEM_DATABASE`{{% /code-placeholder-key %}}: The name of your system database
- {{% code-placeholder-key %}}`ADMIN_TOKEN`{{% /code-placeholder-key %}}: An admin token with read permissions
````
## How it works
### Placeholder detection
The script automatically detects UPPERCASE placeholders in code blocks using these rules:
- **Pattern**: Matches words with 2+ characters, all uppercase, can include underscores
- **Excludes common words**: HTTP verbs (GET, POST), protocols (HTTP, HTTPS), SQL keywords (SELECT, FROM), etc.
### Code block processing
1. Finds all code blocks (including indented ones)
2. Extracts UPPERCASE placeholders
3. Adds `{ placeholders="..." }` attribute to the fence line
4. Preserves indentation and language identifiers
### Description wrapping
1. Detects "Replace the following:" sections
2. Wraps placeholder descriptions matching `- **`PLACEHOLDER`**: description`
3. Preserves indentation and formatting
4. Skips already-wrapped descriptions
## Options
- `--dry` or `-d`: Preview changes without modifying files
## Notes
- The script is idempotent - running it multiple times on the same file won't duplicate syntax
- Preserves existing `placeholders` attributes in code blocks
- Works with both indented and non-indented code blocks
- Handles multiple "Replace the following:" sections in a single file
## Related documentation
- [DOCS-SHORTCODES.md](../DOCS-SHORTCODES.md) - Complete shortcode reference
- [DOCS-CONTRIBUTING.md](../DOCS-CONTRIBUTING.md) - Placeholder conventions and style guidelines

238
scripts/add-placeholders.js Executable file
View File

@ -0,0 +1,238 @@
#!/usr/bin/env node
/**
* Add placeholder syntax to code blocks
*
* This script finds UPPERCASE placeholders in code blocks and:
* 1. Adds `{ placeholders="PATTERN1|PATTERN2" }` attribute to code blocks
* 2. Wraps placeholder descriptions with `{{% code-placeholder-key %}}`
*
* Usage:
* node scripts/add-placeholders.js <file.md>
* node scripts/add-placeholders.js content/influxdb3/enterprise/admin/upgrade.md
*/
import { readFileSync, writeFileSync } from 'fs';
import { parseArgs } from 'node:util';
// Parse command-line arguments
const { positionals } = parseArgs({
allowPositionals: true,
options: {
dry: {
type: 'boolean',
short: 'd',
default: false,
},
},
});
if (positionals.length === 0) {
console.error('Usage: node scripts/add-placeholders.js <file.md> [--dry]');
console.error(
'Example: node scripts/add-placeholders.js content/influxdb3/enterprise/admin/upgrade.md'
);
process.exit(1);
}
const filePath = positionals[0];
const isDryRun = process.argv.includes('--dry') || process.argv.includes('-d');
/**
* Extract UPPERCASE placeholders from a code block
* @param {string} code - Code block content
* @returns {string[]} Array of unique placeholders
*/
function extractPlaceholders(code) {
// Match UPPERCASE words (at least 2 chars, can include underscores)
const placeholderPattern = /\b[A-Z][A-Z0-9_]{1,}\b/g;
const matches = code.match(placeholderPattern) || [];
// Remove duplicates and common words that aren't placeholders
const excludeWords = new Set([
'GET',
'POST',
'PUT',
'DELETE',
'PATCH',
'HEAD',
'OPTIONS',
'HTTP',
'HTTPS',
'URL',
'API',
'CLI',
'JSON',
'YAML',
'TOML',
'SELECT',
'FROM',
'WHERE',
'AND',
'OR',
'NOT',
'NULL',
'TRUE',
'FALSE',
'ERROR',
'WARNING',
'INFO',
'DEBUG',
]);
return [...new Set(matches)].filter((word) => !excludeWords.has(word)).sort();
}
/**
* Add placeholders attribute to a code block
* @param {string} codeBlock - Code block with fence
* @param {string} indent - Leading whitespace from fence line
* @returns {string} Code block with placeholders attribute
*/
function addPlaceholdersAttribute(codeBlock, indent = '') {
const lines = codeBlock.split('\n');
const fenceLine = lines[0];
const codeContent = lines.slice(1, -1).join('\n');
// Check if already has placeholders attribute
if (fenceLine.includes('placeholders=')) {
return codeBlock;
}
// Extract placeholders from code
const placeholders = extractPlaceholders(codeContent);
if (placeholders.length === 0) {
return codeBlock;
}
// Extract language from fence (handle indented fences)
const langMatch = fenceLine.match(/^\s*```(\w+)?/);
const lang = langMatch && langMatch[1] ? langMatch[1] : '';
// Build new fence line with placeholders attribute
const placeholdersStr = placeholders.join('|');
const newFenceLine = lang
? `${indent}\`\`\`${lang} { placeholders="${placeholdersStr}" }`
: `${indent}\`\`\` { placeholders="${placeholdersStr}" }`;
return [newFenceLine, ...lines.slice(1)].join('\n');
}
/**
* Wrap placeholder descriptions with code-placeholder-key shortcode
* @param {string} line - Line potentially containing placeholder description
* @returns {string} Line with shortcode wrapper if placeholder found
*/
function wrapPlaceholderDescription(line) {
// Match patterns like "- **`PLACEHOLDER`**: description" or " - **`PLACEHOLDER`**: description"
const pattern = /^(\s*-\s*)\*\*`([A-Z][A-Z0-9_]+)`\*\*(:\s*)/;
const match = line.match(pattern);
if (!match) {
return line;
}
// Check if already wrapped
if (line.includes('{{% code-placeholder-key %}}')) {
return line;
}
const prefix = match[1];
const placeholder = match[2];
const suffix = match[3];
const description = line.substring(match[0].length);
return `${prefix}{{% code-placeholder-key %}}\`${placeholder}\`{{% /code-placeholder-key %}}${suffix}${description}`;
}
/**
* Process markdown content
* @param {string} content - Markdown content
* @returns {string} Processed content
*/
function processMarkdown(content) {
const lines = content.split('\n');
const result = [];
let inCodeBlock = false;
let codeBlockLines = [];
let inReplaceSection = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
// Track "Replace the following:" sections
if (line.trim().match(/^Replace the following:?$/i)) {
inReplaceSection = true;
result.push(line);
continue;
}
// Exit replace section on non-list-item line (but allow empty lines within list)
if (
inReplaceSection &&
line.trim() !== '' &&
!line.trim().startsWith('-') &&
!line.match(/^#{1,6}\s/)
) {
inReplaceSection = false;
}
// Handle code blocks (including indented)
if (line.trim().startsWith('```')) {
if (!inCodeBlock) {
// Start of code block
inCodeBlock = true;
codeBlockLines = [line];
} else {
// End of code block
codeBlockLines.push(line);
const codeBlock = codeBlockLines.join('\n');
const indent = line.match(/^(\s*)/)[1];
const processedBlock = addPlaceholdersAttribute(codeBlock, indent);
result.push(processedBlock);
inCodeBlock = false;
codeBlockLines = [];
}
} else if (inCodeBlock) {
// Inside code block
codeBlockLines.push(line);
} else if (inReplaceSection) {
// Process placeholder descriptions
result.push(wrapPlaceholderDescription(line));
} else {
// Regular line
result.push(line);
}
}
return result.join('\n');
}
/**
* Main function
*/
function main() {
try {
// Read file
const content = readFileSync(filePath, 'utf-8');
// Process content
const processedContent = processMarkdown(content);
if (isDryRun) {
console.log('=== DRY RUN - Changes that would be made ===\n');
console.log(processedContent);
} else {
// Write back to file
writeFileSync(filePath, processedContent, 'utf-8');
console.log(`✓ Updated ${filePath}`);
console.log('Added placeholder syntax to code blocks and descriptions');
}
} catch (error) {
console.error(`Error: ${error.message}`);
process.exit(1);
}
}
main();

File diff suppressed because it is too large Load Diff

249
scripts/docs-edit.js Executable file
View File

@ -0,0 +1,249 @@
#!/usr/bin/env node
/**
* Documentation file opener
* Opens existing documentation pages in your default editor
*
* Usage:
* yarn docs:edit <url>
* yarn docs:edit https://docs.influxdata.com/influxdb3/core/admin/databases/
* yarn docs:edit /influxdb3/core/admin/databases/
*/
import { parseArgs } from 'node:util';
import process from 'node:process';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { existsSync, readFileSync } from 'fs';
import { spawn } from 'child_process';
import { parseDocumentationURL, urlToFilePaths } from './lib/url-parser.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Repository root
const REPO_ROOT = join(__dirname, '..');
// Colors for console output
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
red: '\x1b[31m',
cyan: '\x1b[36m',
};
/**
* Print colored output
*/
function log(message, color = 'reset') {
console.log(`${colors[color]}${message}${colors.reset}`);
}
/**
* Parse command line arguments
*/
function parseArguments() {
const { values, positionals } = parseArgs({
options: {
help: { type: 'boolean', default: false },
list: { type: 'boolean', default: false },
},
allowPositionals: true,
});
// First positional argument is the URL
if (positionals.length > 0 && !values.url) {
values.url = positionals[0];
}
return values;
}
/**
* Print usage information
*/
function printUsage() {
console.log(`
${colors.bright}Documentation File Opener${colors.reset}
${colors.bright}Usage:${colors.reset}
yarn docs:edit <url> Open page in editor
yarn docs:edit --list <url> List matching files without opening
${colors.bright}Arguments:${colors.reset}
<url> Documentation URL or path
${colors.bright}Options:${colors.reset}
--list List matching files without opening
--help Show this help message
${colors.bright}Examples:${colors.reset}
# Open with full URL
yarn docs:edit https://docs.influxdata.com/influxdb3/core/admin/databases/
# Open with path only
yarn docs:edit /influxdb3/core/admin/databases/
# List files without opening
yarn docs:edit --list /influxdb3/core/admin/databases/
${colors.bright}Notes:${colors.reset}
- Opens files in your default editor (set via EDITOR environment variable)
- If multiple files exist (e.g., shared content variants), opens all of them
- Falls back to VS Code if EDITOR is not set
`);
}
/**
* Find matching files for a URL
*/
function findFiles(url) {
try {
// Parse URL
const parsed = parseDocumentationURL(url);
log(`\n🔍 Analyzing URL: ${url}`, 'bright');
log(` Product: ${parsed.namespace}/${parsed.product || 'N/A'}`, 'cyan');
log(` Section: ${parsed.section || 'N/A'}`, 'cyan');
// Get potential file paths
const potentialPaths = urlToFilePaths(parsed);
const foundFiles = [];
for (const relativePath of potentialPaths) {
const fullPath = join(REPO_ROOT, relativePath);
if (existsSync(fullPath)) {
foundFiles.push(relativePath);
}
}
return { parsed, foundFiles };
} catch (error) {
log(`\n✗ Error parsing URL: ${error.message}`, 'red');
process.exit(1);
}
}
/**
* Check if file uses shared content
*/
function checkSharedContent(filePath) {
const fullPath = join(REPO_ROOT, filePath);
if (!existsSync(fullPath)) {
return null;
}
const content = readFileSync(fullPath, 'utf8');
// Check for source: frontmatter
const sourceMatch = content.match(/^source:\s*(.+)$/m);
if (sourceMatch) {
const sourcePath = sourceMatch[1].trim();
return `content${sourcePath}`;
}
return null;
}
/**
* Open files in editor
*/
function openInEditor(files) {
// Determine editor
const editor = process.env.EDITOR || 'code';
log(`\n📝 Opening ${files.length} file(s) in ${editor}...`, 'bright');
// Convert to absolute paths
const absolutePaths = files.map((f) => join(REPO_ROOT, f));
// Spawn editor process
const child = spawn(editor, absolutePaths, {
stdio: 'inherit',
detached: false,
});
child.on('error', (error) => {
log(`\n✗ Failed to open editor: ${error.message}`, 'red');
log('\nTry setting the EDITOR environment variable:', 'yellow');
log(' export EDITOR=vim', 'cyan');
log(' export EDITOR=code', 'cyan');
log(' export EDITOR=nano', 'cyan');
process.exit(1);
});
child.on('close', (code) => {
if (code !== 0 && code !== null) {
log(`\n✗ Editor exited with code ${code}`, 'yellow');
}
});
}
/**
* Main entry point
*/
async function main() {
const options = parseArguments();
// Show help
if (options.help || !options.url) {
printUsage();
process.exit(0);
}
// Find files
const { parsed, foundFiles } = findFiles(options.url);
if (foundFiles.length === 0) {
log('\n✗ No files found for this URL', 'red');
log('\nThe page may not exist yet. To create new content, use:', 'yellow');
log(' yarn docs:create --url <url> --draft <draft-file>', 'cyan');
process.exit(1);
}
// Display found files
log('\n✓ Found files:', 'green');
const allFiles = new Set();
for (const file of foundFiles) {
allFiles.add(file);
log(`${file}`, 'cyan');
// Check for shared content
const sharedSource = checkSharedContent(file);
if (sharedSource) {
if (existsSync(join(REPO_ROOT, sharedSource))) {
allFiles.add(sharedSource);
log(
`${sharedSource} ${colors.yellow}(shared source)${colors.reset}`,
'cyan'
);
}
}
}
const filesToOpen = Array.from(allFiles);
// List only mode
if (options.list) {
log(`\n✓ Found ${filesToOpen.length} file(s)`, 'green');
process.exit(0);
}
// Open in editor
openInEditor(filesToOpen);
}
// Run if called directly
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch((error) => {
log(`\nFatal error: ${error.message}`, 'red');
console.error(error.stack);
process.exit(1);
});
}
export { findFiles, openInEditor };

View File

@ -16,6 +16,7 @@ import {
validatePath,
ensureDirectory,
} from './file-operations.js';
import { urlToFilePaths } from './url-parser.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
@ -54,68 +55,226 @@ export function loadProducts() {
}
/**
* Analyze content directory structure
* @param {string} basePath - Base path to analyze (e.g., 'content/influxdb3')
* @returns {object} Structure analysis
* Extract product mentions from draft content
* @param {string} content - Draft content to analyze
* @param {object} products - Products map from loadProducts()
* @returns {string[]} Array of product keys mentioned
*/
export function analyzeStructure(basePath = 'content/influxdb3') {
const fullPath = join(REPO_ROOT, basePath);
export function extractProductMentions(content, products) {
const mentioned = new Set();
const contentLower = content.toLowerCase();
if (!existsSync(fullPath)) {
return { sections: [], existingPaths: [], siblingWeights: {} };
}
// Product name patterns to search for
const patterns = {
influxdb3_core: [
'influxdb 3 core',
'influxdb3 core',
'influxdb core',
'core version',
],
influxdb3_enterprise: [
'influxdb 3 enterprise',
'influxdb3 enterprise',
'influxdb enterprise',
'enterprise version',
],
influxdb3_cloud_dedicated: [
'cloud dedicated',
'influxdb cloud dedicated',
'dedicated cluster',
],
influxdb3_cloud_serverless: [
'cloud serverless',
'influxdb cloud serverless',
'serverless',
],
influxdb3_clustered: ['clustered', 'influxdb clustered', 'kubernetes'],
influxdb_cloud: ['influxdb cloud', 'influxdb 2 cloud'],
influxdb_v2: ['influxdb 2', 'influxdb v2', 'influxdb 2.x'],
influxdb_v1: ['influxdb 1', 'influxdb v1', 'influxdb 1.x'],
};
const sections = [];
const existingPaths = [];
const siblingWeights = {};
// Recursively walk directory
function walk(dir, relativePath = '') {
const entries = readdirSync(dir);
for (const entry of entries) {
const fullEntryPath = join(dir, entry);
const relativeEntryPath = join(relativePath, entry);
const stat = statSync(fullEntryPath);
if (stat.isDirectory()) {
// Track sections (top-level directories)
if (relativePath === '') {
sections.push(entry);
}
// Track all directory paths
existingPaths.push(join(basePath, relativeEntryPath));
// Recurse
walk(fullEntryPath, relativeEntryPath);
// Check for each product's patterns
for (const [productKey, productPatterns] of Object.entries(patterns)) {
for (const pattern of productPatterns) {
if (contentLower.includes(pattern)) {
mentioned.add(productKey);
break;
}
}
}
walk(fullPath);
return Array.from(mentioned);
}
// Analyze weights in common sections
const commonSections = [
'admin',
'write-data',
'query-data',
'reference',
'get-started',
];
for (const section of commonSections) {
const sectionPath = join(fullPath, 'core', section);
if (existsSync(sectionPath)) {
const weights = findSiblingWeights(sectionPath);
if (weights.length > 0) {
siblingWeights[`${basePath}/core/${section}/`] = weights;
/**
* Detect InfluxDB version and related tools from draft content
* @param {string} content - Draft content to analyze
* @returns {object} Version information
*/
export function detectInfluxDBVersion(content) {
const contentLower = content.toLowerCase();
// Version detection patterns
const versionInfo = {
version: null,
tools: [],
apis: [],
};
// Detect version
if (
contentLower.includes('influxdb 3') ||
contentLower.includes('influxdb3')
) {
versionInfo.version = '3.x';
// v3-specific tools
if (
contentLower.includes('influxdb3 ') ||
contentLower.includes('influxdb3-')
) {
versionInfo.tools.push('influxdb3 CLI');
}
if (contentLower.includes('influxctl')) {
versionInfo.tools.push('influxctl');
}
if (contentLower.includes('/api/v3')) {
versionInfo.apis.push('/api/v3');
}
} else if (
contentLower.includes('influxdb 2') ||
contentLower.includes('influxdb v2')
) {
versionInfo.version = '2.x';
// v2-specific tools
if (contentLower.includes('influx ')) {
versionInfo.tools.push('influx CLI');
}
if (contentLower.includes('/api/v2')) {
versionInfo.apis.push('/api/v2');
}
} else if (
contentLower.includes('influxdb 1') ||
contentLower.includes('influxdb v1')
) {
versionInfo.version = '1.x';
// v1-specific tools
if (contentLower.includes('influx -')) {
versionInfo.tools.push('influx CLI (v1)');
}
if (contentLower.includes('influxd')) {
versionInfo.tools.push('influxd');
}
}
// Common tools across versions
if (contentLower.includes('telegraf')) {
versionInfo.tools.push('Telegraf');
}
return versionInfo;
}
/**
* Analyze content directory structure
* @param {string|string[]} basePaths - Base path(s) to analyze (e.g., 'content/influxdb3' or ['content/influxdb3', 'content/influxdb'])
* @returns {object} Structure analysis
*/
export function analyzeStructure(basePaths = 'content/influxdb3') {
// Normalize to array
const pathsArray = Array.isArray(basePaths) ? basePaths : [basePaths];
const allSections = new Set();
const allExistingPaths = [];
const siblingWeights = {};
// Analyze each base path
for (const basePath of pathsArray) {
const fullPath = join(REPO_ROOT, basePath);
if (!existsSync(fullPath)) {
continue;
}
// Recursively walk directory
function walk(dir, relativePath = '') {
try {
const entries = readdirSync(dir);
for (const entry of entries) {
const fullEntryPath = join(dir, entry);
const relativeEntryPath = join(relativePath, entry);
try {
const stat = statSync(fullEntryPath);
if (stat.isDirectory()) {
// Track product-level directories (first level under content/namespace/)
const pathParts = relativeEntryPath.split('/');
if (pathParts.length === 2) {
// This is a product directory (e.g., 'core', 'enterprise')
allSections.add(pathParts[1]);
}
// Track all directory paths
allExistingPaths.push(join(basePath, relativeEntryPath));
// Recurse
walk(fullEntryPath, relativeEntryPath);
}
} catch (error) {
// Skip files/dirs we can't access
continue;
}
}
} catch (error) {
// Skip directories we can't read
}
}
walk(fullPath);
// Analyze weights in common sections for all product directories
const commonSections = [
'admin',
'write-data',
'query-data',
'reference',
'get-started',
'plugins',
];
// Find all product directories (e.g., core, enterprise, cloud-dedicated)
try {
const productDirs = readdirSync(fullPath).filter((entry) => {
const fullEntryPath = join(fullPath, entry);
return (
existsSync(fullEntryPath) && statSync(fullEntryPath).isDirectory()
);
});
for (const productDir of productDirs) {
for (const section of commonSections) {
const sectionPath = join(fullPath, productDir, section);
if (existsSync(sectionPath)) {
const weights = findSiblingWeights(sectionPath);
if (weights.length > 0) {
siblingWeights[`${basePath}/${productDir}/${section}/`] = weights;
}
}
}
}
} catch (error) {
// Skip if we can't read directory
}
}
return {
sections: [...new Set(sections)].sort(),
existingPaths: existingPaths.sort(),
sections: [...allSections].sort(),
existingPaths: allExistingPaths.sort(),
siblingWeights,
};
}
@ -154,7 +313,7 @@ export function findSiblingWeights(dirPath) {
}
/**
* Prepare complete context for Claude analysis
* Prepare complete context for AI analysis
* @param {string} draftPath - Path to draft file
* @returns {object} Context object
*/
@ -165,8 +324,27 @@ export function prepareContext(draftPath) {
// Load products
const products = loadProducts();
// Analyze structure
const structure = analyzeStructure();
// Extract product mentions from draft
const mentionedProducts = extractProductMentions(draft.content, products);
// Detect InfluxDB version and tools
const versionInfo = detectInfluxDBVersion(draft.content);
// Determine which content paths to analyze based on version
let contentPaths = [];
if (versionInfo.version === '3.x') {
contentPaths = ['content/influxdb3'];
} else if (versionInfo.version === '2.x') {
contentPaths = ['content/influxdb'];
} else if (versionInfo.version === '1.x') {
contentPaths = ['content/influxdb/v1', 'content/enterprise_influxdb/v1'];
} else {
// Default: analyze all
contentPaths = ['content/influxdb3', 'content/influxdb'];
}
// Analyze structure for relevant paths
const structure = analyzeStructure(contentPaths);
// Build context
const context = {
@ -176,22 +354,38 @@ export function prepareContext(draftPath) {
existingFrontmatter: draft.frontmatter,
},
products,
productHints: {
mentioned: mentionedProducts,
suggested:
mentionedProducts.length > 0
? mentionedProducts
: Object.keys(products).filter(
(key) =>
key.startsWith('influxdb3_') || key.startsWith('influxdb_v')
),
},
versionInfo,
structure,
conventions: {
sharedContentDir: 'content/shared/',
menuKeyPattern: 'influxdb3_{product}',
menuKeyPattern: '{namespace}_{product}',
weightLevels: {
description: 'Weight ranges by level',
level1: '1-99',
level2: '101-199',
level3: '201-299',
level4: '301-399',
level1: '1-99 (top-level pages)',
level2: '101-199 (section landing pages)',
level3: '201-299 (detail pages)',
level4: '301-399 (sub-detail pages)',
},
namingRules: {
files: 'Use lowercase with hyphens (e.g., manage-databases.md)',
directories: 'Use lowercase with hyphens',
shared: 'Shared content in /content/shared/',
},
testing: {
codeblocks: 'Use pytest-codeblocks annotations for testable examples',
docker: 'Use compose.yaml services for testing code samples',
commands: `Version-specific CLIs: ${versionInfo.tools.join(', ') || 'detected from content'}`,
},
},
};
@ -375,3 +569,192 @@ export function suggestNextWeight(existingWeights, level = 3) {
// Return max + 1
return Math.max(...levelWeights) + 1;
}
/**
* Find file from parsed URL
* @param {object} parsedURL - Parsed URL from url-parser.js
* @returns {object|null} File information or null if not found
*/
export function findFileFromURL(parsedURL) {
const potentialPaths = urlToFilePaths(parsedURL);
for (const relativePath of potentialPaths) {
const fullPath = join(REPO_ROOT, relativePath);
if (existsSync(fullPath)) {
return {
path: relativePath,
fullPath,
exists: true,
};
}
}
// File doesn't exist, return first potential path for creation
return {
path: potentialPaths[0],
fullPath: join(REPO_ROOT, potentialPaths[0]),
exists: false,
};
}
/**
* Detect if a file uses shared content
* @param {string} filePath - Path to file (relative to repo root)
* @returns {string|null} Shared source path if found, null otherwise
*/
export function detectSharedContent(filePath) {
const fullPath = join(REPO_ROOT, filePath);
if (!existsSync(fullPath)) {
return null;
}
try {
const content = readFileSync(fullPath, 'utf8');
const parsed = matter(content);
if (parsed.data && parsed.data.source) {
return parsed.data.source;
}
} catch (error) {
// Can't parse, assume not shared
return null;
}
return null;
}
/**
* Find all files that reference a shared source
* @param {string} sourcePath - Path to shared content file (e.g., "/shared/influxdb3-admin/databases.md")
* @returns {string[]} Array of file paths that use this shared source
*/
export function findSharedContentVariants(sourcePath) {
const variants = [];
// Search content directories
const contentDirs = [
'content/influxdb3',
'content/influxdb',
'content/telegraf',
];
function searchDirectory(dir) {
if (!existsSync(dir)) {
return;
}
try {
const entries = readdirSync(dir);
for (const entry of entries) {
const fullPath = join(dir, entry);
const stat = statSync(fullPath);
if (stat.isDirectory()) {
searchDirectory(fullPath);
} else if (entry.endsWith('.md')) {
try {
const content = readFileSync(fullPath, 'utf8');
const parsed = matter(content);
if (parsed.data && parsed.data.source === sourcePath) {
// Convert to relative path from repo root
const relativePath = fullPath.replace(REPO_ROOT + '/', '');
variants.push(relativePath);
}
} catch (error) {
// Skip files that can't be parsed
continue;
}
}
}
} catch (error) {
// Skip directories we can't read
}
}
for (const contentDir of contentDirs) {
searchDirectory(join(REPO_ROOT, contentDir));
}
return variants;
}
/**
* Analyze an existing page
* @param {string} filePath - Path to file (relative to repo root)
* @returns {object} Page analysis
*/
export function analyzeExistingPage(filePath) {
const fullPath = join(REPO_ROOT, filePath);
if (!existsSync(fullPath)) {
throw new Error(`File not found: ${filePath}`);
}
const content = readFileSync(fullPath, 'utf8');
const parsed = matter(content);
const analysis = {
path: filePath,
fullPath,
content: parsed.content,
frontmatter: parsed.data,
isShared: false,
sharedSource: null,
variants: [],
};
// Check if this file uses shared content
if (parsed.data && parsed.data.source) {
analysis.isShared = true;
analysis.sharedSource = parsed.data.source;
// Find all variants that use the same shared source
analysis.variants = findSharedContentVariants(parsed.data.source);
}
return analysis;
}
/**
* Analyze multiple URLs and find their files
* @param {object[]} parsedURLs - Array of parsed URLs
* @returns {object[]} Array of URL analysis results
*/
export function analyzeURLs(parsedURLs) {
const results = [];
for (const parsedURL of parsedURLs) {
const fileInfo = findFileFromURL(parsedURL);
const result = {
url: parsedURL.url,
parsed: parsedURL,
exists: fileInfo.exists,
files: {
main: fileInfo.path,
isShared: false,
sharedSource: null,
variants: [],
},
};
if (fileInfo.exists) {
// Analyze existing page
try {
const analysis = analyzeExistingPage(fileInfo.path);
result.files.isShared = analysis.isShared;
result.files.sharedSource = analysis.sharedSource;
result.files.variants = analysis.variants;
} catch (error) {
console.error(`Error analyzing ${fileInfo.path}: ${error.message}`);
}
}
results.push(result);
}
return results;
}

216
scripts/lib/url-parser.js Normal file
View File

@ -0,0 +1,216 @@
/**
* URL parsing utilities for documentation scaffolding
* Parses docs.influxdata.com URLs to extract product, version, and path information
*/
import { basename } from 'path';
// Base URL pattern for InfluxData documentation
const DOCS_BASE_URL = 'docs.influxdata.com';
/**
* Parse a documentation URL to extract components
* @param {string} url - Full URL or path (e.g., "https://docs.influxdata.com/influxdb3/core/admin/databases/" or "/influxdb3/core/admin/databases/")
* @returns {object} Parsed URL components
*/
export function parseDocumentationURL(url) {
// Remove protocol and domain if present
let path = url;
if (url.includes(DOCS_BASE_URL)) {
const urlObj = new URL(url);
path = urlObj.pathname;
}
// Remove leading and trailing slashes
path = path.replace(/^\/+|\/+$/g, '');
// Split into parts
const parts = path.split('/').filter((p) => p.length > 0);
if (parts.length === 0) {
throw new Error('Invalid URL: no path components');
}
// First part is the namespace (influxdb3, influxdb, telegraf, etc.)
const namespace = parts[0];
// Determine product structure based on namespace
let product = null;
let section = null;
let pagePath = [];
let isSection = false;
if (namespace === 'influxdb3') {
// InfluxDB 3 structure: /influxdb3/{product}/{section}/{...path}
if (parts.length >= 2) {
product = parts[1]; // core, enterprise, cloud-dedicated, cloud-serverless, clustered, explorer
if (parts.length >= 3) {
section = parts[2]; // admin, write-data, query-data, reference, get-started, plugins
pagePath = parts.slice(3);
}
}
} else if (namespace === 'influxdb') {
// InfluxDB 2/1 structure: /influxdb/{version}/{section}/{...path}
if (parts.length >= 2) {
const secondPart = parts[1];
if (secondPart === 'cloud') {
product = 'cloud';
if (parts.length >= 3) {
section = parts[2];
pagePath = parts.slice(3);
}
} else if (secondPart.match(/^v\d/)) {
// v2.x or v1.x
product = secondPart;
if (parts.length >= 3) {
section = parts[2];
pagePath = parts.slice(3);
}
} else {
// Assume cloudless-v2 structure: /influxdb/{section}/{...path}
section = secondPart;
pagePath = parts.slice(2);
product = 'v2'; // default
}
}
} else if (namespace === 'telegraf') {
// Telegraf structure: /telegraf/{version}/{section}/{...path}
if (parts.length >= 2) {
product = parts[1];
if (parts.length >= 3) {
section = parts[2];
pagePath = parts.slice(3);
}
}
} else if (namespace === 'kapacitor' || namespace === 'chronograf') {
// Other products: /{product}/{version}/{section}/{...path}
if (parts.length >= 2) {
product = parts[1];
if (parts.length >= 3) {
section = parts[2];
pagePath = parts.slice(3);
}
}
}
// Determine if this is a section (directory) or single page
// Section URLs typically end with / or have no file extension
// Single page URLs typically end with a page name
if (pagePath.length === 0 && section) {
// URL points to section landing page
isSection = true;
} else if (pagePath.length > 0) {
const lastPart = pagePath[pagePath.length - 1];
// If last part looks like a directory (no dots), it's a section
isSection = !lastPart.includes('.');
}
return {
url,
namespace,
product,
section,
pagePath: pagePath.join('/'),
isSection,
fullPath: parts.join('/'),
};
}
/**
* Validate if a URL is a valid documentation URL
* @param {string} url - URL to validate
* @returns {boolean} True if valid documentation URL
*/
export function validateDocumentationURL(url) {
try {
const parsed = parseDocumentationURL(url);
return parsed.namespace && parsed.namespace.length > 0;
} catch (error) {
return false;
}
}
/**
* Convert parsed URL to potential file paths
* @param {object} parsedURL - Parsed URL from parseDocumentationURL()
* @returns {string[]} Array of potential file paths to check
*/
export function urlToFilePaths(parsedURL) {
const { namespace, product, section, pagePath, isSection } = parsedURL;
const basePaths = [];
// Build base path based on namespace and product
let contentPath = `content/${namespace}`;
if (product) {
contentPath += `/${product}`;
}
if (section) {
contentPath += `/${section}`;
}
if (pagePath) {
contentPath += `/${pagePath}`;
}
if (isSection) {
// Section could be _index.md or directory with _index.md
basePaths.push(`${contentPath}/_index.md`);
basePaths.push(`${contentPath}.md`); // Sometimes sections are single files
} else {
// Single page
basePaths.push(`${contentPath}.md`);
basePaths.push(`${contentPath}/_index.md`); // Could still be a section
}
return basePaths;
}
/**
* Extract page name from URL for use in file names
* @param {object} parsedURL - Parsed URL from parseDocumentationURL()
* @returns {string} Suggested file name
*/
export function urlToFileName(parsedURL) {
const { pagePath, section } = parsedURL;
if (pagePath && pagePath.length > 0) {
// Use last part of page path
const parts = pagePath.split('/');
return parts[parts.length - 1];
} else if (section) {
// Use section name
return section;
}
return 'index';
}
/**
* Parse multiple URLs (comma-separated or array)
* @param {string|string[]} urls - URLs to parse
* @returns {object[]} Array of parsed URLs
*/
export function parseMultipleURLs(urls) {
let urlArray = [];
if (typeof urls === 'string') {
// Split by comma if string
urlArray = urls.split(',').map((u) => u.trim());
} else if (Array.isArray(urls)) {
urlArray = urls;
} else {
throw new Error('URLs must be a string or array');
}
return urlArray
.map((url) => {
try {
return parseDocumentationURL(url);
} catch (error) {
console.error(`Error parsing URL ${url}: ${error.message}`);
return null;
}
})
.filter((parsed) => parsed !== null);
}

View File

@ -0,0 +1,182 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Content Scaffolding Context",
"description": "Context data prepared by docs-create.js for AI analysis",
"type": "object",
"required": ["draft", "products", "productHints", "versionInfo", "structure", "conventions"],
"properties": {
"mode": {
"type": "string",
"enum": ["create", "edit"],
"description": "Operation mode: create new content or edit existing content"
},
"urls": {
"type": "array",
"description": "URL analysis results (for URL-based workflow)",
"items": {
"type": "object",
"properties": {
"url": { "type": "string" },
"parsed": {
"type": "object",
"properties": {
"namespace": { "type": "string" },
"product": { "type": "string" },
"section": { "type": "string" },
"pagePath": { "type": "string" },
"isSection": { "type": "boolean" }
}
},
"exists": { "type": "boolean" },
"files": {
"type": "object",
"properties": {
"main": { "type": "string" },
"isShared": { "type": "boolean" },
"sharedSource": { "type": ["string", "null"] },
"variants": {
"type": "array",
"items": { "type": "string" }
}
}
}
}
}
},
"existingContent": {
"type": "object",
"description": "Existing file contents (for edit mode)",
"patternProperties": {
".*": { "type": "string" }
}
},
"draft": {
"type": "object",
"description": "Draft content and metadata",
"required": ["path", "content", "existingFrontmatter"],
"properties": {
"path": {
"type": "string",
"description": "Path to the draft file"
},
"content": {
"type": "string",
"description": "Markdown content of the draft"
},
"existingFrontmatter": {
"type": "object",
"description": "Frontmatter from draft (if any)"
}
}
},
"products": {
"type": "object",
"description": "Available InfluxDB products from data/products.yml",
"patternProperties": {
".*": {
"type": "object",
"properties": {
"key": { "type": "string" },
"name": { "type": "string" },
"namespace": { "type": "string" },
"menu_category": { "type": "string" },
"versions": { "type": "array", "items": { "type": "string" } },
"latest": { "type": "string" }
}
}
}
},
"productHints": {
"type": "object",
"description": "Product recommendations from content analysis",
"required": ["mentioned", "suggested"],
"properties": {
"mentioned": {
"type": "array",
"description": "Products explicitly mentioned in draft content",
"items": { "type": "string" }
},
"suggested": {
"type": "array",
"description": "Products suggested based on analysis",
"items": { "type": "string" }
}
}
},
"versionInfo": {
"type": "object",
"description": "Detected InfluxDB version and tools",
"required": ["version", "tools", "apis"],
"properties": {
"version": {
"type": ["string", "null"],
"description": "Detected version (3.x, 2.x, 1.x, or null)"
},
"tools": {
"type": "array",
"description": "CLI tools and utilities mentioned",
"items": { "type": "string" }
},
"apis": {
"type": "array",
"description": "API endpoints mentioned",
"items": { "type": "string" }
}
}
},
"structure": {
"type": "object",
"description": "Repository structure analysis",
"required": ["sections", "existingPaths", "siblingWeights"],
"properties": {
"sections": {
"type": "array",
"description": "Available documentation sections",
"items": { "type": "string" }
},
"existingPaths": {
"type": "array",
"description": "All existing directory paths",
"items": { "type": "string" }
},
"siblingWeights": {
"type": "object",
"description": "Weight values from sibling pages by section",
"patternProperties": {
".*": {
"type": "array",
"items": { "type": "number" }
}
}
}
}
},
"conventions": {
"type": "object",
"description": "Documentation conventions and guidelines",
"required": ["sharedContentDir", "menuKeyPattern", "weightLevels", "namingRules", "testing"],
"properties": {
"sharedContentDir": {
"type": "string",
"description": "Directory for shared content"
},
"menuKeyPattern": {
"type": "string",
"description": "Pattern for menu keys"
},
"weightLevels": {
"type": "object",
"description": "Weight ranges by navigation level"
},
"namingRules": {
"type": "object",
"description": "File and directory naming conventions"
},
"testing": {
"type": "object",
"description": "Testing conventions for code samples"
}
}
}
}
}

View File

@ -0,0 +1,145 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Content Scaffolding Proposal",
"description": "Proposal generated by AI analysis for creating documentation files",
"type": "object",
"required": ["analysis", "files"],
"properties": {
"analysis": {
"type": "object",
"description": "Analysis results from AI agents",
"required": ["topic", "targetProducts", "section", "isShared"],
"properties": {
"topic": {
"type": "string",
"description": "Brief topic description"
},
"targetProducts": {
"type": "array",
"description": "Products this documentation applies to",
"items": { "type": "string" },
"minItems": 1
},
"section": {
"type": "string",
"description": "Documentation section (admin, write-data, query-data, etc.)"
},
"isShared": {
"type": "boolean",
"description": "Whether content should be shared across products"
},
"reasoning": {
"type": "string",
"description": "Explanation for structure decisions"
},
"styleReview": {
"type": "object",
"description": "Style compliance review from Style Agent",
"properties": {
"issues": {
"type": "array",
"items": { "type": "string" }
},
"recommendations": {
"type": "array",
"items": { "type": "string" }
}
}
},
"codeValidation": {
"type": "object",
"description": "Code sample validation from Coding Agent",
"properties": {
"tested": {
"type": "boolean",
"description": "Whether code samples were tested"
},
"tools": {
"type": "array",
"description": "Tools used in code samples",
"items": { "type": "string" }
}
}
}
}
},
"files": {
"type": "array",
"description": "Files to create",
"minItems": 1,
"items": {
"type": "object",
"required": ["path", "type"],
"properties": {
"path": {
"type": "string",
"description": "File path relative to repository root"
},
"type": {
"type": "string",
"enum": ["shared-content", "frontmatter-only"],
"description": "File type: shared-content (with body) or frontmatter-only (just frontmatter + source)"
},
"content": {
"type": "string",
"description": "Markdown content (for shared-content files)"
},
"frontmatter": {
"type": "object",
"description": "Frontmatter object (for frontmatter-only files)",
"required": ["title", "description", "menu", "weight"],
"properties": {
"title": {
"type": "string",
"description": "Page title"
},
"description": {
"type": "string",
"description": "SEO description"
},
"menu": {
"type": "object",
"description": "Menu configuration",
"patternProperties": {
".*": {
"type": "object",
"required": ["name"],
"properties": {
"name": { "type": "string" },
"parent": { "type": "string" }
}
}
}
},
"weight": {
"type": "number",
"description": "Sort weight"
},
"source": {
"type": "string",
"description": "Path to shared content file"
},
"related": {
"type": "array",
"description": "Related article URLs",
"items": { "type": "string" }
},
"alt_links": {
"type": "object",
"description": "Cross-product navigation links",
"patternProperties": {
".*": { "type": "string" }
}
}
}
}
}
}
},
"nextSteps": {
"type": "array",
"description": "Recommended next steps after file creation",
"items": { "type": "string" }
}
}
}

View File

@ -0,0 +1,136 @@
# Content Scaffolding Analysis Prompt (ChatGPT)
## Context
You are analyzing a documentation draft to generate an intelligent file structure proposal for the InfluxData documentation repository.
**Context file**: `.tmp/scaffold-context.json`
Read and analyze the context file, which contains:
- **draft**: The markdown content and any existing frontmatter
- **products**: Available InfluxDB products (Core, Enterprise, Cloud, etc.)
- **productHints**: Products mentioned or suggested based on content analysis
- **versionInfo**: Detected InfluxDB version (3.x, 2.x, 1.x) and tools
- **structure**: Repository structure, existing paths, and sibling weights
- **conventions**: Documentation conventions for naming, weights, and testing
## Your Tasks
### 1. Content Analysis
Analyze the draft content to determine:
- **Topic**: What is this documentation about?
- **Target audience**: Developers, administrators, beginners, or advanced users?
- **Documentation type**: Conceptual overview, how-to guide, reference, or tutorial?
- **Target products**: Which InfluxDB products does this apply to?
- Use `productHints.mentioned` and `productHints.suggested` from context
- Consider `versionInfo.version` (3.x, 2.x, or 1.x)
- **Section**: Which documentation section? (admin, write-data, query-data, reference, get-started, plugins)
### 2. Structure Decisions
Decide on the optimal file structure:
- **Shared vs Product-Specific**:
- Use shared content (`content/shared/`) when content applies broadly with minor variations
- Use product-specific when content differs significantly between products
- **Parent menu item**: What should be the navigation parent?
- **Weight**: Calculate appropriate weight based on `structure.siblingWeights`
- Weights are in ranges: 1-99 (top level), 101-199 (level 2), 201-299 (level 3)
### 3. Frontmatter Generation
For each file, create complete frontmatter with:
- **title**: Clear, SEO-friendly title
- **description**: Concise 1-2 sentence description for SEO
- **menu**: Proper menu structure with product key (pattern: `{namespace}_{product}`)
- **weight**: Sequential weight based on siblings
- **source**: (for frontmatter-only files) Path to shared content
- **related**: 3-5 relevant related articles from `structure.existingPaths`
- **alt_links**: Map equivalent pages across products for cross-product navigation
### 4. Code Sample Considerations
Based on `versionInfo`:
- Use version-specific CLI commands (influxdb3, influx, influxctl)
- Reference appropriate API endpoints (/api/v3, /api/v2)
- Note testing requirements from `conventions.testing`
### 5. Style Compliance
Follow conventions from `conventions.namingRules`:
- Files: Use lowercase with hyphens (e.g., `manage-databases.md`)
- Directories: Use lowercase with hyphens
- Shared content: Place in appropriate `/content/shared/` subdirectory
## Output Format
Generate a JSON proposal matching the schema in `scripts/schemas/scaffold-proposal.schema.json`.
**Required structure**:
```json
{
"analysis": {
"topic": "Brief topic description",
"targetProducts": ["core", "enterprise", "cloud-dedicated"],
"section": "admin",
"isShared": true,
"reasoning": "Why this structure makes sense",
"styleReview": {
"issues": [],
"recommendations": []
},
"codeValidation": {
"tested": false,
"tools": ["influxdb3 CLI", "influxctl"]
}
},
"files": [
{
"path": "content/shared/influxdb3-admin/topic-name.md",
"type": "shared-content",
"content": "{{ACTUAL_DRAFT_CONTENT}}"
},
{
"path": "content/influxdb3/core/admin/topic-name.md",
"type": "frontmatter-only",
"frontmatter": {
"title": "Page Title",
"description": "Page description",
"menu": {
"influxdb3_core": {
"name": "Nav Label",
"parent": "Parent Item"
}
},
"weight": 205,
"source": "/shared/influxdb3-admin/topic-name.md",
"related": [
"/influxdb3/core/path/to/related/"
],
"alt_links": {
"enterprise": "/influxdb3/enterprise/admin/topic-name/"
}
}
}
],
"nextSteps": [
"Review generated frontmatter",
"Test with: npx hugo server",
"Add product-specific variations if needed"
]
}
```
## Instructions
1. Read and parse `.tmp/scaffold-context.json`
2. Analyze the draft content thoroughly
3. Make structure decisions based on the analysis
4. Generate complete frontmatter for all files
5. Save the proposal to `.tmp/scaffold-proposal.json`
The proposal will be validated and used by `yarn docs:create --proposal .tmp/scaffold-proposal.json` to create the files.

View File

@ -0,0 +1,111 @@
# Content Scaffolding Analysis (GitHub Copilot)
Generate a documentation scaffolding proposal from the context file.
## Input
Read `.tmp/scaffold-context.json` which contains:
- `draft`: Documentation draft content and frontmatter
- `products`: Available InfluxDB products
- `productHints`: Suggested products based on content analysis
- `versionInfo`: Detected version (3.x/2.x/1.x) and tools
- `structure`: Repository structure and sibling weights
- `conventions`: Documentation standards
## Analysis
Determine:
1. **Topic** and **audience** from draft content
2. **Target products** from `productHints` and `versionInfo`
3. **Documentation section** (admin/write-data/query-data/reference/get-started/plugins)
4. **Shared vs product-specific** structure
5. **Weight** from `structure.siblingWeights` for the section
## File Structure
Generate files following these patterns:
### Shared Content Pattern
```
content/shared/{namespace}-{section}/{topic-name}.md
├─ content/{namespace}/{product}/{section}/{topic-name}.md (frontmatter only)
├─ content/{namespace}/{product}/{section}/{topic-name}.md (frontmatter only)
└─ ...
```
### Product-Specific Pattern
```
content/{namespace}/{product}/{section}/{topic-name}.md (full content)
```
## Frontmatter Template
For frontmatter-only files:
```yaml
---
title: Clear SEO title
description: 1-2 sentence description
menu:
{namespace}_{product}:
name: Nav label
parent: Parent item
weight: {calculated from siblings}
source: /shared/{namespace}-{section}/{topic-name}.md
related:
- /path/to/related1/
- /path/to/related2/
alt_links:
{product}: /path/to/equivalent/
---
```
## Code Samples
Based on `versionInfo`:
- **v3.x**: Use `influxdb3` CLI, `influxctl`, `/api/v3`
- **v2.x**: Use `influx` CLI, `/api/v2`
- **v1.x**: Use `influx` CLI (v1), `influxd`, InfluxQL
## Output
Generate JSON matching `scripts/schemas/scaffold-proposal.schema.json`:
```json
{
"analysis": {
"topic": "...",
"targetProducts": ["..."],
"section": "...",
"isShared": true/false,
"reasoning": "...",
"styleReview": {
"issues": [],
"recommendations": []
},
"codeValidation": {
"tested": false,
"tools": []
}
},
"files": [
{
"path": "content/...",
"type": "shared-content" | "frontmatter-only",
"content": "..." OR "frontmatter": {...}
}
],
"nextSteps": ["..."]
}
```
Save to: `.tmp/scaffold-proposal.json`
## Conventions
- **Files**: lowercase-with-hyphens.md
- **Menu keys**: `{namespace}_{product}` (e.g., `influxdb3_core`)
- **Weights**: 1-99 (top), 101-199 (level 2), 201-299 (level 3)
- **Shared content**: `content/shared/` subdirectories
- **Related links**: 3-5 contextually relevant articles
Begin analysis of `.tmp/scaffold-context.json`.