Last updated: Sep 1, 2025, 01:10 PM UTC

HTML Auto-Generation Implementation Plan

Executive Summary

This document outlines the implementation plan for automatically generating HTML files and updating the navigation menu whenever markdown (MD) files are created within the Sasha Studio application. The goal is to ensure that all documentation is immediately available in HTML format without requiring manual intervention via the "Publish HTML" button.

Current State Analysis

Existing HTML Generation Infrastructure

  1. Generation Script: claudecodeui/scripts/generate-spa-html.js

    • Supports full regeneration mode (all files)
    • Supports single-file mode with --single-file flag
    • Supports navigation update with --update-nav flag
    • Generates content-only HTML for SPA navigation
  2. Manual Trigger: "Publish HTML" button in FileTree.jsx

    • Calls /api/files/generate-reports endpoint
    • Runs full regeneration of all MD files
    • Shows toast notifications for user feedback
  3. Docker Startup: Initial HTML generation

    • Runs once during container initialization via docker-entrypoint.sh
    • Generates HTML for all existing MD files in /home/nodejs/all-project-files/docs/

MD File Creation Points

After thorough analysis of the codebase, MD files are created at the following explicit points:

1. Document Upload Endpoint ( Partially Implemented)

Location: server/routes/files.js:349
Endpoint: POST /api/projects/:projectName/upload-documents
Current Status: Already generates HTML but only for single file, not navigation

// Line 349: MD file creation
await fs.writeFile(convertedFilePath, enhancedMarkdown, 'utf-8');

// Lines 351-390: HTML generation (already implemented)
// Uses: node generate-spa-html.js --single-file

Issue: Doesn't update navigation menu when new file is added

2. Organization Document Processing ( Missing HTML Generation)

Location: server/services/document-processor.js:498
Function: processOrganizationDocuments()
Current Status: No HTML generation after MD creation

// Line 498: MD file creation
await fs.writeFile(outputPath, markdown);
// MISSING: HTML generation

Used By:

  • Profile setup completion (server/routes/profile.js:531)
  • Batch document processing

3. Workspace Setup Functions ( Partially Implemented)

Location: server/services/workspace-manager.js
Function: setupOrganizationWorkspace()

Multiple MD files created:

a. CLAUDE.md (Line 73) - No HTML generation

await fs.writeFile(claudeMdPath, claudeMd);
// MISSING: HTML generation

b. citations.md (Line 79) - Has HTML generation

await fs.writeFile(citationsPath, citationsTemplate);
// Lines 82-103: HTML generation implemented

c. README.md (Line 109) - Has HTML generation

await fs.writeFile(readmePath, localReadme);
// Lines 112-133: HTML generation implemented

d. index.md (Line 467) - No HTML generation

await fs.writeFile(indexPath, indexContent);
// MISSING: HTML generation

Additional Dynamic File Creation Points (Found During Implementation)

5. Claude CLI Tool Operations ( NO HTML Generation)

Location: Detection in server/claude-cli.js:42-100
WebSocket Event: document-created sent at line 540
Current Status: System detects when Claude creates/edits .md files but NO HTML generation occurs

When users interact with Claude in the chat interface, Claude can create or edit markdown files using:

  • Write tool: Creates new .md files
  • Edit tool: Modifies existing .md files
  • MultiEdit tool: Makes multiple edits to .md files

The system already:

  • Detects these operations via detectDocumentOperation() function
  • Sends WebSocket notifications to frontend
  • Shows toast notifications to users
  • BUT DOES NOT GENERATE HTML FILES

This is a critical gap because users expect documentation created by Claude to be immediately available in the Knowledge panel.

Implementation Strategy

Phase 1: Create Shared HTML Generation Service

Create a centralized service to handle HTML generation consistently across all MD file creation points.

New File: server/services/html-generator.js

import path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

/**
 * Generate HTML for a single markdown file
 * @param {string} mdFilePath - Absolute path to the markdown file
 * @param {string} workspacePath - Root workspace path
 * @param {boolean} updateNav - Whether to update navigation (default: true)
 * @returns {Promise<boolean>} - Success status
 */
export async function generateHtmlForSingleFile(mdFilePath, workspacePath, updateNav = true) {
  const scriptPath = process.env.RUNNING_IN_DOCKER === 'true' 
    ? '/app/scripts/generate-spa-html.js'
    : path.join(process.cwd(), 'claudecodeui/scripts/generate-spa-html.js');
  
  const docsPath = path.join(workspacePath, 'docs');
  const relativePath = path.relative(docsPath, mdFilePath);
  
  try {
    console.log(`πŸ”¨ Generating HTML for: ${relativePath}`);
    
    // Build command with appropriate flags
    let command = `node "${scriptPath}" --single-file "${relativePath}"`;
    if (updateNav) {
      command += ' --update-nav';
    }
    
    const { stdout, stderr } = await execAsync(command);
    
    if (stderr) {
      console.warn('⚠️ HTML generation warnings:', stderr);
    }
    
    console.log(`βœ… Generated HTML for: ${relativePath}`);
    return true;
  } catch (error) {
    console.error(`❌ HTML generation failed for ${relativePath}:`, error.message);
    return false;
  }
}

/**
 * Generate HTML for multiple markdown files
 * @param {string[]} mdFilePaths - Array of absolute paths to markdown files
 * @param {string} workspacePath - Root workspace path
 * @returns {Promise<{success: number, failed: number}>} - Generation statistics
 */
export async function generateHtmlForMultipleFiles(mdFilePaths, workspacePath) {
  let success = 0;
  let failed = 0;
  
  // Process files sequentially to avoid overwhelming the system
  for (const mdFilePath of mdFilePaths) {
    const result = await generateHtmlForSingleFile(
      mdFilePath, 
      workspacePath, 
      false // Don't update nav for each file
    );
    
    if (result) {
      success++;
    } else {
      failed++;
    }
  }
  
  // Update navigation once after all files are processed
  if (success > 0) {
    await updateNavigationMenu(workspacePath);
  }
  
  return { success, failed };
}

/**
 * Update the navigation menu after file changes
 * @param {string} workspacePath - Root workspace path
 * @returns {Promise<boolean>} - Success status
 */
export async function updateNavigationMenu(workspacePath) {
  const scriptPath = process.env.RUNNING_IN_DOCKER === 'true' 
    ? '/app/scripts/generate-spa-html.js'
    : path.join(process.cwd(), 'claudecodeui/scripts/generate-spa-html.js');
  
  try {
    console.log('🧭 Updating navigation menu...');
    
    // Run full generation to rebuild navigation
    const { stdout, stderr } = await execAsync(`node "${scriptPath}"`);
    
    if (stderr) {
      console.warn('⚠️ Navigation update warnings:', stderr);
    }
    
    console.log('βœ… Navigation menu updated');
    return true;
  } catch (error) {
    console.error('❌ Navigation update failed:', error.message);
    return false;
  }
}

Phase 2: Update Document Processor

File: server/services/document-processor.js

Add HTML generation after MD file creation:

// At the top of the file
import { generateHtmlForSingleFile } from './html-generator.js';

// After line 498
await fs.writeFile(outputPath, markdown);

// ADD: Generate HTML for the converted document
await generateHtmlForSingleFile(outputPath, workspacePath);

console.log(`βœ… Generated HTML for converted document: ${sanitizedName}`);

Phase 3: Update Workspace Manager

File: server/services/workspace-manager.js

Add HTML generation for missing files:

// At the top of the file
import { generateHtmlForSingleFile, generateHtmlForMultipleFiles } from './html-generator.js';

// After line 73 (CLAUDE.md)
await fs.writeFile(claudeMdPath, claudeMd);
// ADD: Generate HTML
await generateHtmlForSingleFile(claudeMdPath, workspacePath, false);

// After line 467 (index.md)
await fs.writeFile(indexPath, indexContent);
// ADD: Generate HTML
await generateHtmlForSingleFile(indexPath, workspacePath, false);

// At the end of setupOrganizationWorkspace function
// ADD: Update navigation after all files are created
await updateNavigationMenu(workspacePath);

Phase 4: Refactor Upload Endpoint

File: server/routes/files.js

Refactor to use the shared service and ensure navigation updates:

// At the top of the file
import { generateHtmlForSingleFile } from '../services/html-generator.js';

// Replace lines 351-390 with:
// Generate HTML for the converted markdown
const docsPath = path.join(workspacePath, 'docs');
await generateHtmlForSingleFile(
  convertedFilePath, 
  workspacePath,
  true // Update navigation for new uploads
);

console.log(`βœ… Generated HTML with navigation update for: ${mdFilename}`);

Phase 5: Handle Claude-Created Files

File: server/claude-cli.js

Add HTML generation when Claude creates or edits markdown files:

// At the top of the file (with other imports)
import { generateHtmlForSingleFile } from './services/html-generator.js';

// After line 540 (where WebSocket notification is sent)
if (documentOperation) {
  // Also generate HTML for the newly created/edited markdown file
  const workspacePath = path.join(process.env.HOME, 'projects', sessionProjectName || 'company-search');
  
  // Trigger HTML generation asynchronously (don't block Claude's response)
  generateHtmlForSingleFile(
    documentOperation.filePath,
    workspacePath,
    true // Update navigation for Claude-created files
  ).then(() => {
    console.log(`βœ… Generated HTML for Claude-created file: ${documentOperation.filePath}`);
  }).catch(err => {
    console.error(`❌ Failed to generate HTML for: ${documentOperation.filePath}`, err);
    // Don't throw - this is a non-critical enhancement
  });
  
  // Continue with WebSocket notification as before
  ws.send(JSON.stringify({
    type: 'document-created',
    data: documentOperation
  }));
}

This ensures that whenever Claude creates or modifies a markdown file through the chat interface, the corresponding HTML is automatically generated and the navigation menu is updated.

Navigation Menu Update Strategy

The navigation menu is built by scanning all MD files in the docs directory. The update strategy:

  1. Single File Addition: Use --update-nav flag to rebuild navigation
  2. Batch Operations: Update navigation once after all files are processed
  3. Menu Structure: Automatically organized by directory structure
  4. Special Handling: README.md files become section headers

Menu Generation Process

  1. Scan /home/nodejs/all-project-files/docs/ recursively
  2. Build hierarchical structure based on directories
  3. Generate navigation HTML in index.html
  4. Update all existing HTML files with new navigation

Error Handling

Graceful Degradation

  • If HTML generation fails, MD file creation continues
  • Log errors but don't block the main operation
  • User can still use "Publish HTML" button as fallback

Error Scenarios

  1. Script Not Found: Fall back to manual generation
  2. Permission Issues: Log and continue
  3. Disk Space: Alert user via toast notification
  4. Invalid Markdown: Generate partial HTML with error message

Performance Considerations

Optimization Strategies

  1. Single File Mode: Generate only the affected file's HTML
  2. Batch Processing: Group multiple files before updating navigation
  3. Async Processing: Non-blocking HTML generation
  4. Caching: Reuse parsed markdown when possible

Performance Metrics

  • Single file generation: ~100-200ms
  • Navigation update: ~500ms-1s (depends on total files)
  • Full regeneration: 2-5s for 100 files

Testing Plan

Unit Tests

  1. Test generateHtmlForSingleFile with various MD files
  2. Test navigation update with new files
  3. Test error handling scenarios
  4. Test batch processing

Integration Tests

  1. Upload single document β†’ Verify HTML generation
  2. Upload multiple documents β†’ Verify batch processing
  3. Complete organization setup β†’ Verify all MD files get HTML
  4. Create new workspace β†’ Verify initial HTML generation

Manual Testing Checklist

  • Upload PDF document - verify MD and HTML creation
  • Upload Word document - verify conversion and HTML
  • Upload multiple files - verify batch processing
  • Complete organization onboarding - verify all files
  • Ask Claude to create a new .md document - verify HTML generation
  • Ask Claude to edit an existing .md file - verify HTML regeneration
  • Ask Claude to use MultiEdit on .md file - verify HTML updates
  • Check navigation menu updates correctly for all scenarios
  • Verify "Publish HTML" button still works as fallback
  • Test error scenarios (disk full, permissions)
  • Verify toast notifications appear correctly
  • Confirm Claude-created docs appear in Knowledge panel immediately

Rollout Plan

Phase 1: Core Service Development

  • Implement shared HTML generation service
  • Add comprehensive logging
  • Create unit tests

Phase 2: Existing Endpoints Integration

  • Update document processor
  • Update workspace manager
  • Fix upload endpoint navigation

Phase 3: Claude Integration

  • Add HTML generation for Claude-created files
  • Test Claude Write/Edit/MultiEdit tools
  • Verify WebSocket notifications work

Phase 4: Testing & Deployment

  • Complete integration testing
  • Performance testing with large file sets
  • Deploy and monitor

Success Metrics

  1. Automation Rate: 100% of MD files get HTML generated
  2. Navigation Accuracy: Menu always reflects current file structure
  3. Performance: HTML generation < 500ms per file
  4. Error Rate: < 1% generation failures
  5. User Satisfaction: Reduced support requests about missing HTML

Future Enhancements

  1. Incremental Navigation Updates: Only update affected menu sections
  2. Background Queue: Process HTML generation in background queue
  3. Preview Mode: Generate preview HTML before saving MD
  4. Templating System: Custom HTML templates per document type
  5. Search Index: Auto-generate search index when creating HTML

Conclusion

This implementation plan ensures that every markdown file created in the Sasha Studio application automatically gets an HTML version generated with an updated navigation menu. The approach uses explicit triggers at file creation points rather than file watching, making it more predictable and efficient. The shared service pattern ensures consistency and maintainability across the codebase.